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:
parent
0df3fe544c
commit
6ae6a343b2
@ -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
|
||||
|
214
src/dhgr.tk/utils/gsfonconv.c
Normal file
214
src/dhgr.tk/utils/gsfonconv.c
Normal 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;
|
||||
}
|
||||
|
BIN
src/dhgr.tk/utils/samples/SHASTON.16.$C8
Normal file
BIN
src/dhgr.tk/utils/samples/SHASTON.16.$C8
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user