From 9936e65e6dba6480f7cb21d97e569f36f5113f78 Mon Sep 17 00:00:00 2001 From: Michael Giacomelli Date: Tue, 29 Sep 2026 20:37:25 -0400 Subject: [PATCH] imageviewer/jpegp: decode RGB images jpegp converted every image from YCbCr, so RGB JPEGs showed scrambled colours. That affects progressive RGB files, and now also baseline RGB files the jpeg decoder rejects and hands on to jpegp, such as RGB with the R component sampled 2x2. Record the JFIF and Adobe APP14 markers, decide the colour space with the same rule as the other decoders, and skip the YUV conversion for RGB. Co-Authored-By: Claude Opus 5.5 Change-Id: If023eeb612b7f8a891d21fbe0070ab43c5a08f17 --- apps/plugins/imageviewer/jpegp/jpeg81.c | 12 ++++++++++-- apps/plugins/imageviewer/jpegp/jpeg81.h | 4 ++++ apps/plugins/imageviewer/jpegp/jpegp.c | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.c b/apps/plugins/imageviewer/jpegp/jpeg81.c index 83f4e287fa..b4849da6f7 100644 --- a/apps/plugins/imageviewer/jpegp/jpeg81.c +++ b/apps/plugins/imageviewer/jpegp/jpeg81.c @@ -43,6 +43,7 @@ jpeg81.c #include "GETC.h" #include "rb_glue.h" #include "jpeg81.h" +#include "jpeg_common.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -982,8 +983,15 @@ extern enum JPEGENUM JPEGDecode(struct JPEGD *j) } else if ( (marker & 0xf0) == 0xE0 ) // APPn E0..EF { - int La= GETWbi(); - SEEK(La-2); + int La= GETWbi()-2; + int n= 0; + if ( marker == 0xE0 || marker == 0xEE ) // JFIF, Adobe: colour space + { + unsigned char id[12]; + for ( ; n < La && n < 12; n++ ) id[n]= GETC(); + jpeg_app_colorspace(marker, id, n, &j->jfif, &j->adobe); + } + SEEK(La-n); printf("APP%d\n", marker&15); } else if ( marker == 0xFE ) // COM diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.h b/apps/plugins/imageviewer/jpegp/jpeg81.h index e265d84926..8d9c2a04a3 100644 --- a/apps/plugins/imageviewer/jpegp/jpeg81.h +++ b/apps/plugins/imageviewer/jpegp/jpeg81.h @@ -34,6 +34,8 @@ enum JPEGENUM { JPEGENUMERR_COMPNOTFOUND, // Scan component selector (Csj) not found among Component identifiers (Ci) }; +#include + typedef short TCOEF; // 16-bit coefficients typedef TCOEF DU[64]; // The DATA UNIT typedef unsigned short TSAMP; // Lossless 'coefficients' are unsigned @@ -103,6 +105,8 @@ struct JPEGD { // The JPEG DECODER OBJECT void *jpeg_mem; // <-- free me int Hmax, Vmax; // for conversion + bool jfif; // saw a JFIF APP0 marker + unsigned char adobe; // Adobe APP14 transform flag + 1, 0 if none int mcu_width; int mcu_height; int mcu_total; // covers the whole image diff --git a/apps/plugins/imageviewer/jpegp/jpegp.c b/apps/plugins/imageviewer/jpegp/jpegp.c index a5883e3a28..955399b2f6 100644 --- a/apps/plugins/imageviewer/jpegp/jpegp.c +++ b/apps/plugins/imageviewer/jpegp/jpegp.c @@ -4,6 +4,7 @@ #include "rb_glue.h" #include "../imageviewer.h" +#include "jpeg_common.h" /**************** begin Application ********************/ @@ -217,6 +218,8 @@ static int get_image(struct image_info *info, int frame, int ds) int v1 = j->Vmax / j->Components[1].Vi; int h2 = j->Hmax / j->Components[2].Hi; int v2 = j->Vmax / j->Components[2].Vi; + bool rgb = jpeg_is_rgb(j->jfif, j->adobe, j->Components[0].Ci, + j->Components[1].Ci, j->Components[2].Ci); int x, y; int max_y = info->height * ds; @@ -264,6 +267,9 @@ static int get_image(struct image_info *info, int frame, int ds) c2 = (sumV + area/2) / area; } + if (rgb) // components are R, G, B: no conversion + *bmp++= FB_RGBPACK(c0, c1, c2); + else // ITU BT.601 full-range YUV-to-RGB integer approximation { int y = (c0 << 5) + 16;