Files
picovga-RGsB/_picovga/vga_util.cpp
2021-06-10 19:07:49 +02:00

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;
}