From 0df3fe544c0942eb5fa5f211db7114e5c7bc4da2 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Thu, 5 Dec 2024 21:33:28 -0800 Subject: [PATCH] Update to RGB24 and 32 bit distance calc --- images/apple/DCGR-RGB.PO | Bin 143360 -> 143360 bytes src/dhgr.tk/makefile | 6 +- src/dhgr.tk/test/fonttest.pla | 61 ++++++++++++++-- src/dhgr.tk/utils/dhgrrgb.pla | 131 +++++++++++++++++++--------------- src/dhgr.tk/utils/ttfconv.c | 6 +- 5 files changed, 134 insertions(+), 70 deletions(-) diff --git a/images/apple/DCGR-RGB.PO b/images/apple/DCGR-RGB.PO index dddb527e98d82ad9474b59df50061f6c7d113b27..04ae1e141af6e62df6f3e5b3a458866dee86129c 100755 GIT binary patch delta 978 zcmY+DU1$?&6o$|DWnx3A+cT~8hiKy(w-#YVFRHcJv>V%O7E2u3z_N=-1y{>}D5zCJ zX&muJ5aqLI1a}2*6m%DKl?E@oh-qpE(i-xEe>b8a2rB->U(otaRM3HE&ikJC%=x~X z*>}&g@1EzvJGXWq*`kkpaQkK+NUqd9^nl0_BkIWZODqS(e$S{!%sJ=}|JvIZUjI9N zem=e>jgGo8+Vb_A7CqUf#P|k%z$O3MMPZ&n-n#VUSmAc!$ERX0k4;?9XYHUxVM#!YBH)w{7EmT5uqPzV~GBLtDVt9{Y!uDjAW;cA;&psCl3eM?5yYz z4|j2-;Y+m4y|AOBVYZ`lcHWF3lgDe-zv#8Ms|2@rz4(ML4nXmGH*HOma6U16wEgS|`;{4QiNt>L2<+okz`3ohnhYdI0G@Ed|2&<8f5w^=q>TcJ&`4St98TRWi#!4Q00YU-fWtRwKpzzJ{?oC2r8 zSA;RP{KuSLEi=U;UCF%>j`ujyn%l& zXIR2TmIkUoHDFK=W&$G>iU9ifJ)QQBqn&R8p(vCZ#sHhGrR2 zMD&ljsda5yMMT77h;}2TNoMq$dVKhvd*8VUPbEBc_U+15E6bC4x3*-(HdQFf5EUb7 zcIPhxJS)~!T8YZ-`p(|iaNkgz{=Y(wB=x&gT>jfBhK(3;H|Ae8xNDQ`UJGd9lablTsg|IyK20=TO96Gl#_5D0i4~j_L^}J;P+?IH(uV8ohz@E%Xi; z*oOl+gk#*FaF;$sU%(aS8k9YSM(cXnPTRP!}gly_height = height glyph->gly_adv = adv if not base; base = glyph; fin + //glyph = glyph + gly_pixmap + //height = width * height - 1 + //for i = 0 to height + // width = glyph->[i] + // glyph->[i] = clrRot[width&$0F]|(clrRot[width>>4]<<4) + //next else if base; heaprelease(base); fin base = NULL @@ -84,11 +93,42 @@ def fontLoad(filename)#1 return numGlyphs end -def glyphStr(x, y, strptr)#2 +def pixGlyphStr(x, y, strptr)#2 + var glyph, left, top, fixX + byte i, ch, width, height + + fixX = x * 4 + for i = 1 to ^strptr + ch = ^(strptr + i) + if ch < 32 or ch > 127 + when ch + is '\n' + x = 0 + y = y + heightGlyph + break + is '\t' + x = x + (widthGlyph * 8) + break + wend + elsif (ch >= firstGlyph and ch < (firstGlyph + numGlyphs)) + glyph = fontGlyphs=>[ch - firstGlyph] + left = glyph=>gly_left + top = glyph=>gly_top + width = glyph->gly_width + height = glyph->gly_height + dcgrPixmap((x + left) / 4, y + top, width, height, glyph + gly_pixmap) + x = x + glyph->gly_adv + else + x = x + widthGlyph + fin + next + return x, y +end + +def bitGlyphStr(x, y, strptr)#2 var glyph, left, top byte i, ch, width, height - dhgrOp(OP_OR) for i = 1 to ^strptr ch = ^(strptr + i) if ch < 32 or ch > 127 @@ -103,11 +143,11 @@ def glyphStr(x, y, strptr)#2 wend elsif (ch >= firstGlyph and ch < (firstGlyph + numGlyphs)) glyph = fontGlyphs=>[ch - firstGlyph] - left = 0 // glyph=>gly_left + left = glyph=>gly_left top = glyph=>gly_top - width = glyph->gly_width + width = glyph->gly_width * 4 height = glyph->gly_height - dcgrPixmap(x + left, y + top, width, height, glyph + gly_pixmap) + dcgrBitmap(x + left, y + top, width, height, glyph + gly_pixmap) x = x + glyph->gly_adv else x = x + widthGlyph @@ -118,9 +158,16 @@ end arg = argNext(argFirst) dhgrMode(DHGR_COLOR_MODE) +dcgrColor(CLR_WHITE) +dhgrClearBl7(0, 0, SCR_WIDTH7, SCR_HEIGHT) +dcgrColor(CLR_BLACK) +dcgrStr(0, 0, "Wide Default Font Test") +dcgrFont(FONT_THIN) +dcgrStr(0, 8, "Thin Default Font Test") +dhgrOp(OP_XOR) while arg and ^arg fontLoad(arg) - xPen, yPen = glyphStr(xPen, yPen, "\nHello, world") + xPen, yPen = pixGlyphStr(xPen, yPen, "\nHello, world") arg = argNext(arg) loop getc diff --git a/src/dhgr.tk/utils/dhgrrgb.pla b/src/dhgr.tk/utils/dhgrrgb.pla index cd5f4a1..4c15a88 100644 --- a/src/dhgr.tk/utils/dhgrrgb.pla +++ b/src/dhgr.tk/utils/dhgrrgb.pla @@ -1,6 +1,7 @@ include "inc/cmdsys.plh" include "inc/args.plh" include "inc/fileio.plh" +include "inc/int32.plh" include "dhgr.tk/inc/dhgrlib.plh" include "dhgr.tk/inc/dhgrutils.plh" @@ -9,44 +10,24 @@ sysflags resxtxt1|reshgr1|resxhgr1 const RED = 0 const GRN = 1 const BLU = 2 -const RGB_MAX = 63 -const ERR_MAX = 32 -byte errDiv = 2 +const MAX_RGB = 512 +const MIN_RGB = -256 byte[] ntscChroma // Imperical 0-255 R G B -//byte[] = 64, 51, 127 // BLUE -//byte[] = 0, 108, 64 // GREEN -//byte[] = 64, 77, 1 // BROWN -//byte[] = 128, 20, 64 // RED -// Imperical 0-63 R G B -byte[] = 16, 12, 32 // BLUE -byte[] = 0, 28, 16 // GREEN -byte[] = 16, 20, 0 // BROWN -byte[] = 32, 4, 16 // RED +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-63 R G B -//byte[] = 8, 12, 30 // BLUE -//byte[] = 2, 32, 8 // GREEN -//byte[] = 24, 20, 2 // BROWN -//byte[] = 30, 0, 24 // RED -// Ideal/simplified 0-63 R G B -//byte[] = 16, 16, 32 // BLUE -//byte[] = 0, 32, 16 // GREEN -//byte[] = 16, 16, 0 // BROWN -//byte[] = 32, 0, 16 // RED -// Test 0-63 R G B -//byte[] = 12, 10, 24 // BLUE 872 -//byte[] = 8, 26, 16 // GREEN 996 -//byte[] = 20, 22, 8 // BROWN 872 -//byte[] = 24, 6, 16 // RED 868 byte[12] ntscCycle -byte[256] gamma +byte[256+3] gamma var rgbErr // Running color error array +byte errDiv = 2 var arg def abs(n) @@ -61,24 +42,48 @@ def min(a, b) return a < b ?? a :: b end -def dist(x1, y1, z1, x2, y2, z2) +def dist(x1, y1, z1, x2, y2, z2)#2 + res[t_i32] xx, yy + x2 = x2 - x1 y2 = y2 - y1 z2 = z2 - z1 - return x2*x2 + y2*y2 + z2*z2 + 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 var errptr var pr, pg, pb var nr, ng, nb + var lr, lg, lb var cr, cg, cb, cx - var pd, cd, nd byte i + res[t_i32] pd, cd, nd // Error propogation errptr = rgbErr + x * 3 * 2 @@ -90,57 +95,62 @@ def rgbPix(r, g, b, x, y)#0 pr = 0 pg = 0 pb = 0 - // Project RGB on previous 3/4 chroma cycle + // Previous 3/4 chroma cycle for cx = x - 1 downto x - 3 i = (cx & 3) * 3 pr = pr + ntscCycle[i+RED] pg = pg + ntscCycle[i+GRN] pb = pb + ntscCycle[i+BLU] next - pd = dist(r, g, b, pr, pg, pb) - // Look ahead for possible better match + pd:[0], pd:[1] = dist(r, g, b, pr, pg, pb) + // Look ahead in chroma cycle for possible better match i = ((x + 1) & 3) * 3 - nr = pr - ntscCycle[i+RED] + ntscChroma[i+RED] - ng = pg - ntscCycle[i+GRN] + ntscChroma[i+GRN] - nb = pb - ntscCycle[i+BLU] + ntscChroma[i+BLU] + 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 = nr - (errptr=>[3+RED] + (r - nr + 1) / 2) / errDiv - ng = ng - (errptr=>[3+GRN] + (g - ng + 1) / 2) / errDiv - nb = nb - (errptr=>[3+BLU] + (b - nb + 1) / 2) / 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 fin - nd = dist(r, g, b, nr, ng, nb) - // Add current 1/4 chroma color + nd:[0], nd:[1] = dist(nr, ng, nb, lr, lg, lb) + // Current 1/4 chroma color i = (x & 3) * 3 cr = pr + ntscChroma[i+RED] cg = pg + ntscChroma[i+GRN] cb = pb + ntscChroma[i+BLU] - cd = dist(r, g, b, cr, cg, cb) - if cd < pd and cd < nd + cd:[0], cd:[1] = dist(r, g, b, cr, cg, cb) + load32(@cd) + if islt32(@pd) and islt32(@nd) // RGB better matched with current 1/4 chroma color - r = (r - cr + 1) / 2 - g = (g - cg + 1) / 2 - b = (b - cb + 1) / 2 + nr = nextErr(r, cr) + ng = nextErr(g, cg) + nb = nextErr(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 - r = (r - pr + 1) / 2 - g = (g - pg + 1) / 2 - b = (b - pb + 1) / 2 + nr = nextErr(r, pr) + ng = nextErr(g, pg) + nb = nextErr(b, pb) ntscCycle[i+RED] = 0 ntscCycle[i+GRN] = 0 ntscCycle[i+BLU] = 0 fin // Propogate error down and forward - errptr=>[RED] = r - errptr=>[GRN] = g - errptr=>[BLU] = b + errptr=>[RED] = nr + errptr=>[GRN] = ng + errptr=>[BLU] = nb errptr = errptr + 6 - errptr=>[RED] = r + errptr=>[RED] - errptr=>[GRN] = g + errptr=>[GRN] - errptr=>[BLU] = b + errptr=>[BLU] + errptr=>[RED] = nr + errptr=>[RED] + errptr=>[GRN] = ng + errptr=>[GRN] + errptr=>[BLU] = nb + errptr=>[BLU] // Map dark grey to light grey if (x & 3) == 3 and dcgrGetPixel(x >> 2, y) == 5 dhgrOp(OP_SRC) @@ -154,11 +164,14 @@ def rgbInit#0 if not gamma for i = 0 to 255 - gamma[i] = (i / 4) * (i / 4) / 63 + loadi16(i) + muli16(i) + divi16(255) + store32(@gamma + i) next else for i = 0 to 255 - gamma[i] = i / 4 + gamma[i] = i next fin dhgrMode(DHGR_COLOR_MODE) @@ -254,7 +267,7 @@ if ^arg is 'L' // Use linear RGB transfer instead of gama gamma = 1 break - is 'E' // Set error divisor + is 'E' // Set error strength if ^arg > 2 errDiv = ^(arg + 3) - '0' if ^arg > 3 diff --git a/src/dhgr.tk/utils/ttfconv.c b/src/dhgr.tk/utils/ttfconv.c index d0eece0..4d603a2 100644 --- a/src/dhgr.tk/utils/ttfconv.c +++ b/src/dhgr.tk/utils/ttfconv.c @@ -25,11 +25,11 @@ void write_glyph(FILE *fp, int left, int top, int width, int height, int advance unsigned char glyphdef[5], *swapbuf; int i; - glyphdef[0] = (left + 3) / 4; + glyphdef[0] = left; glyphdef[1] = -top; glyphdef[2] = (width + 3) / 4; glyphdef[3] = height; - glyphdef[4] = (advance + 3) / 4; + glyphdef[4] = advance; fwrite(&glyphdef, 1, 5, fp); swapbuf = malloc(pitch * height); for (i = 0; i < pitch * height; i++) @@ -66,7 +66,7 @@ void write_font_file(char *filename, FT_Face face, int glyph_width, int glyph_he face->glyph->bitmap_top, face->glyph->bitmap.width, face->glyph->bitmap.rows, - face->glyph->advance.x >> 6, + (face->glyph->advance.x + 0x40) >> 6, face->glyph->bitmap.buffer, face->glyph->bitmap.pitch); }