190 lines
4.0 KiB
C++
190 lines
4.0 KiB
C++
|
|
// ****************************************************************************
|
|
//
|
|
// VGA utilities
|
|
//
|
|
// ****************************************************************************
|
|
|
|
#include "include.h"
|
|
|
|
// convert image from 16-color to 8x8 attribute format
|
|
void Attr8Conv(u8* dst, u8* attr, const u8* src, int w, int h, const u8* pal)
|
|
{
|
|
int x, y, i, j, bestnum, best2num;
|
|
int hist[16];
|
|
u8 b, b2, b3, best, best2, bestcol, best2col;
|
|
const u8 *s;
|
|
u8 *d;
|
|
int ws = w/2;
|
|
int wd = w/8;
|
|
|
|
for (y = 0; y < h; y += 8)
|
|
{
|
|
for (x = 0; x < w; x += 8)
|
|
{
|
|
// clear histogram
|
|
memset(hist, 0, 16*sizeof(int));
|
|
|
|
// get histogram of this segment
|
|
s = src;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
b = s[0]; hist[b >> 4]++; hist[b & 0x0f]++;
|
|
b = s[1]; hist[b >> 4]++; hist[b & 0x0f]++;
|
|
b = s[2]; hist[b >> 4]++; hist[b & 0x0f]++;
|
|
b = s[3]; hist[b >> 4]++; hist[b & 0x0f]++;
|
|
s += ws;
|
|
}
|
|
|
|
// find 1st best pixel
|
|
best2 = 0;
|
|
best2num = 0;
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
if (hist[i] > best2num)
|
|
{
|
|
best2 = (u8)i;
|
|
best2num = hist[i];
|
|
}
|
|
}
|
|
|
|
// find 2nd best pixel
|
|
best = best2;
|
|
bestnum = 0;
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
if ((hist[i] > bestnum) && (i != best2))
|
|
{
|
|
best = (u8)i;
|
|
bestnum = hist[i];
|
|
}
|
|
}
|
|
|
|
// sort pixels, 'best' will be brighter (foreground) than 'best2' (background)
|
|
if (ColDist(best, 0) < ColDist(best2, 0))
|
|
{
|
|
i = best;
|
|
best = best2;
|
|
best2 = i;
|
|
}
|
|
|
|
// write attributes (best = foreground, best2 = background)
|
|
*attr++ = (best2 << 4) | best;
|
|
bestcol = pal[best];
|
|
best2col = pal[best2];
|
|
|
|
// write pixels
|
|
s = src;
|
|
d = dst;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
b3 = 0;
|
|
|
|
b = s[0];
|
|
b2 = pal[b >> 4];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B7 : 0;
|
|
b2 = pal[b & 0x0f];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B6 : 0;
|
|
|
|
b = s[1];
|
|
b2 = pal[b >> 4];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B5 : 0;
|
|
b2 = pal[b & 0x0f];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B4 : 0;
|
|
|
|
b = s[2];
|
|
b2 = pal[b >> 4];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B3 : 0;
|
|
b2 = pal[b & 0x0f];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B2 : 0;
|
|
|
|
b = s[3];
|
|
b2 = pal[b >> 4];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B1 : 0;
|
|
b2 = pal[b & 0x0f];
|
|
b3 |= (ColDist(b2, bestcol) < ColDist(b2, best2col)) ? B0 : 0;
|
|
|
|
*d = b3;
|
|
|
|
s += ws;
|
|
d += wd;
|
|
}
|
|
|
|
// next segment on the row
|
|
src += 4;
|
|
dst++;
|
|
}
|
|
|
|
// next row
|
|
src += ws*7;
|
|
dst += wd*7;
|
|
}
|
|
}
|
|
|
|
// convert image from 4-color to 2-plane format (width must be multiply of 8)
|
|
void Plane2Conv(u8* plane0, u8* plane1, const u8* src, int w, int h)
|
|
{
|
|
int i;
|
|
u8 b1, b2;
|
|
for (i = w/8*h; i > 0; i--)
|
|
{
|
|
b2 = *src++;
|
|
b1 = *src++;
|
|
*plane0++ = ((b2 & B6)<<1) | ((b2 & B4)<<2) | ((b2 & B2)<<3) | ((b2 & B0)<<4) |
|
|
((b1 & B6)>>3) | ((b1 & B4)>>2) | ((b1 & B2)>>1) | (b1 & B0);
|
|
*plane1++ = (b2 & B7) | ((b2 & B5)<<1) | ((b2 & B3)<<2) | ((b2 & B1)<<3) |
|
|
((b1 & B7)>>4) | ((b1 & B5)>>3) | ((b1 & B3)>>2) | ((b1 & B1)>>1);
|
|
}
|
|
}
|
|
|
|
// invert image
|
|
void ImgInvert(u8* dst, int num)
|
|
{
|
|
for (; num > 0; num--)
|
|
{
|
|
*dst = ~*dst;
|
|
dst++;
|
|
}
|
|
}
|
|
|
|
// decode unsigned number into ASCIIZ text buffer (returns number of digits)
|
|
int DecUNum(char* buf, u32 num)
|
|
{
|
|
// temporary buffer (max. 10 digits + 1 NUL)
|
|
char b[11];
|
|
|
|
// decode number
|
|
char* d = &b[10];
|
|
*d = 0;
|
|
int n = 0;
|
|
u32 k;
|
|
do {
|
|
k = num / 10;
|
|
num -= k*10;
|
|
d--;
|
|
*d = (char)(num + '0');
|
|
num = k;
|
|
n++;
|
|
} while (num != 0);
|
|
|
|
// copy number to destination buffer
|
|
memcpy(buf, d, n+1);
|
|
return n;
|
|
}
|
|
|
|
// decode signed number into ASCIIZ text buffer (returns number of digits)
|
|
int DecNum(char* buf, s32 num)
|
|
{
|
|
if (num >= 0) return DecUNum(buf, num);
|
|
|
|
num = -num;
|
|
*buf++ = '-';
|
|
return DecUNum(buf, num)+1;
|
|
}
|
|
|
|
// prepare image with white key transparency (copy and increment pixels)
|
|
void CopyWhiteImg(u8* dst, const u8* src, int num)
|
|
{
|
|
for (; num > 0; num--) *dst++ = *src++ + 1;
|
|
}
|