1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-04-10 23:41:35 +00:00

dd selectable color palettes and keep more precision for errDiv

This commit is contained in:
David Schmenk 2024-12-06 14:07:07 -08:00
parent 0df3fe544c
commit 6ae6a343b2
3 changed files with 277 additions and 108 deletions

View File

@ -14,72 +14,50 @@ const MAX_RGB = 512
const MIN_RGB = -256
byte[] ntscChroma
// Imperical 0-255 R G B
// Imperical 0-255 R G B
byte[] = 64, 51, 125 // BLUE
byte[] = 0, 108, 64 // GREEN
byte[] = 64, 77, 3 // BROWN
byte[] = 128, 20, 64 // RED
//// Calculated 0-255 R G B
//byte[] = 32, 46, 120 // BLUE
//byte[] = 8, 126, 32 // GREEN
//byte[] = 96, 82, 8 // BROWN
//byte[] = 120, 2, 96 // RED
// Calculated 0-255 R G B
byte[] = 32, 46, 120 // BLUE
byte[] = 8, 126, 32 // GREEN
byte[] = 96, 82, 8 // BROWN
byte[] = 120, 2, 96 // RED
// Idealized 0-255 R G B
byte[] = 64, 48, 128 // BLUE
byte[] = 16, 112, 64 // GREEN
byte[] = 64, 80, 0 // BROWN
byte[] = 112, 16, 64 // RED
byte[12] ntscCycle
byte[256+3] gamma
var rgbErr // Running color error array
byte errDiv = 2
byte errDiv = 3
var arg
def abs(n)
return n < 0 ?? -n :: n
end
def max(a, b)
return a < b ?? b :: a
end
def min(a, b)
return a < b ?? a :: b
end
def dist(x1, y1, z1, x2, y2, z2)#2
res[t_i32] xx, yy
res[t_i32] xx, yy
x2 = x2 - x1
y2 = y2 - y1
z2 = z2 - z1
loadi16(x2)
muli16(x2)
store32(@xx)
loadi16(y2)
muli16(y2)
store32(@yy)
loadi16(z2)
muli16(z2)
add32(@yy)
add32(@xx)
store32(@xx)
return xx:[0], xx:[1]
x2 = x2 - x1
y2 = y2 - y1
z2 = z2 - z1
loadi16(x2)
muli16(x2)
store32(@xx)
loadi16(y2)
muli16(y2)
store32(@yy)
loadi16(z2)
muli16(z2)
add32(@yy)
add32(@xx)
store32(@xx)
return xx:[0], xx:[1]
end
def dotprod(x1, y1, z1, x2, y2, z2)
return x1*x2 + y1*y2 + z1*z2
end
// Next error
def nextErr(rgb, closest)
return (rgb - closest + 1) / 2
end
def rgbClamp(rgb)
//return rgb > MAX_RGB ?? MAX_RGB :: (rgb < MIN_RGB ?? MIN_RGB :: rgb)
return rgb
end
def rgbPix(r, g, b, x, y)#0
def rgbPix(r, g, b, nr, ng, nb, x, y)#0
var errptr
var pr, pg, pb
var nr, ng, nb
var lr, lg, lb
var cr, cg, cb, cx
byte i
@ -103,19 +81,15 @@ def rgbPix(r, g, b, x, y)#0
pb = pb + ntscCycle[i+BLU]
next
pd:[0], pd:[1] = dist(r, g, b, pr, pg, pb)
// Look ahead in chroma cycle for possible better match
// Look ahead in chroma cycle for possible better match for next RGB pixel
i = ((x + 1) & 3) * 3
lr = pr - ntscCycle[i+RED] + ntscChroma[i+RED]
lg = pg - ntscCycle[i+GRN] + ntscChroma[i+GRN]
lb = pb - ntscCycle[i+BLU] + ntscChroma[i+BLU]
if errDiv
nr = r + (errptr=>[3+RED] + nextErr(r, lr)) / errDiv
ng = g + (errptr=>[3+GRN] + nextErr(g, lg)) / errDiv
nb = b + (errptr=>[3+BLU] + nextErr(b, lb)) / errDiv
else
nr = r
ng = g
nb = b
nr = nr + (errptr=>[3+RED] + r - lr) / errDiv
ng = ng + (errptr=>[3+GRN] + g - lg) / errDiv
nb = nb + (errptr=>[3+BLU] + b - lb) / errDiv
fin
nd:[0], nd:[1] = dist(nr, ng, nb, lr, lg, lb)
// Current 1/4 chroma color
@ -127,18 +101,18 @@ def rgbPix(r, g, b, x, y)#0
load32(@cd)
if islt32(@pd) and islt32(@nd)
// RGB better matched with current 1/4 chroma color
nr = nextErr(r, cr)
ng = nextErr(g, cg)
nb = nextErr(b, cb)
nr = r - cr
ng = g - cg
nb = b - cb
ntscCycle[i+RED] = ntscChroma[i+RED]
ntscCycle[i+GRN] = ntscChroma[i+GRN]
ntscCycle[i+BLU] = ntscChroma[i+BLU]
dhgrSet(x, y)
else
// RGB closer to black
nr = nextErr(r, pr)
ng = nextErr(g, pg)
nb = nextErr(b, pb)
nr = r - pr
ng = g - pg
nb = b - pb
ntscCycle[i+RED] = 0
ntscCycle[i+GRN] = 0
ntscCycle[i+BLU] = 0
@ -162,10 +136,11 @@ end
def rgbInit#0
var i
if not gamma
if not gamma[1]
for i = 0 to 255
loadi16(i)
muli16(i)
addi16(127)
divi16(255)
store32(@gamma + i)
next
@ -188,41 +163,8 @@ def rgbExit#0
dhgrMode(DHGR_TEXT_MODE)
end
def rgb3Spans(rs, gs, bs, re, ge, be, rm, gm, bm, y)#0
var i, j
memset(@ntscCycle, 0, 12)
for j = y to y + 2
for i = 0 to 63
rgbPix((i>>rs)|re, (i>>gs)|ge, (i>>bs)|be, i, j)
next
for i = 64 to 127
rgbPix(rm, gm, bm, i, j)
next
next
end
def rgbTest#0
var i
rgbInit
rgb3Spans(0,5,5, 0, 0, 0, 63, 0, 0, 0)
rgb3Spans(5,0,5, 0, 0, 0, 0,63, 0, 3)
rgb3Spans(5,5,0, 0, 0, 0, 0, 0,63, 6)
rgb3Spans(0,0,0, 0, 0, 0, 63,63,63, 9)
rgb3Spans(0,1,1, 0, 0, 0, 63,31,31, 12)
rgb3Spans(1,0,1, 0, 0, 0, 31,63,31, 15)
rgb3Spans(1,1,0, 0, 0, 0, 31,31,63, 18)
rgb3Spans(5,5,5, 16,16,16, 16,16,16, 21)
rgb3Spans(5,5,5, 32,32,32, 32,32,32, 24)
rgb3Spans(5,5,5, 48,48,48, 48,48,48, 27)
rgb3Spans(5,5,5, 63,63,63, 63,63,63, 30)
getc
rgbExit
end
def rgbImportExport(rgbfile, dhgrfile)#0
byte refnum, r, g, b
byte refnum, r, g, b, nxtr, nxtg, nxtb
var i, j
var rgbScanline, rgbptr
@ -234,12 +176,18 @@ def rgbImportExport(rgbfile, dhgrfile)#0
for j = 0 to 191
fileio:read(refnum, rgbScanline, 560 * 3)
rgbptr = rgbScanline
nxtr = gamma[rgbptr->RED]
nxtg = gamma[rgbptr->GRN]
nxtb = gamma[rgbptr->BLU]
for i = 0 to 559
r = gamma[rgbptr->RED]
g = gamma[rgbptr->GRN]
b = gamma[rgbptr->BLU]
r = nxtr
g = nxtg
b = nxtb
rgbptr = rgbptr + 3
rgbPix(r, g, b, i, j)
nxtr = gamma[rgbptr->RED]
nxtg = gamma[rgbptr->GRN]
nxtb = gamma[rgbptr->BLU]
rgbPix(r, g, b, nxtr, nxtg, nxtb, i, j)
next
if ^$C000 == $83
break
@ -261,11 +209,8 @@ arg = argNext(argFirst)
if ^arg
while ^(arg + 1) == '-'
when toupper(^(arg + 2))
is 'T' // Run color test
rgbTest
break
is 'L' // Use linear RGB transfer instead of gama
gamma = 1
gamma[1] = 1
break
is 'E' // Set error strength
if ^arg > 2
@ -275,6 +220,16 @@ if ^arg
fin
fin
break
is 'C' // Use calculated chroma values
for gamma = 0 to 11
ntscChroma[gamma] = ntscChroma[gamma + 12]
next
break
is 'I' // Use idealized chroma values
for gamma = 0 to 11
ntscChroma[gamma] = ntscChroma[gamma + 24]
next
break
wend
arg = argNext(arg)
loop

