diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-12-07 16:23:22 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-12-07 16:23:22 -0800 |
commit | 2f74a2a8b56622951b2bad1ca19e61ad02eb9f03 (patch) | |
tree | 0208468772b4cffef6819d36b07f0b4ac9abb673 /com32/lib | |
parent | 2c36092660d8666a2a50c73da66717208b94eb4f (diff) | |
parent | 66a4a0bab62d10c66386c1f879a606366c5aea99 (diff) | |
download | syslinux-2f74a2a8b56622951b2bad1ca19e61ad02eb9f03.tar.gz |
Merge branch 'softres'
Diffstat (limited to 'com32/lib')
-rw-r--r-- | com32/lib/Makefile | 3 | ||||
-rw-r--r-- | com32/lib/jpeg/bgr24.c | 135 | ||||
-rw-r--r-- | com32/lib/jpeg/bgra32.c | 158 | ||||
-rw-r--r-- | com32/lib/jpeg/grey.c | 87 | ||||
-rw-r--r-- | com32/lib/jpeg/jidctflt.c | 22 | ||||
-rw-r--r-- | com32/lib/jpeg/rgb24.c | 135 | ||||
-rw-r--r-- | com32/lib/jpeg/rgba32.c | 155 | ||||
-rw-r--r-- | com32/lib/jpeg/tinyjpeg-internal.h | 45 | ||||
-rw-r--r-- | com32/lib/jpeg/tinyjpeg.c | 243 | ||||
-rw-r--r-- | com32/lib/jpeg/yuv420p.c | 133 | ||||
-rw-r--r-- | com32/lib/sys/vesa/background.c | 56 | ||||
-rw-r--r-- | com32/lib/sys/vesa/drawtxt.c | 48 | ||||
-rw-r--r-- | com32/lib/sys/vesa/initvesa.c | 47 | ||||
-rw-r--r-- | com32/lib/sys/vesa/video.h | 23 | ||||
-rw-r--r-- | com32/lib/sys/vesacon_write.c | 18 |
15 files changed, 765 insertions, 543 deletions
diff --git a/com32/lib/Makefile b/com32/lib/Makefile index d136d2b3..ad77bcd6 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -80,7 +80,8 @@ LIBOBJS = \ libpng/pngerror.o libpng/pngpread.o \ \ jpeg/tinyjpeg.o jpeg/jidctflt.o jpeg/decode1.o jpeg/decode3.o \ - jpeg/rgb24.o jpeg/bgr24.o jpeg/yuv420p.o jpeg/grey.o \ + jpeg/grey.o jpeg/yuv420p.o \ + jpeg/rgb24.o jpeg/bgr24.o \ jpeg/rgba32.o jpeg/bgra32.o \ \ sys/x86_init_fpu.o math/pow.o math/strtod.o \ diff --git a/com32/lib/jpeg/bgr24.c b/com32/lib/jpeg/bgr24.c index ffdcbdf9..855b855f 100644 --- a/com32/lib/jpeg/bgr24.c +++ b/com32/lib/jpeg/bgr24.c @@ -69,7 +69,7 @@ static unsigned char clamp(int i) * | 1 | * `---' */ -static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) +static void YCrCB_to_BGR24_1x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -85,15 +85,14 @@ static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 8*3; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -107,6 +106,7 @@ static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); + Y++; } p += offset_to_next_row; @@ -125,7 +125,7 @@ static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) * | 1 | 2 | * `-------' */ -static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) +static void YCrCB_to_BGR24_2x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -141,9 +141,8 @@ static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 16*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; @@ -155,15 +154,7 @@ static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -171,6 +162,17 @@ static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + } + + Y += 2; } p += offset_to_next_row; @@ -190,7 +192,7 @@ static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) * | 2 | * `---' */ -static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) +static void YCrCB_to_BGR24_1x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -207,9 +209,8 @@ static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0 ; j--) { int y, cb, cr; int add_r, add_g, add_b; @@ -221,7 +222,7 @@ static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -229,14 +230,17 @@ static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); - y = (Y[8-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - + if (i > 1) { + y = Y[8] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + } + + Y++; } Y += 8; p += offset_to_next_row; @@ -258,7 +262,7 @@ static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) * | 3 | 4 | * `-------' */ -static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) +static void YCrCB_to_BGR24_2x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -275,9 +279,8 @@ static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 16*3; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; @@ -289,7 +292,7 @@ static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -297,29 +300,37 @@ static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (Y[16-2]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - - y = (Y[16-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + } + } + + Y += 2; } Y += 16; p += offset_to_next_row; @@ -336,12 +347,12 @@ static int initialize_bgr24(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); if (!priv->bytes_per_row[0]) priv->bytes_per_row[0] = priv->width * 3; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; bytes_per_mcu[0] = 3*8; return !priv->components[0]; diff --git a/com32/lib/jpeg/bgra32.c b/com32/lib/jpeg/bgra32.c index 7e2c72bc..9a1ab309 100644 --- a/com32/lib/jpeg/bgra32.c +++ b/com32/lib/jpeg/bgra32.c @@ -69,7 +69,7 @@ static unsigned char clamp(int i) * | 1 | * `---' */ -static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv) +static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -85,15 +85,14 @@ static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 8*4; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b, a; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -109,6 +108,7 @@ static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv) a = 255; *p++ = a; + Y++; } p += offset_to_next_row; @@ -127,7 +127,7 @@ static void YCrCB_to_BGRA32_1x1(struct jdec_private *priv) * | 1 | 2 | * `-------' */ -static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv) +static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -143,10 +143,8 @@ static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 16*4; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b, a; @@ -157,7 +155,7 @@ static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -166,17 +164,20 @@ static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv) *p++ = clamp(r); a = 255; *p++ = a; - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - a = 255; - *p++ = a; - + + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + } + + Y += 2; } p += offset_to_next_row; @@ -196,7 +197,7 @@ static void YCrCB_to_BGRA32_2x1(struct jdec_private *priv) * | 2 | * `---' */ -static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv) +static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -213,9 +214,8 @@ static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 8*4; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; @@ -227,7 +227,7 @@ static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -237,16 +237,19 @@ static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv) a = 255; *p++ = a; - y = (Y[8-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - a = 255; - *p2++ = a; - + if (i > 1) { + y = Y[8] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + } + + Y++; } Y += 8; p += offset_to_next_row; @@ -268,7 +271,7 @@ static void YCrCB_to_BGRA32_1x2(struct jdec_private *priv) * | 3 | 4 | * `-------' */ -static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv) +static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -285,9 +288,8 @@ static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 16*4; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; @@ -299,17 +301,7 @@ static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - a = 255; - *p++ = a; - - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); g = (y + add_g) >> SCALEBITS; @@ -319,25 +311,43 @@ static void YCrCB_to_BGRA32_2x2(struct jdec_private *priv) a = 255; *p++ = a; - y = (Y[16-2]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - a = 255; - *p2++ = a; - - y = (Y[16-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - a = 255; - *p2++ = a; + if (j > 1) { + y = Y[1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + a = 255; + *p++ = a; + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + a = 255; + *p2++ = a; + } + } + + Y += 2; } Y += 16; p += offset_to_next_row; @@ -354,12 +364,12 @@ static int initialize_bgra32(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 4); if (!priv->bytes_per_row[0]) priv->bytes_per_row[0] = priv->width * 4; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; bytes_per_mcu[0] = 4*8; return !priv->components[0]; diff --git a/com32/lib/jpeg/grey.c b/com32/lib/jpeg/grey.c index 0034ce2b..6710ede6 100644 --- a/com32/lib/jpeg/grey.c +++ b/com32/lib/jpeg/grey.c @@ -40,12 +40,12 @@ #include "tinyjpeg-internal.h" /** - * YCrCb -> Grey (1x1) + * YCrCb -> Grey (1x1, 1x2) * .---. * | 1 | * `---' */ -static void YCrCB_to_Grey_1x1(struct jdec_private *priv) +static void YCrCB_to_Grey_1xN(struct jdec_private *priv, int sx, int sy) { const unsigned char *y; unsigned char *p; @@ -56,73 +56,20 @@ static void YCrCB_to_Grey_1x1(struct jdec_private *priv) y = priv->Y; offset_to_next_row = priv->bytes_per_row[0]; - for (i=0; i<8; i++) { - memcpy(p, y, 8); - y+=8; - p += offset_to_next_row; - } -} - -/** - * YCrCb -> Grey (2x1) - * .-------. - * | 1 | 2 | - * `-------' - */ -static void YCrCB_to_Grey_2x1(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - int offset_to_next_row; - - p = priv->plane[0]; - y = priv->Y; - offset_to_next_row = priv->bytes_per_row[0]; - - for (i=0; i<8; i++) { - memcpy(p, y, 16); - y += 16; - p += offset_to_next_row; - } -} - - -/** - * YCrCb -> Grey (1x2) - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void YCrCB_to_Grey_1x2(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - int offset_to_next_row; - - p = priv->plane[0]; - y = priv->Y; - offset_to_next_row = priv->bytes_per_row[0]; - - for (i=0; i<16; i++) { - memcpy(p, y, 8); + for (i = sy; i > 0; i--) { + memcpy(p, y, sx); y += 8; p += offset_to_next_row; } } /** - * YCrCb -> Grey (2x2) + * YCrCb -> Grey (2x1, 2x2) * .-------. * | 1 | 2 | - * |---+---| - * | 3 | 4 | * `-------' */ -static void YCrCB_to_Grey_2x2(struct jdec_private *priv) +static void YCrCB_to_Grey_2xN(struct jdec_private *priv, int sx, int sy) { const unsigned char *y; unsigned char *p; @@ -133,8 +80,8 @@ static void YCrCB_to_Grey_2x2(struct jdec_private *priv) y = priv->Y; offset_to_next_row = priv->bytes_per_row[0]; - for (i=0; i<16; i++) { - memcpy(p, y, 16); + for (i = sy; i > 0; i--) { + memcpy(p, y, sx); y += 16; p += offset_to_next_row; } @@ -144,13 +91,13 @@ static int initialize_grey(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); if (!priv->bytes_per_row[0]) - priv->bytes_per_row[0] = priv->width * 3; + priv->bytes_per_row[0] = priv->width; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; - bytes_per_mcu[0] = 3*8; + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; + bytes_per_mcu[0] = 8; return !priv->components[0]; } @@ -158,10 +105,10 @@ static int initialize_grey(struct jdec_private *priv, static const struct tinyjpeg_colorspace format_grey = { { - YCrCB_to_Grey_1x1, - YCrCB_to_Grey_1x2, - YCrCB_to_Grey_2x1, - YCrCB_to_Grey_2x2, + YCrCB_to_Grey_1xN, + YCrCB_to_Grey_1xN, + YCrCB_to_Grey_2xN, + YCrCB_to_Grey_2xN, }, tinyjpeg_decode_mcu_1comp_table, initialize_grey diff --git a/com32/lib/jpeg/jidctflt.c b/com32/lib/jpeg/jidctflt.c index e5e66edc..6f0df772 100644 --- a/com32/lib/jpeg/jidctflt.c +++ b/com32/lib/jpeg/jidctflt.c @@ -80,7 +80,7 @@ #define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) -#if defined(__GNUC__) && defined(__i686__) || defined(__x86_64__) +#if 1 && defined(__GNUC__) && (defined(__i686__) || defined(__x86_64__)) static inline unsigned char descale_and_clamp(int x, int shift) { @@ -92,7 +92,7 @@ static inline unsigned char descale_and_clamp(int x, int shift) "\tcmpl %4,%1\n" "\tcmovg %4,%1\n" : "=r"(x) - : "0"(x), "i"(shift), "i"(1UL<<(shift-1)), "r" (0xff), "r" (0) + : "0"(x), "Ir"(shift), "ir"(1UL<<(shift-1)), "r" (0xff), "r" (0) ); return x; } @@ -120,7 +120,7 @@ static inline unsigned char descale_and_clamp(int x, int shift) */ void -jpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) +tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; @@ -269,14 +269,14 @@ jpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) /* Final output stage: scale down by a factor of 8 and range-limit */ - outptr[0] = descale_and_clamp(tmp0 + tmp7, 3); - outptr[7] = descale_and_clamp(tmp0 - tmp7, 3); - outptr[1] = descale_and_clamp(tmp1 + tmp6, 3); - outptr[6] = descale_and_clamp(tmp1 - tmp6, 3); - outptr[2] = descale_and_clamp(tmp2 + tmp5, 3); - outptr[5] = descale_and_clamp(tmp2 - tmp5, 3); - outptr[4] = descale_and_clamp(tmp3 + tmp4, 3); - outptr[3] = descale_and_clamp(tmp3 - tmp4, 3); + outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3); + outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3); + outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3); + outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3); + outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3); + outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3); + outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3); + outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3); wsptr += DCTSIZE; /* advance pointer to next row */ diff --git a/com32/lib/jpeg/rgb24.c b/com32/lib/jpeg/rgb24.c index e37cc77d..e1481f31 100644 --- a/com32/lib/jpeg/rgb24.c +++ b/com32/lib/jpeg/rgb24.c @@ -69,7 +69,7 @@ static unsigned char clamp(int i) * | 1 | * `---' */ -static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) +static void YCrCB_to_RGB24_1x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -85,15 +85,13 @@ static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 8*3; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { - + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j++) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -107,6 +105,7 @@ static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); + Y++; } p += offset_to_next_row; @@ -124,7 +123,7 @@ static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) * | 1 | 2 | * `-------' */ -static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) +static void YCrCB_to_RGB24_2x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -140,15 +139,15 @@ static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 16*3; - for (i=0; i<8; i++) { + for (i = sy; i > 0; i--) { - for (j=0; j<8; j++) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -162,14 +161,17 @@ static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + } + + Y += 2; } p += offset_to_next_row; @@ -190,7 +192,7 @@ static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) * | 2 | * `---' */ -static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) +static void YCrCB_to_RGB24_1x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -207,9 +209,8 @@ static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; @@ -221,7 +222,7 @@ static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); g = (y + add_g) >> SCALEBITS; @@ -229,14 +230,17 @@ static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); - y = (Y[8-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - + if (i > 1) { + y = Y[8] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + } + + Y++; } Y += 8; p += offset_to_next_row; @@ -257,7 +261,7 @@ static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) * | 3 | 4 | * `-------' */ -static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) +static void YCrCB_to_RGB24_2x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -274,9 +278,8 @@ static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 16*3; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; @@ -288,7 +291,7 @@ static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); g = (y + add_g) >> SCALEBITS; @@ -296,29 +299,37 @@ static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) b = (y + add_b) >> SCALEBITS; *p++ = clamp(b); - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - y = (Y[16-2]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - - y = (Y[16-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + } + } + + Y += 2; } Y += 16; p += offset_to_next_row; @@ -335,12 +346,12 @@ static int initialize_rgb24(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); if (!priv->bytes_per_row[0]) priv->bytes_per_row[0] = priv->width * 3; + if (priv->components[0] == NULL) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; bytes_per_mcu[0] = 3*8; return !priv->components[0]; diff --git a/com32/lib/jpeg/rgba32.c b/com32/lib/jpeg/rgba32.c index 5fcbe992..d04f0f13 100644 --- a/com32/lib/jpeg/rgba32.c +++ b/com32/lib/jpeg/rgba32.c @@ -69,7 +69,7 @@ static unsigned char clamp(int i) * | 1 | * `---' */ -static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv) +static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -85,15 +85,14 @@ static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 8*4; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b, a; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -108,6 +107,8 @@ static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv) *p++ = clamp(b); a = 255; *p++ = a; + + Y++; } p += offset_to_next_row; @@ -125,7 +126,7 @@ static void YCrCB_to_RGBA32_1x1(struct jdec_private *priv) * | 1 | 2 | * `-------' */ -static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv) +static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p; @@ -141,15 +142,14 @@ static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = priv->bytes_per_row[0] - 16*4; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i--) { + for (j = sx; j > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; int r, g , b, a; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; cb = *Cb++ - 128; cr = *Cr++ - 128; add_r = FIX(1.40200) * cr + ONE_HALF; @@ -165,15 +165,19 @@ static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv) a = 255; *p++ = a; - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - a = 255; - *p++ = a; + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + } + + Y += 2; } p += offset_to_next_row; @@ -194,7 +198,7 @@ static void YCrCB_to_RGBA32_2x1(struct jdec_private *priv) * | 2 | * `---' */ -static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv) +static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -211,9 +215,8 @@ static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 8*4; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; j > 0; j--) { int y, cb, cr; int add_r, add_g, add_b; @@ -225,7 +228,7 @@ static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); g = (y + add_g) >> SCALEBITS; @@ -235,16 +238,19 @@ static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv) a = 255; *p++ = a; - y = (Y[8-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - a = 255; - *p2++ = a; - + if (i > 1) { + y = Y[8] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + } + + Y++; } Y += 8; p += offset_to_next_row; @@ -265,7 +271,7 @@ static void YCrCB_to_RGBA32_1x2(struct jdec_private *priv) * | 3 | 4 | * `-------' */ -static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv) +static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *Y, *Cb, *Cr; unsigned char *p, *p2; @@ -282,9 +288,8 @@ static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv) Cb = priv->Cb; Cr = priv->Cr; offset_to_next_row = 2*priv->bytes_per_row[0] - 16*4; - for (i=0; i<8; i++) { - - for (j=0;j<8;j++) { + for (i = sy; i > 0; i -= 2) { + for (j = sx; i > 0; j -= 2) { int y, cb, cr; int add_r, add_g, add_b; @@ -296,7 +301,7 @@ static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv) add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; add_b = FIX(1.77200) * cb + ONE_HALF; - y = (*Y++) << SCALEBITS; + y = Y[0] << SCALEBITS; r = (y + add_r) >> SCALEBITS; *p++ = clamp(r); g = (y + add_g) >> SCALEBITS; @@ -306,35 +311,43 @@ static void YCrCB_to_RGBA32_2x2(struct jdec_private *priv) a = 255; *p++ = a; - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - a = 255; - *p++ = a; - - y = (Y[16-2]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - a = 255; - *p2++ = a; - - y = (Y[16-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - a = 255; - *p2++ = a; + if (j > 1) { + y = Y[1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + a = 255; + *p++ = a; + } + + if (i > 1) { + y = Y[16+0] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + + if (j > 1) { + y = Y[16+1] << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + a = 255; + *p2++ = a; + } + } + + Y += 2; } Y += 16; p += offset_to_next_row; @@ -351,12 +364,12 @@ static int initialize_rgba32(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 4); if (!priv->bytes_per_row[0]) priv->bytes_per_row[0] = priv->width * 4; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; + bytes_per_blocklines[0] = priv->bytes_per_row[0] << 3; bytes_per_mcu[0] = 4*8; return !priv->components[0]; diff --git a/com32/lib/jpeg/tinyjpeg-internal.h b/com32/lib/jpeg/tinyjpeg-internal.h index 78cb0421..bb5c6707 100644 --- a/com32/lib/jpeg/tinyjpeg-internal.h +++ b/com32/lib/jpeg/tinyjpeg-internal.h @@ -35,14 +35,21 @@ #ifndef __TINYJPEG_INTERNAL_H_ #define __TINYJPEG_INTERNAL_H_ +#include <setjmp.h> + +#define SANITY_CHECK 1 + struct jdec_private; +#define HUFFMAN_BITS_SIZE 256 #define HUFFMAN_HASH_NBITS 9 #define HUFFMAN_HASH_SIZE (1UL<<HUFFMAN_HASH_NBITS) #define HUFFMAN_HASH_MASK (HUFFMAN_HASH_SIZE-1) #define HUFFMAN_TABLES 4 -#define COMPONENTS 4 +#define COMPONENTS 3 +#define JPEG_MAX_WIDTH 4096 +#define JPEG_MAX_HEIGHT 4096 struct huffman_table { @@ -66,11 +73,14 @@ struct component struct huffman_table *DC_table; short int previous_DC; /* Previous DC coefficient */ short int DCT[64]; /* DCT coef */ +#if SANITY_CHECK + unsigned int cid; +#endif }; typedef void (*decode_MCU_fct) (struct jdec_private *priv); -typedef void (*convert_colorspace_fct) (struct jdec_private *priv); +typedef void (*convert_colorspace_fct) (struct jdec_private *priv, int, int); struct jdec_private { @@ -81,7 +91,7 @@ struct jdec_private unsigned int flags; /* Private variables */ - const unsigned char *stream_begin; + const unsigned char *stream_begin, *stream_end; unsigned int stream_length; const unsigned char *stream; /* Pointer to the current stream */ @@ -92,24 +102,28 @@ struct jdec_private struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC huffman tables */ struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC huffman tables */ int default_huffman_table_initialized; + int restart_interval; + int restarts_to_go; /* MCUs left in this restart interval */ + int last_rst_marker_seen; /* Rst marker is incremented each time */ /* Temp space used after the IDCT to store each components */ uint8_t Y[64*4], Cr[64], Cb[64]; + jmp_buf jump_state; /* Internal Pointer use for colorspace conversion, do not modify it !!! */ uint8_t *plane[COMPONENTS]; }; +#define IDCT tinyjpeg_idct_float +void tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride); + struct tinyjpeg_colorspace { convert_colorspace_fct convert_colorspace[4]; const decode_MCU_fct *decode_mcu_table; int (*initialize)(struct jdec_private *, unsigned int *, unsigned int *); }; -#define IDCT jpeg_idct_float -void jpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride); - void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component); extern const decode_MCU_fct tinyjpeg_decode_mcu_3comp_table[4]; @@ -121,13 +135,16 @@ enum std_markers { DHT = 0xC4, /* Huffman Table */ SOI = 0xD8, /* Start of Image */ SOS = 0xDA, /* Start of Scan */ + RST = 0xD0, /* Reset Marker d0 -> .. */ + RST7 = 0xD7, /* Reset Marker .. -> d7 */ EOI = 0xD9, /* End of Image */ + DRI = 0xDD, /* Define Restart Interval */ APP0 = 0xE0, }; -#define cY 1 -#define cCb 2 -#define cCr 3 +#define cY 0 +#define cCb 1 +#define cCr 2 #define BLACK_Y 0 #define BLACK_U 127 @@ -150,6 +167,16 @@ enum std_markers { #define trace(fmt, args...) do { } while (0) #endif +#ifndef __likely +# define __likely(x) (!!(x)) +#endif +#ifndef __unlikely +# define __unlikely(x) (!!(x)) +#endif + +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + #if 0 static char *print_bits(unsigned int value, char *bitstr) { diff --git a/com32/lib/jpeg/tinyjpeg.c b/com32/lib/jpeg/tinyjpeg.c index f8e881f0..3c6070f4 100644 --- a/com32/lib/jpeg/tinyjpeg.c +++ b/com32/lib/jpeg/tinyjpeg.c @@ -35,6 +35,7 @@ #include <stdlib.h> #include <string.h> #include <stdint.h> +#include <errno.h> #include "tinyjpeg.h" #include "tinyjpeg-internal.h" @@ -162,7 +163,10 @@ static const unsigned char val_ac_chrominance[] = #define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ while (nbits_in_reservoir<nbits_wanted) \ { \ - const unsigned char c = *stream++; \ + unsigned char c; \ + if (stream >= priv->stream_end) \ + longjmp(priv->jump_state, -EIO); \ + c = *stream++; \ reservoir <<= 8; \ if (c == 0xff && *stream == 0x00) \ stream++; \ @@ -177,7 +181,7 @@ static const unsigned char val_ac_chrominance[] = result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ nbits_in_reservoir -= (nbits_wanted); \ reservoir &= ((1U<<nbits_in_reservoir)-1); \ - if (result < (1UL<<((nbits_wanted)-1))) \ + if ((unsigned int)result < (1UL<<((nbits_wanted)-1))) \ result += (0xFFFFFFFFUL<<(nbits_wanted))+1; \ } while(0); @@ -186,8 +190,15 @@ static const unsigned char val_ac_chrominance[] = result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ } while(0); +/* To speed up the decoding, we assume that the reservoir have enough bit + * slow version: + * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + * fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + * nbits_in_reservoir -= (nbits_wanted); \ + * reservoir &= ((1U<<nbits_in_reservoir)-1); \ + * } while(0); + */ #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ - fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ nbits_in_reservoir -= (nbits_wanted); \ reservoir &= ((1U<<nbits_in_reservoir)-1); \ } while(0); @@ -195,6 +206,7 @@ static const unsigned char val_ac_chrominance[] = #define be16_to_cpu(x) (((x)[0]<<8)|(x)[1]) +static void resync(struct jdec_private *priv); /** * Get the next (valid) huffman code in the stream. @@ -215,9 +227,9 @@ static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); value = huffman_table->lookup[hcode]; - if (value>=0) + if (__likely(value >= 0)) { - int code_size = huffman_table->code_size[value]; + unsigned int code_size = huffman_table->code_size[value]; skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); return value; } @@ -253,17 +265,19 @@ static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component) { unsigned char j; - int huff_code; + unsigned int huff_code; unsigned char size_val, count_0; struct component *c = &priv->component_infos[component]; short int DCT[64]; + /* Initialize the DCT coef table */ memset(DCT, 0, sizeof(DCT)); /* DC coefficient decoding */ huff_code = get_next_huffman_code(priv, c->DC_table); + //trace("+ %x\n", huff_code); if (huff_code) { get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); DCT[0] += c->previous_DC; @@ -277,6 +291,7 @@ void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component while (j<64) { huff_code = get_next_huffman_code(priv, c->AC_table); + //trace("- %x\n", huff_code); size_val = huff_code & 0xF; count_0 = huff_code >> 4; @@ -291,6 +306,11 @@ void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component else { j += count_0; /* skip count_0 zeroes */ + if (__unlikely(j >= 64)) + { + snprintf(error_string, sizeof(error_string), "Bad huffman data (buffer overflow)"); + break; + } get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); j++; } @@ -298,7 +318,6 @@ void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component for (j = 0; j < 64; j++) c->DCT[j] = DCT[zigzag[j]]; - } /* @@ -311,8 +330,8 @@ void tinyjpeg_process_Huffman_data_unit(struct jdec_private *priv, int component static void build_huffman_table(const unsigned char *bits, const unsigned char *vals, struct huffman_table *table) { unsigned int i, j, code, code_size, val, nbits; - unsigned char huffsize[257], *hz; - unsigned int huffcode[257], *hc; + unsigned char huffsize[HUFFMAN_BITS_SIZE+1], *hz; + unsigned int huffcode[HUFFMAN_BITS_SIZE+1], *hc; int next_free_entry; /* @@ -340,10 +359,11 @@ static void build_huffman_table(const unsigned char *bits, const unsigned char * nbits = *hz; while (*hz) { - while (*hz == nbits) { + while (*hz == nbits) + { *hc++ = code++; hz++; - } + } code <<= 1; nbits++; } @@ -358,7 +378,7 @@ static void build_huffman_table(const unsigned char *bits, const unsigned char * code = huffcode[i]; code_size = huffsize[i]; - trace("val=%2.2x code=%8.8x codesize=%2.2d\n", i, code, code_size); + trace("val=%2.2x code=%8.8x codesize=%2.2d\n", val, code, code_size); table->code_size[val] = code_size; if (code_size <= HUFFMAN_HASH_NBITS) @@ -386,7 +406,6 @@ static void build_huffman_table(const unsigned char *bits, const unsigned char * } } - } static void build_default_huffman_tables(struct jdec_private *priv) @@ -483,14 +502,15 @@ static void build_quantization_table(float *qtable, const unsigned char *ref_tab static int parse_DQT(struct jdec_private *priv, const unsigned char *stream) { - int length, qi; + int qi; float *table; + const unsigned char *dqt_block_end; trace("> DQT marker\n"); - length = be16_to_cpu(stream) - 2; + dqt_block_end = stream + be16_to_cpu(stream); stream += 2; /* Skip length */ - while (length>0) + while (stream < dqt_block_end) { qi = *stream++; #if SANITY_CHECK @@ -502,8 +522,8 @@ static int parse_DQT(struct jdec_private *priv, const unsigned char *stream) table = priv->Q_tables[qi]; build_quantization_table(table, stream); stream += 64; - length -= 65; } + trace("< DQT marker\n"); return 0; } @@ -513,6 +533,7 @@ static int parse_SOF(struct jdec_private *priv, const unsigned char *stream) int Q_table; struct component *c; + trace("> SOF marker\n"); print_SOF(stream); height = be16_to_cpu(stream+3); @@ -521,31 +542,34 @@ static int parse_SOF(struct jdec_private *priv, const unsigned char *stream) #if SANITY_CHECK if (stream[2] != 8) error("Precision other than 8 is not supported\n"); - if (width>2048 || height>2048) + if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT) error("Width and Height (%dx%d) seems suspicious\n", width, height); if (nr_components != 3) error("We only support YUV images\n"); - if (height%16) - error("Height need to be a multiple of 16 (current height is %d)\n", height); - if (width%16) - error("Width need to be a multiple of 16 (current Width is %d)\n", width); #endif stream += 8; for (i=0; i<nr_components; i++) { cid = *stream++; sampling_factor = *stream++; Q_table = *stream++; - c = &priv->component_infos[cid]; + c = &priv->component_infos[i]; +#if SANITY_CHECK + c->cid = cid; + if (Q_table >= COMPONENTS) + error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1); +#endif c->Vfactor = sampling_factor&0xf; c->Hfactor = sampling_factor>>4; c->Q_table = priv->Q_tables[Q_table]; trace("Component:%d factor:%dx%d Quantization table:%d\n", - cid, c->Hfactor, c->Hfactor, Q_table ); + cid, c->Hfactor, c->Hfactor, Q_table ); } priv->width = width; priv->height = height; + trace("< SOF marker\n"); + return 0; } @@ -570,12 +594,16 @@ static int parse_SOS(struct jdec_private *priv, const unsigned char *stream) error("We do not support more than 2 AC Huffman table\n"); if ((table>>4)>=4) error("We do not support more than 2 DC Huffman table\n"); + if (cid != priv->component_infos[i].cid) + error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n", + i, cid, i, priv->component_infos[i].cid); trace("ComponentId:%d tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4); #endif - priv->component_infos[cid].AC_table = &priv->HTAC[table&0xf]; - priv->component_infos[cid].DC_table = &priv->HTDC[table>>4]; + priv->component_infos[i].AC_table = &priv->HTAC[table&0xf]; + priv->component_infos[i].DC_table = &priv->HTDC[table>>4]; } priv->stream = stream+3; + trace("< SOS marker\n"); return 0; } @@ -601,12 +629,11 @@ static int parse_DHT(struct jdec_private *priv, const unsigned char *stream) count += huff_bits[i]; } #if SANITY_CHECK - if (count > 1024) - error("No more than 1024 bytes is allowed to describe a huffman table"); + if (count >= HUFFMAN_BITS_SIZE) + error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE); if ( (index &0xf) >= HUFFMAN_TABLES) - error("No mode than %d Huffman tables is supported\n", HUFFMAN_TABLES); - trace("Huffman table %s n%d\n", (index&0xf0)?"AC":"DC", index&0xf); - trace("Length of the table: %d\n", count); + error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf); + trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count); #endif if (index & 0xf0 ) @@ -617,11 +644,38 @@ static int parse_DHT(struct jdec_private *priv, const unsigned char *stream) length -= 1; length -= 16; length -= count; + stream += count; } trace("< DHT marker\n"); return 0; } +static int parse_DRI(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int length; + + trace("> DRI marker\n"); + + length = be16_to_cpu(stream); + +#if SANITY_CHECK + if (length != 4) + error("Length of DRI marker need to be 4\n"); +#endif + + priv->restart_interval = be16_to_cpu(stream+2); + +#if DEBUG + trace("Restart interval = %d\n", priv->restart_interval); +#endif + + trace("< DRI marker\n"); + + return 0; +} + + + static void resync(struct jdec_private *priv) { int i; @@ -632,9 +686,46 @@ static void resync(struct jdec_private *priv) priv->reservoir = 0; priv->nbits_in_reservoir = 0; - + if (priv->restart_interval > 0) + priv->restarts_to_go = priv->restart_interval; + else + priv->restarts_to_go = -1; } +static int find_next_rst_marker(struct jdec_private *priv) +{ + int rst_marker_found = 0; + int marker; + const unsigned char *stream = priv->stream; + + /* Parse marker */ + while (!rst_marker_found) + { + while (*stream++ != 0xff) + { + if (stream >= priv->stream_end) + error("EOF while search for a RST marker."); + } + /* Skip any padding ff byte (this is normal) */ + while (*stream == 0xff) + stream++; + + marker = *stream++; + if ((RST+priv->last_rst_marker_seen) == marker) + rst_marker_found = 1; + else if (marker >= RST && marker <= RST7) + error("Wrong Reset marker found, abording"); + else if (marker == EOI) + return 0; + } + trace("RST Marker %d found at offset %d\n", priv->last_rst_marker_seen, stream - priv->stream_begin); + + priv->stream = stream; + priv->last_rst_marker_seen++; + priv->last_rst_marker_seen &= 7; + + return 0; +} static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream) { @@ -676,6 +767,10 @@ static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream) return -1; dht_marker_found = 1; break; + case DRI: + if (parse_DRI(priv, stream) < 0) + return -1; + break; default: trace("> Unknown marker %2.2x\n", marker); break; @@ -767,6 +862,7 @@ int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, u priv->stream_begin = buf+2; priv->stream_length = size-2; + priv->stream_end = priv->stream_begin + priv->stream_length; ret = parse_JFIF(priv, priv->stream_begin); @@ -781,18 +877,21 @@ int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, u int tinyjpeg_decode(struct jdec_private *priv, const struct tinyjpeg_colorspace *pixfmt) { - unsigned int x, y, xstride_by_mcu, ystride_by_mcu; + int x, y, sx, sy; + int xshift_by_mcu, yshift_by_mcu; + int xstride_by_mcu, ystride_by_mcu; unsigned int bytes_per_blocklines[3], bytes_per_mcu[3]; decode_MCU_fct decode_MCU; const decode_MCU_fct *decode_mcu_table; convert_colorspace_fct convert_to_pixfmt; + uint8_t *pptr[3]; decode_mcu_table = pixfmt->decode_mcu_table; /* Fix: check return value */ pixfmt->initialize(priv, bytes_per_blocklines, bytes_per_mcu); - xstride_by_mcu = ystride_by_mcu = 8; + xshift_by_mcu = yshift_by_mcu = 3; if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) { decode_MCU = decode_mcu_table[0]; convert_to_pixfmt = pixfmt->convert_colorspace[0]; @@ -800,55 +899,85 @@ int tinyjpeg_decode(struct jdec_private *priv, } else if (priv->component_infos[cY].Hfactor == 1) { decode_MCU = decode_mcu_table[1]; convert_to_pixfmt = pixfmt->convert_colorspace[1]; - ystride_by_mcu = 16; + yshift_by_mcu = 4; trace("Use decode 1x2 sampling (not supported)\n"); } else if (priv->component_infos[cY].Vfactor == 2) { decode_MCU = decode_mcu_table[3]; convert_to_pixfmt = pixfmt->convert_colorspace[3]; - xstride_by_mcu = 16; - ystride_by_mcu = 16; + xshift_by_mcu = 4; + yshift_by_mcu = 4; trace("Use decode 2x2 sampling\n"); } else { decode_MCU = decode_mcu_table[2]; convert_to_pixfmt = pixfmt->convert_colorspace[2]; - xstride_by_mcu = 16; + xshift_by_mcu = 4; trace("Use decode 2x1 sampling\n"); } resync(priv); /* Don't forget to that block can be either 8 or 16 lines */ - bytes_per_blocklines[0] *= ystride_by_mcu; - bytes_per_blocklines[1] *= ystride_by_mcu; - bytes_per_blocklines[2] *= ystride_by_mcu; + bytes_per_blocklines[0] <<= yshift_by_mcu-3; + bytes_per_blocklines[1] <<= yshift_by_mcu-3; + bytes_per_blocklines[2] <<= yshift_by_mcu-3; + + bytes_per_mcu[0] <<= xshift_by_mcu-3; + bytes_per_mcu[1] <<= xshift_by_mcu-3; + bytes_per_mcu[2] <<= xshift_by_mcu-3; - bytes_per_mcu[0] *= xstride_by_mcu/8; - bytes_per_mcu[1] *= xstride_by_mcu/8; - bytes_per_mcu[2] *= xstride_by_mcu/8; + xstride_by_mcu = 1 << xshift_by_mcu; + ystride_by_mcu = 1 << yshift_by_mcu; - /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */ - for (y=0; y < priv->height/ystride_by_mcu; y++) + pptr[0] = priv->components[0]; + pptr[1] = priv->components[1]; + pptr[2] = priv->components[2]; + + trace("bpbl = %d, bpmcu = %d\n", + bytes_per_blocklines[0], bytes_per_mcu[0]); + + for (y = priv->height; y > 0; y -= ystride_by_mcu) { - //trace("Decoding row %d\n", y); - priv->plane[0] = priv->components[0] + (y * bytes_per_blocklines[0]); - priv->plane[1] = priv->components[1] + (y * bytes_per_blocklines[1]); - priv->plane[2] = priv->components[2] + (y * bytes_per_blocklines[2]); - for (x=0; x < priv->width; x+=xstride_by_mcu) + trace("Decoding row %d\n", priv->height-y); + priv->plane[0] = pptr[0]; pptr[0] += bytes_per_blocklines[0]; + priv->plane[1] = pptr[1]; pptr[1] += bytes_per_blocklines[1]; + priv->plane[2] = pptr[2]; pptr[2] += bytes_per_blocklines[2]; + + sy = min(y, ystride_by_mcu); + + for (x = priv->width; x > 0; x -= xstride_by_mcu) { + sx = min(x, xstride_by_mcu); + trace("Block size: %dx%d\n", sx, sy); + decode_MCU(priv); - convert_to_pixfmt(priv); + convert_to_pixfmt(priv, sx, sy); priv->plane[0] += bytes_per_mcu[0]; priv->plane[1] += bytes_per_mcu[1]; priv->plane[2] += bytes_per_mcu[2]; - + if (priv->restarts_to_go>0) + { + priv->restarts_to_go--; + if (priv->restarts_to_go == 0) + { + priv->stream -= (priv->nbits_in_reservoir/8); + resync(priv); + if (find_next_rst_marker(priv) < 0) + return -1; + } + } } } + trace("Input file size: %d\n", priv->stream_length+2); + trace("Input bytes actually read: %d\n", priv->stream - priv->stream_begin + 2); + return 0; } const char *tinyjpeg_get_errorstring(struct jdec_private *priv) { + /* FIXME: the error string must be store in the context */ + priv = priv; return error_string; } @@ -860,7 +989,7 @@ void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents) { - int i; + unsigned int i; if (ncomponents > COMPONENTS) ncomponents = COMPONENTS; for (i=0; i<ncomponents; i++) @@ -870,7 +999,7 @@ int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **component int tinyjpeg_set_components(struct jdec_private *priv, unsigned char * const *components, unsigned int ncomponents) { - int i; + unsigned int i; if (ncomponents > COMPONENTS) ncomponents = COMPONENTS; for (i=0; i<ncomponents; i++) @@ -882,7 +1011,7 @@ int tinyjpeg_get_bytes_per_row(struct jdec_private *priv, unsigned int *bytes, unsigned int ncomponents) { - int i; + unsigned int i; if (ncomponents > COMPONENTS) ncomponents = COMPONENTS; for (i=0; i<ncomponents; i++) @@ -894,7 +1023,7 @@ int tinyjpeg_set_bytes_per_row(struct jdec_private *priv, const unsigned int *bytes, unsigned int ncomponents) { - int i; + unsigned int i; if (ncomponents > COMPONENTS) ncomponents = COMPONENTS; for (i=0; i<ncomponents; i++) diff --git a/com32/lib/jpeg/yuv420p.c b/com32/lib/jpeg/yuv420p.c index 0c5edf7c..c512089c 100644 --- a/com32/lib/jpeg/yuv420p.c +++ b/com32/lib/jpeg/yuv420p.c @@ -43,13 +43,28 @@ #include "tinyjpeg.h" #include "tinyjpeg-internal.h" +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ + /** * YCrCb -> YUV420P (1x1) * .---. * | 1 | * `---' */ -static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) +static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv, int sx, int sy) { const unsigned char *s, *y; unsigned char *p; @@ -57,19 +72,21 @@ static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) p = priv->plane[0]; y = priv->Y; - for (i=0; i<8; i++) + for (i = sy; i > 0; i--) { - memcpy(p, y, 8); + memcpy(p, y, sx); p += priv->bytes_per_row[0]; y += 8; } p = priv->plane[1]; s = priv->Cb; - for (i=0; i<8; i+=2) + for (i = sy; i > 0; i--) { - for (j=0; j<8; j+=2, s+=2) + for (j = sx; j >= 0; j -= 2) { *p++ = *s; + s += 2; + } s += 8; /* Skip one line */ p += priv->bytes_per_row[1] - 4; } @@ -78,8 +95,10 @@ static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) s = priv->Cr; for (i=0; i<8; i+=2) { - for (j=0; j<8; j+=2, s+=2) + for (j = sx; j >= 0; j -= 2) { *p++ = *s; + s += 2; + } s += 8; /* Skip one line */ p += priv->bytes_per_row[2] - 4; } @@ -91,39 +110,39 @@ static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) * | 1 | 2 | * `-------' */ -static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv) +static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv, int sx, int sy) { unsigned char *p; const unsigned char *s, *y1; - int i,j; + unsigned int i; p = priv->plane[0]; y1 = priv->Y; - for (i=0; i<8; i++) + for (i = sy; i > 0; i--) { - memcpy(p, y1, 16); + memcpy(p, y1, sx); p += priv->bytes_per_row[0]; y1 += 16; } + sx = (sx+1) >> 1; + p = priv->plane[1]; s = priv->Cb; - for (i=0; i<8; i+=2) + for (i = sy; i > 0; i -= 2) { - for (j=0; j<8; j+=1, s+=1) - *p++ = *s; - s += 8; /* Skip one line */ - p += priv->bytes_per_row[1] - 8; + memcpy(p, s, sx); + s += 16; /* Skip one line */ + p += priv->bytes_per_row[1]; } p = priv->plane[2]; s = priv->Cr; - for (i=0; i<8; i+=2) + for (i = sy; i > 0; i -= 2) { - for (j=0; j<8; j+=1, s+=1) - *p++ = *s; - s += 8; /* Skip one line */ - p += priv->bytes_per_row[2] - 8; + memcpy(p, s, sx); + s += 16; /* Skip one line */ + p += priv->bytes_per_row[2]; } } @@ -136,37 +155,43 @@ static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv) * | 2 | * `---' */ -static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv) +static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv, int sx, int sy) { const unsigned char *s, *y; - unsigned char *p; + unsigned char *p, *pr; int i,j; p = priv->plane[0]; y = priv->Y; - for (i=0; i<16; i++) + for (i = sy; i > 0; i++) { - memcpy(p, y, 8); + memcpy(p, y, sx); p+=priv->bytes_per_row[0]; y+=8; } - p = priv->plane[1]; + pr = priv->plane[1]; s = priv->Cb; - for (i=0; i<8; i++) + for (i = sy; i > 0; i -= 2) { - for (j=0; j<8; j+=2, s+=2) + p = pr; + for (j = sx; j > 0; j -= 2) { *p++ = *s; - p += priv->bytes_per_row[1] - 4; + s += 2; + } + pr += priv->bytes_per_row[1]; } - p = priv->plane[2]; + pr = priv->plane[2]; s = priv->Cr; for (i=0; i<8; i++) { - for (j=0; j<8; j+=2, s+=2) + p = pr; + for (j = sx; j > 0; j -= 2) { *p++ = *s; - p += priv->bytes_per_row[2] - 4; + s += 2; + } + pr += priv->bytes_per_row[2] - 4; } } @@ -178,35 +203,37 @@ static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv) * | 3 | 4 | * `-------' */ -static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv) +static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv, int sx, int sy) { unsigned char *p; const unsigned char *s, *y1; - int i; + unsigned int i; p = priv->plane[0]; y1 = priv->Y; - for (i=0; i<16; i++) + for (i = sy; i > 0; i--) { - memcpy(p, y1, 16); + memcpy(p, y1, sx); p += priv->bytes_per_row[0]; y1 += 16; } + sx = (sx+1) >> 1; + p = priv->plane[1]; s = priv->Cb; - for (i=0; i<8; i++) + for (i = sy; i > 0; i -= 2) { - memcpy(p, s, 8); + memcpy(p, s, sx); s += 8; p += priv->bytes_per_row[1]; } p = priv->plane[2]; s = priv->Cr; - for (i=0; i<8; i++) + for (i = sy; i > 0; i -= 2) { - memcpy(p, s, 8); + memcpy(p, s, sx); s += 8; p += priv->bytes_per_row[2]; } @@ -216,26 +243,32 @@ static int initialize_yuv420p(struct jdec_private *priv, unsigned int *bytes_per_blocklines, unsigned int *bytes_per_mcu) { - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height); - if (priv->components[1] == NULL) - priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4); - if (priv->components[2] == NULL) - priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4); + int half_height = (priv->height + 1) >> 2; + int half_width = (priv->width + 1) >> 2; + if (!priv->bytes_per_row[0]) priv->bytes_per_row[0] = priv->width; + if (!priv->components[0]) + priv->components[0] = malloc(priv->height * priv->bytes_per_row[0]); + if (!priv->bytes_per_row[1]) - priv->bytes_per_row[1] = priv->width/2; + priv->bytes_per_row[1] = half_width; + if (!priv->components[1]) + priv->components[1] = malloc(half_height * priv->bytes_per_row[1]); + if (!priv->bytes_per_row[2]) - priv->bytes_per_row[2] = priv->width/2; + priv->bytes_per_row[2] = half_width; + if (!priv->components[2]) + priv->components[2] = malloc(half_height * priv->bytes_per_row[2]); - bytes_per_blocklines[0] = priv->bytes_per_row[0]; - bytes_per_blocklines[1] = priv->bytes_per_row[1]/2; - bytes_per_blocklines[2] = priv->bytes_per_row[2]/2; bytes_per_mcu[0] = 8; bytes_per_mcu[1] = 4; bytes_per_mcu[2] = 4; + bytes_per_blocklines[0] = priv->width << 3; + bytes_per_blocklines[1] = half_width << 2; + bytes_per_blocklines[2] = half_width << 2; + /* Return nonzero on failure */ return !priv->components[0] || !priv->components[1] || !priv->components[2]; } diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c index 815f984c..256c8247 100644 --- a/com32/lib/sys/vesa/background.c +++ b/com32/lib/sys/vesa/background.c @@ -44,9 +44,9 @@ aligned dwords. */ static void draw_background_line(int line, int start, int npixels) { - uint32_t *bgptr = &__vesacon_background[line][start]; + uint32_t *bgptr = &__vesacon_background[line*__vesa_info.mi.h_res+start]; unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel; - size_t fbptr = line * __vesa_info.mi.logical_scan + start * bytes_per_pixel; + size_t fbptr = line * __vesa_info.mi.logical_scan + start*bytes_per_pixel; __vesacon_copy_to_screen(fbptr, bgptr, npixels); } @@ -60,15 +60,17 @@ static void draw_background(void) const int right_border = VIDEO_BORDER + (TEXT_PIXEL_COLS % FONT_WIDTH); for (i = 0; i < VIDEO_BORDER; i++) - draw_background_line(i, 0, VIDEO_X_SIZE); + draw_background_line(i, 0, __vesa_info.mi.h_res); - for (i = VIDEO_BORDER; i < VIDEO_Y_SIZE - bottom_border; i++) { + for (i = VIDEO_BORDER; i < __vesa_info.mi.v_res - bottom_border; i++) { draw_background_line(i, 0, VIDEO_BORDER); - draw_background_line(i, VIDEO_X_SIZE - right_border, right_border); + draw_background_line(i, __vesa_info.mi.h_res - right_border, + right_border); } - for (i = VIDEO_Y_SIZE - bottom_border; i < VIDEO_Y_SIZE; i++) - draw_background_line(i, 0, VIDEO_X_SIZE); + for (i = __vesa_info.mi.v_res - bottom_border; + i < __vesa_info.mi.v_res; i++) + draw_background_line(i, 0, __vesa_info.mi.h_res); __vesacon_redraw_text(); } @@ -82,7 +84,7 @@ static int read_png_file(FILE * fp) png_color_16p image_background; static const png_color_16 my_background = { 0, 0, 0, 0, 0 }; #endif - png_bytep row_pointers[VIDEO_Y_SIZE]; + png_bytep row_pointers[__vesa_info.mi.v_res], rp; int passes; int i; int rv = -1; @@ -98,7 +100,7 @@ static int read_png_file(FILE * fp) png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); - png_set_user_limits(png_ptr, VIDEO_X_SIZE, VIDEO_Y_SIZE); + png_set_user_limits(png_ptr, __vesa_info.mi.h_res, __vesa_info.mi.v_res); png_read_info(png_ptr, info_ptr); @@ -138,8 +140,11 @@ static int read_png_file(FILE * fp) #endif /* Whew! Now we should get the stuff we want... */ - for (i = 0; i < (int)info_ptr->height; i++) - row_pointers[i] = (void *)__vesacon_background[i]; + rp = (png_bytep)__vesacon_background; + for (i = 0; i < (int)info_ptr->height; i++) { + row_pointers[i] = rp; + rp += __vesa_info.mi.h_res << 2; + } passes = png_set_interlace_handling(png_ptr); @@ -157,6 +162,7 @@ err: static int jpeg_sig_cmp(uint8_t * bytes, int len) { (void)len; + return (bytes[0] == 0xff && bytes[1] == 0xd8) ? 0 : -1; } @@ -183,12 +189,12 @@ static int read_jpeg_file(FILE * fp, uint8_t * header, int len) goto err; tinyjpeg_get_size(jdec, &width, &height); - if (width > VIDEO_X_SIZE || height > VIDEO_Y_SIZE) + if (width > __vesa_info.mi.h_res || height > __vesa_info.mi.v_res) goto err; - components[0] = (void *)&__vesacon_background[0]; + components[0] = (void *)__vesacon_background; tinyjpeg_set_components(jdec, components, 1); - bytes_per_row[0] = VIDEO_X_SIZE << 2; + bytes_per_row[0] = __vesa_info.mi.h_res << 2; tinyjpeg_set_bytes_per_row(jdec, bytes_per_row, 1); tinyjpeg_decode(jdec, TINYJPEG_FMT_BGRA32); @@ -217,9 +223,11 @@ int vesacon_default_background(void) if (__vesacon_pixel_format == PXF_NONE) return 0; /* Not in graphics mode */ - for (y = 0, dy = -VIDEO_Y_SIZE / 2; y < VIDEO_Y_SIZE; y++, dy++) { + for (y = 0, dy = -__vesa_info.mi.v_res / 2; + y < __vesa_info.mi.v_res; y++, dy++) { dy2 = dy * dy; - for (x = 0, dx = -VIDEO_X_SIZE / 2; x < VIDEO_X_SIZE; x++, dx++) { + for (x = 0, dx = -__vesa_info.mi.h_res / 2; + x < __vesa_info.mi.h_res; x++, dx++) { k = __vesacon_linear_to_srgb[500 + ((dx * dx + dy2) >> 6)]; bgptr[0] = k; /* Blue */ bgptr[1] = k; /* Green */ @@ -236,7 +244,7 @@ int vesacon_default_background(void) int vesacon_set_background(unsigned int rgb) { void *bgptr = __vesacon_background; - unsigned int count = VIDEO_X_SIZE * VIDEO_Y_SIZE; + unsigned int count = __vesa_info.mi.h_res * __vesa_info.mi.v_res; if (__vesacon_pixel_format == PXF_NONE) return 0; /* Not in graphics mode */ @@ -265,7 +273,8 @@ static inline int lss16_sig_cmp(const void *header, int len) return 1; return !(h->magic == LSS16_MAGIC && - h->xsize <= VIDEO_X_SIZE && h->ysize <= VIDEO_Y_SIZE); + h->xsize <= __vesa_info.mi.h_res && + h->ysize <= __vesa_info.mi.v_res); } static int read_lss16_file(FILE * fp, const void *header, int header_len) @@ -283,7 +292,7 @@ static int read_lss16_file(FILE * fp, const void *header, int header_len) st_c2, } state; int i, x, y; - uint32_t *bgptr = (void *)__vesacon_background; + uint32_t *bgptr = __vesacon_background; /* Assume the header, 8 bytes, has already been loaded. */ if (header_len != 8) @@ -295,7 +304,8 @@ static int read_lss16_file(FILE * fp, const void *header, int header_len) return -1; colors[i] = (((rgb[0] & 63) * 255 / 63) << 16) + - (((rgb[1] & 63) * 255 / 63) << 8) + ((rgb[2] & 63) * 255 / 63); + (((rgb[1] & 63) * 255 / 63) << 8) + + ((rgb[2] & 63) * 255 / 63); } /* By spec, the state machine is per row */ @@ -356,12 +366,12 @@ do_run: } /* Zero-fill rest of row */ - i = VIDEO_X_SIZE - x; + i = __vesa_info.mi.h_res - x; asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory"); } /* Zero-fill rest of screen */ - i = (VIDEO_Y_SIZE - y) * VIDEO_X_SIZE; + i = (__vesa_info.mi.v_res - y) * __vesa_info.mi.h_res; asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory"); return 0; @@ -404,7 +414,7 @@ err: int __vesacon_init_background(void) { - /* The BSS clearing has already cleared __vesacon_background */ + /* __vesacon_background was cleared by calloc() */ /* The VESA BIOS has already cleared the screen */ return 0; diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c index 4b46d678..92d89018 100644 --- a/com32/lib/sys/vesa/drawtxt.c +++ b/com32/lib/sys/vesa/drawtxt.c @@ -27,6 +27,7 @@ #include <inttypes.h> #include <colortbl.h> +#include <string.h> #include "vesa.h" #include "video.h" #include "fill.h" @@ -81,25 +82,20 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) struct vesa_char *rowptr, *rowsptr, *cptr, *csptr; unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel; unsigned long pixel_offset; - uint32_t row_buffer[VIDEO_X_SIZE], *rowbufptr; + uint32_t row_buffer[__vesa_info.mi.h_res], *rowbufptr; size_t fbrowptr; uint8_t sha; - bgrowptr = - &__vesacon_background[row * height + VIDEO_BORDER][col * width + - VIDEO_BORDER]; - - pixel_offset = ((row * height + VIDEO_BORDER) * VIDEO_X_SIZE) + + pixel_offset = ((row * height + VIDEO_BORDER) * __vesa_info.mi.h_res) + (col * width + VIDEO_BORDER); + bgrowptr = &__vesacon_background[pixel_offset]; fbrowptr = (row * height + VIDEO_BORDER) * __vesa_info.mi.logical_scan + (col * width + VIDEO_BORDER) * bytes_per_pixel; /* Note that we keep a 1-character guard area around the real text area... */ - rowptr = - &__vesacon_text_display[(row + 1) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2) + - (col + 1)]; - rowsptr = rowptr - ((TEXT_PIXEL_COLS / FONT_WIDTH + 2) + 1); + rowptr = &__vesacon_text_display[(row+1)*(__vesacon_text_cols+2)+(col+1)]; + rowsptr = rowptr - ((__vesacon_text_cols+2)+1); pixrow = 0; pixsrow = height - 1; @@ -159,7 +155,8 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) } /* If this pixel is raised, use the offsetted value */ - bgval = (chxbits & 0x80) ? bgptr[VIDEO_X_SIZE + 1] : *bgptr; + bgval = (chxbits & 0x80) + ? bgptr[__vesa_info.mi.h_res + 1] : *bgptr; bgptr++; /* If this pixel is set, use the fg color, else the bg color */ @@ -180,15 +177,15 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols) /* Copy to frame buffer */ __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr - row_buffer); - bgrowptr += VIDEO_X_SIZE; + bgrowptr += __vesa_info.mi.h_res; fbrowptr += __vesa_info.mi.logical_scan; if (++pixrow == height) { - rowptr += TEXT_PIXEL_COLS / FONT_WIDTH + 2; + rowptr += __vesacon_text_cols + 2; pixrow = 0; } if (++pixsrow == height) { - rowsptr += TEXT_PIXEL_COLS / FONT_WIDTH + 2; + rowsptr += __vesacon_text_cols + 2; pixsrow = 0; } } @@ -232,7 +229,7 @@ void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr) { int y; struct vesa_char *ptr = &__vesacon_text_display - [(y0 + 1) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2) + (x0 + 1)]; + [(y0 + 1) * (__vesacon_text_cols + 2) + (x0 + 1)]; struct vesa_char fill = { .ch = ' ', .attr = attr, @@ -241,7 +238,7 @@ void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr) for (y = y0; y <= y1; y++) { vesacon_fill(ptr, fill, ncols); - ptr += TEXT_PIXEL_COLS / FONT_WIDTH + 2; + ptr += __vesacon_text_cols + 2; } vesacon_touch(y0, x0, y1 - y0 + 1, ncols); @@ -251,11 +248,11 @@ void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr) void __vesacon_scroll_up(int nrows, attr_t attr) { struct vesa_char *fromptr = &__vesacon_text_display - [(nrows + 1) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2)]; + [(nrows + 1) * (__vesacon_text_cols + 2)]; struct vesa_char *toptr = &__vesacon_text_display - [(TEXT_PIXEL_COLS / FONT_WIDTH + 2)]; + [(__vesacon_text_cols + 2)]; int dword_count = - (__vesacon_text_rows - nrows) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2); + (__vesacon_text_rows - nrows) * (__vesacon_text_cols + 2); struct vesa_char fill = { .ch = ' ', .attr = attr, @@ -263,18 +260,18 @@ void __vesacon_scroll_up(int nrows, attr_t attr) toptr = copy_dword(toptr, fromptr, dword_count); - dword_count = nrows * (TEXT_PIXEL_COLS / FONT_WIDTH + 2); + dword_count = nrows * (__vesacon_text_cols + 2); vesacon_fill(toptr, fill, dword_count); - vesacon_touch(0, 0, __vesacon_text_rows, TEXT_PIXEL_COLS / FONT_WIDTH); + vesacon_touch(0, 0, __vesacon_text_rows, __vesacon_text_cols); } /* Draw one character text at a specific area of the screen */ void __vesacon_write_char(int x, int y, uint8_t ch, attr_t attr) { struct vesa_char *ptr = &__vesacon_text_display - [(y + 1) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2) + (x + 1)]; + [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)]; ptr->ch = ch; ptr->attr = attr; @@ -285,7 +282,7 @@ void __vesacon_write_char(int x, int y, uint8_t ch, attr_t attr) void __vesacon_set_cursor(int x, int y, int visible) { struct vesa_char *ptr = &__vesacon_text_display - [(y + 1) * (TEXT_PIXEL_COLS / FONT_WIDTH + 2) + (x + 1)]; + [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)]; if (cursor_pointer) vesacon_touch(cursor_y, cursor_x, 1, 1); @@ -309,13 +306,12 @@ void __vesacon_init_cursor(int font_height) if (r0 < 0) r0 = 0; - /* cursor_pattern is assumed to be all zero */ + memset(cursor_pattern, 0, font_height); cursor_pattern[r0] = 0xff; cursor_pattern[r0 + 1] = 0xff; } void __vesacon_redraw_text(void) { - vesacon_update_characters(0, 0, __vesacon_text_rows, - TEXT_PIXEL_COLS / FONT_WIDTH); + vesacon_update_characters(0, 0, __vesacon_text_rows, __vesacon_text_cols); } diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c index 9254683b..0221fcf7 100644 --- a/com32/lib/sys/vesa/initvesa.c +++ b/com32/lib/sys/vesa/initvesa.c @@ -46,12 +46,14 @@ struct vesa_info __vesa_info; struct vesa_char *__vesacon_text_display; -int __vesacon_font_height, __vesacon_text_rows; +int __vesacon_font_height; +int __vesacon_text_rows; +int __vesacon_text_cols; enum vesa_pixel_format __vesacon_pixel_format = PXF_NONE; unsigned int __vesacon_bytes_per_pixel; uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT]; -uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE]; +uint32_t *__vesacon_background, *__vesacon_shadowfb; static void unpack_font(uint8_t * dst, uint8_t * src, int height) { @@ -87,7 +89,7 @@ static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi) return 0; /* Nope... */ } -static int vesacon_set_mode(void) +static int vesacon_set_mode(int x, int y) { com32sys_t rm; uint8_t *rom_font; @@ -96,6 +98,16 @@ static int vesacon_set_mode(void) struct vesa_mode_info *mi; enum vesa_pixel_format pxf, bestpxf; + /* Free any existing data structures */ + if (__vesacon_background) { + free(__vesacon_background); + __vesacon_background = NULL; + } + if (__vesacon_shadowfb) { + free(__vesacon_shadowfb); + __vesacon_shadowfb = NULL; + } + /* Allocate space in the bounce buffer for these structures */ gi = &((struct vesa_info *)__com32.cs_bounce)->gi; mi = &((struct vesa_info *)__com32.cs_bounce)->mi; @@ -121,7 +133,7 @@ static int vesacon_set_mode(void) /* Copy general info */ memcpy(&__vesa_info.gi, gi, sizeof *gi); - /* Search for a 640x480 mode with a suitable color and memory model... */ + /* Search for the proper mode with a suitable color and memory model... */ mode_ptr = GET_PTR(gi->video_mode_ptr); bestmode = 0; @@ -159,8 +171,8 @@ static int vesacon_set_mode(void) if ((mi->mode_attr & 0x001b) != 0x001b) continue; - /* Must be 640x480 */ - if (mi->h_res != VIDEO_X_SIZE || mi->v_res != VIDEO_Y_SIZE) + /* Must be the chosen size */ + if (mi->h_res != x || mi->v_res != y) continue; /* We don't support multibank (interlaced memory) modes */ @@ -242,9 +254,6 @@ static int vesacon_set_mode(void) } unpack_font((uint8_t *) __vesacon_graphics_font, rom_font, __vesacon_font_height); - __vesacon_text_rows = - (VIDEO_Y_SIZE - 2 * VIDEO_BORDER) / __vesacon_font_height; - __vesacon_init_cursor(__vesacon_font_height); /* Now set video mode */ rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */ @@ -255,6 +264,9 @@ static int vesacon_set_mode(void) if (rm.eax.w[0] != 0x004F) return 9; /* Failed to set mode */ + __vesacon_background = calloc(mi->h_res*mi->v_res, 4); + __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4); + __vesacon_init_copy_to_screen(); /* Tell syslinux we changed video mode */ @@ -266,8 +278,8 @@ static int vesacon_set_mode(void) However, that would assume all systems that claim to handle text output in VESA modes actually do that... */ rm.ebx.w[0] = 0x000f; - rm.ecx.w[0] = VIDEO_X_SIZE; - rm.edx.w[0] = VIDEO_Y_SIZE; + rm.ecx.w[0] = mi->h_res; + rm.edx.w[0] = mi->v_res; __intcall(0x22, &rm, NULL); __vesacon_pixel_format = bestpxf; @@ -284,8 +296,12 @@ static int init_text_display(void) .attr = 0, }; - nchars = (TEXT_PIXEL_ROWS / __vesacon_font_height + 2) * - (TEXT_PIXEL_COLS / FONT_WIDTH + 2); + if (__vesacon_text_display) + free(__vesacon_text_display); + + __vesacon_text_cols = TEXT_PIXEL_COLS / FONT_WIDTH; + __vesacon_text_rows = TEXT_PIXEL_ROWS / __vesacon_font_height; + nchars = (__vesacon_text_cols+2) * (__vesacon_text_rows+2); __vesacon_text_display = ptr = malloc(nchars * sizeof(struct vesa_char)); @@ -293,11 +309,12 @@ static int init_text_display(void) return -1; vesacon_fill(ptr, def_char, nchars); + __vesacon_init_cursor(__vesacon_font_height); return 0; } -int __vesacon_init(void) +int __vesacon_init(int x, int y) { int rv; @@ -305,7 +322,7 @@ int __vesacon_init(void) if (x86_init_fpu()) return 10; - rv = vesacon_set_mode(); + rv = vesacon_set_mode(x, y); if (rv) return rv; diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h index b02b5ae7..0bd1abff 100644 --- a/com32/lib/sys/vesa/video.h +++ b/com32/lib/sys/vesa/video.h @@ -29,17 +29,18 @@ #define LIB_SYS_VESA_VIDEO_H #include <colortbl.h> +#include "vesa.h" #define FONT_MAX_CHARS 256 #define FONT_MAX_HEIGHT 32 #define FONT_WIDTH 8 -#define VIDEO_X_SIZE 640 -#define VIDEO_Y_SIZE 480 +#define DEFAULT_VESA_X_SIZE 640 +#define DEFAULT_VESA_Y_SIZE 480 #define VIDEO_BORDER 8 -#define TEXT_PIXEL_ROWS (VIDEO_Y_SIZE-2*VIDEO_BORDER) -#define TEXT_PIXEL_COLS (VIDEO_X_SIZE-2*VIDEO_BORDER) +#define TEXT_PIXEL_ROWS (__vesa_info.mi.v_res - 2*VIDEO_BORDER) +#define TEXT_PIXEL_COLS (__vesa_info.mi.h_res - 2*VIDEO_BORDER) typedef uint16_t attr_t; @@ -60,24 +61,26 @@ enum vesa_pixel_format { }; extern enum vesa_pixel_format __vesacon_pixel_format; extern unsigned int __vesacon_bytes_per_pixel; -typedef const void *(*__vesacon_format_pixels_t) (void *, const uint32_t *, - size_t); +typedef const void *(*__vesacon_format_pixels_t) + (void *, const uint32_t *, size_t); extern __vesacon_format_pixels_t __vesacon_format_pixels; extern const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE]; extern struct vesa_char *__vesacon_text_display; -extern int __vesacon_font_height, __vesacon_text_rows; +extern int __vesacon_font_height; +extern int __vesacon_text_rows; +extern int __vesacon_text_cols; extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT]; -extern uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE]; -extern uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE]; +extern uint32_t *__vesacon_background; +extern uint32_t *__vesacon_shadowfb; extern const uint16_t __vesacon_srgb_to_linear[256]; extern const uint8_t __vesacon_linear_to_srgb[4080]; int __vesacon_init_background(void); int vesacon_load_background(const char *); -int __vesacon_init(void); +int __vesacon_init(int, int); void __vesacon_init_cursor(int); void __vesacon_erase(int, int, int, int, attr_t); void __vesacon_scroll_up(int, attr_t); diff --git a/com32/lib/sys/vesacon_write.c b/com32/lib/sys/vesacon_write.c index f0fc845f..e85aba88 100644 --- a/com32/lib/sys/vesacon_write.c +++ b/com32/lib/sys/vesacon_write.c @@ -61,7 +61,6 @@ static struct ansi_ops op = { }; static struct term_info ti = { - .cols = TEXT_PIXEL_COLS / FONT_WIDTH, .disabled = 0, .ts = &ts, .op = &op @@ -71,6 +70,20 @@ static struct term_info ti = { reinitialization. */ static int vesacon_counter = 0; +static struct { + int x, y; +} vesacon_resolution = { + .x = DEFAULT_VESA_X_SIZE, + .y = DEFAULT_VESA_Y_SIZE, +}; + +/* Set desired resolution - requires a full close/open cycle */ +void vesacon_set_resolution(int x, int y) +{ + vesacon_resolution.x = x; + vesacon_resolution.y = y; +} + /* Common setup */ int __vesacon_open(struct file_info *fp) { @@ -84,7 +97,7 @@ int __vesacon_open(struct file_info *fp) ti.cols = 80; } else { /* Switch mode */ - if (__vesacon_init()) { + if (__vesacon_init(vesacon_resolution.x, vesacon_resolution.y)) { vesacon_counter = -1; return EAGAIN; } @@ -92,6 +105,7 @@ int __vesacon_open(struct file_info *fp) /* Initial state */ __ansi_init(&ti); ti.rows = __vesacon_text_rows; + ti.cols = __vesacon_text_cols; } } else if (vesacon_counter == -1) { return EAGAIN; |