View File

@ -0,0 +1,214 @@
/*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FONT_WIDTH 32
#define FONT_HEIGHT 12
#define GLYPH_FIRST 32
#define GLYPH_LAST 127
#define GLYPH_COUNT (GLYPH_LAST-GLYPH_FIRST+1)
/*
* Bit reversals
*/
unsigned char clrSwap[256];
unsigned char clrRot[] = {0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,
0x01,0x03,0x05,0x07,0x09,0x0B,0x0D,0x0F};
void write_glyph(FILE *fp, int left, int top, int width, int height, int advance, unsigned char *buf, int pitch)
{
unsigned char glyphdef[5], *swapbuf;
int i;
glyphdef[0] = left;
glyphdef[1] = -top;
glyphdef[2] = (width + 3) / 4;
glyphdef[3] = height;
glyphdef[4] = advance;
fwrite(&glyphdef, 1, 5, fp);
swapbuf = malloc(pitch * height);
for (i = 0; i < pitch * height; i++)
swapbuf[i] = clrSwap[buf[i]];
buf = swapbuf;
while (height--)
{
fwrite(buf, 1, (width + 7) / 8, fp);
buf = buf + pitch;
}
free(swapbuf);
}
void write_font_file(char *filename, int glyph_width, int glyph_height)
{
FILE *fp;
unsigned char ch;
int c;
if ((fp = fopen(filename, "wb")))
{
ch = GLYPH_FIRST;
fwrite(&ch, 1, 1, fp);
ch = GLYPH_COUNT;
fwrite(&ch, 1, 1, fp);
ch = (glyph_width + 3) / 4;
fwrite(&ch, 1, 1, fp);
ch = glyph_height;
fwrite(&ch, 1, 1, fp);
for (c = GLYPH_FIRST; c <= GLYPH_LAST; c++)
{
#if 0
FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
write_glyph(fp,
face->glyph->bitmap_left,
face->glyph->bitmap_top,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
(face->glyph->advance.x + 0x40) >> 6,
face->glyph->bitmap.buffer,
face->glyph->bitmap.pitch);
#endif
}
fclose(fp);
}
}
/*
* Glyph render routines.
*/
void bitblt(int xorg, int yorg, int width, int height, unsigned char *srcbuf, int srcpitch, unsigned char *dstbuf, int dstpitch)
{
int i, j;
dstbuf = dstbuf + yorg * dstpitch;
width = (width + 7) / 8; // Width in bytes
for (j = 0; j < height; j++)
{
for (i = 0; i < width; i++)
dstbuf[i] = srcbuf[i];
srcbuf += srcpitch;
dstbuf += dstpitch;
}
}
void write_bitmap_file(char *filename, int glyph_width, int glyph_height)
{
int bitmap_top, bitmap_rows;
int c, glyph_base, glyph_byte_width, glyph_pitch;
unsigned char *glyph_buf, *bitmap_buf;
FILE *fp;
#if 0
glyph_base = glyph_height * 3 / 4 ; //+ 1;
glyph_width = glyph_width * 1.25;
glyph_byte_width = (glyph_width + 7) / 8;
glyph_pitch = GLYPH_COUNT * glyph_byte_width;
glyph_buf = malloc(glyph_pitch * glyph_height);
memset(glyph_buf, 0, glyph_pitch * glyph_height);
for (c = GLYPH_FIRST; c <= GLYPH_LAST; c++)
{
FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
bitmap_buf = face->glyph->bitmap.buffer,
bitmap_top = glyph_base - face->glyph->bitmap_top;
bitmap_rows = face->glyph->bitmap.rows;
if (bitmap_top < 0)
{
bitmap_rows += bitmap_top;
bitmap_buf = bitmap_buf - face->glyph->bitmap.pitch * bitmap_top;
bitmap_top = 0;
}
if (bitmap_top < glyph_height)
{
if (bitmap_top + bitmap_rows > glyph_height)
bitmap_rows = glyph_height - bitmap_top;
bitblt(0,
bitmap_top,
face->glyph->bitmap.width,
bitmap_rows,
bitmap_buf,
face->glyph->bitmap.pitch,
glyph_buf + (c - GLYPH_FIRST) * glyph_byte_width,
glyph_pitch);
}
else
printf("Glyph (%c) height: %d, top: %d, rows: %d Skipped!\n", c, glyph_height, face->glyph->bitmap_top, face->glyph->bitmap.rows);
}
if ((fp = fopen(filename, "wb")))
{
fprintf(fp, "P4\n%d\n%d\n", glyph_width * GLYPH_COUNT, glyph_height);
fwrite(glyph_buf, 1, glyph_pitch * glyph_height, fp);
fclose(fp);
}
#endif
}
void die(char *str)
{
fprintf(stderr,"error: %s\n", str);
exit(-1);
}
void load_iigs_file(char *filename)
{
FILE *fp;
char *fontdef;
char fontname[64];
int fontdefsize;
if ((fp = fopen(filename, "rb")))
{
fontdef = malloc(65536);
fontdefsize = fread(fontdef, 1, 65536, fp);
fclose(fp);
}
else
die("Unable to open IIGS font file");
memcpy(&fontname, fontdef + 1, fontdef[0]);
fontname[fontdef[0]] = '\0';
printf("Font name: %s\n", fontname);
}
int main(int argc, char **argv)
{
char *iigs_file, *font_file;
unsigned char *font_buf;
int glyph_width, glyph_height, font_pitch;
unsigned char bitReverse;
int i;
font_file = NULL;
if (argc > 1)
{
iigs_file = argv[1];
if (argc > 2)
font_file = argv[2];
if (argc > 3)
glyph_width = atoi(argv[3]);
else
glyph_width = FONT_WIDTH;
if (argc > 4)
glyph_height = atoi(argv[4]);
else
glyph_height = FONT_HEIGHT;
}
else
die( "Missing font file");
/*
* Bit/color reversal
*/
for (i = 0; i < 256; i++)
{
bitReverse = ((i & 0x01) << 7)
| ((i & 0x02) << 5)
| ((i & 0x04) << 3)
| ((i & 0x08) << 1)
| ((i & 0x10) >> 1)
| ((i & 0x20) >> 3)
| ((i & 0x40) >> 5)
| ((i & 0x80) >> 7);
clrSwap[i] = clrRot[bitReverse & 0x0F]
| (clrRot[bitReverse >> 4] << 4);
}
/*
* Load IIGS font file header.
*/
load_iigs_file(iigs_file);
write_bitmap_file(font_file, glyph_width, glyph_height);
//write_font_file(font_file, face, glyph_width, glyph_height);
return 0;
}

Binary file not shown.