kwo pushed a commit to branch master.

http://git.enlightenment.org/legacy/imlib2.git/commit/?id=fb0cce4caf5e076cad5947e15a4656facbd54175

commit fb0cce4caf5e076cad5947e15a4656facbd54175
Author: Olof-Joachim Frahm (欧雅福) <[email protected]>
Date:   Thu Nov 14 16:09:55 2019 +0100

    tga loader: implement handling of palette
    
    Summary:
    implemented 8 bit color mapped images with 24/32bpp palette.
    
    This is coming from an issue on [[ https://github.com/derf/feh/issues/491 | 
feh ]] to support indexed TGA images. Written by [[ https://github.com/rofl0r | 
rofl0r ]], I'm forwarding it because I already have the tools for submission 
set up.
    
    N.b. I'm not terribly familiar with the particular code style, if there's 
anything to format differently I'm happy to update.
    
    Test Plan:
    - Compared [[ https://0x0.st/zgB4.tga | example file ]] with known good in 
GIMP, looks okay.
    - Tested that said example file doesn't load without this patch (in feh, 
which uses Imlib2).
    
    Reviewers: kwo
    
    Differential Revision: https://phab.enlightenment.org/D10618
---
 src/modules/loaders/loader_tga.c | 80 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 10 deletions(-)

diff --git a/src/modules/loaders/loader_tga.c b/src/modules/loaders/loader_tga.c
index 88818ee..0713911 100644
--- a/src/modules/loaders/loader_tga.c
+++ b/src/modules/loaders/loader_tga.c
@@ -192,10 +192,10 @@ load(ImlibImage * im, ImlibProgressFunction progress,
    tga_footer         *footer;
 
    unsigned long       datasize;
-   unsigned char      *bufptr, *bufend;
+   unsigned char      *bufptr, *bufend, *palette = 0;
    DATA32             *dataptr;
 
-   int                 y;
+   int                 y, palcnt = 0, palbpp = 0;
 
    fd = open(im->real_file, O_RDONLY);
    if (fd < 0)
@@ -245,11 +245,13 @@ load(ImlibImage * im, ImlibProgressFunction progress,
 
    switch (header->imageType)
      {
+     case TGA_TYPE_MAPPED_RLE:
      case TGA_TYPE_COLOR_RLE:
      case TGA_TYPE_GRAY_RLE:
         rle = 1;
         break;
 
+     case TGA_TYPE_MAPPED:
      case TGA_TYPE_COLOR:
      case TGA_TYPE_GRAY:
         rle = 0;
@@ -298,6 +300,22 @@ load(ImlibImage * im, ImlibProgressFunction progress,
    datasize = ss.st_size - sizeof(tga_header) - header->idLength -
       (footer_present ? sizeof(tga_footer) : 0);
 
+   if (header->imageType == TGA_TYPE_MAPPED ||
+       header->imageType == TGA_TYPE_MAPPED_RLE)
+     {
+        if (bpp != 8)
+           goto quit;
+        palette = filedata;
+        palcnt = (header->colorMapLengthHi << 8) | header->colorMapLengthLo;
+        palbpp = header->colorMapSize / 8;      /* bytes per palette entry */
+        if (palbpp < 3 || palbpp > 4)
+           goto quit;           /* only supporting 24/32bit palettes */
+        int                 palbytes = palcnt * palbpp;
+
+        filedata = ((unsigned char *)filedata) + palbytes;
+        datasize -= palbytes;
+     }
+
    /* buffer is ready for parsing */
 
    /* bufptr is the next byte to be read from the buffer */
@@ -341,9 +359,23 @@ load(ImlibImage * im, ImlibProgressFunction progress,
                        bufptr += 3;
                        break;
 
-                    case 8:    /* 8-bit grayscale */
-                       *dataptr++ =
-                          PIXEL_ARGB(0xff, bufptr[0], bufptr[0], bufptr[0]);
+                    case 8:    /* 8-bit grayscale or palette */
+                       if (!palette)
+                         {
+                            *dataptr++ =
+                               PIXEL_ARGB(0xff, bufptr[0], bufptr[0],
+                                          bufptr[0]);
+                         }
+                       else
+                         {
+                            if (*bufptr >= palcnt)
+                               goto quit;
+                            *dataptr++ =
+                               PIXEL_ARGB(0xff,
+                                          palette[*bufptr * palbpp + 2],
+                                          palette[*bufptr * palbpp + 1],
+                                          palette[*bufptr * palbpp + 0]);
+                         }
                        bufptr += 1;
                        break;
                     }
@@ -393,8 +425,23 @@ load(ImlibImage * im, ImlibProgressFunction progress,
                     case 8:
                        red = *bufptr++;
                        alpha = 0xff;
+                       if (palette && red >= palcnt)
+                          goto quit;
+
                        for (i = 0; (i < count) && (dataptr < final_pixel); i++)
-                          *dataptr++ = PIXEL_ARGB(alpha, red, red, red);
+                          if (!palette)
+                            {
+                               *dataptr++ = PIXEL_ARGB(alpha, red, red, red);
+                            }
+                          else
+                            {
+                               *dataptr++ =
+                                  PIXEL_ARGB(alpha,
+                                             palette[red * palbpp + 2],
+                                             palette[red * palbpp + 1],
+                                             palette[red * palbpp + 0]);
+                            }
+
                        break;
                     }
                }                /* end if (RLE packet) */
@@ -421,10 +468,23 @@ load(ImlibImage * im, ImlibProgressFunction progress,
                             bufptr += 3;
                             break;
 
-                         case 8:       /* 8-bit grayscale */
-                            *dataptr++ =
-                               PIXEL_ARGB(0xff, bufptr[0], bufptr[0],
-                                          bufptr[0]);
+                         case 8:       /* 8-bit grayscale or palette */
+                            if (!palette)
+                              {
+                                 *dataptr++ =
+                                    PIXEL_ARGB(0xff, bufptr[0], bufptr[0],
+                                               bufptr[0]);
+                              }
+                            else
+                              {
+                                 if (bufptr[0] >= palcnt)
+                                    goto quit;
+                                 *dataptr++ =
+                                    PIXEL_ARGB(0xff,
+                                               palette[*bufptr * palbpp + 2],
+                                               palette[*bufptr * palbpp + 1],
+                                               palette[*bufptr * palbpp + 0]);
+                              }
                             bufptr += 1;
                             break;
                          }

-- 


Reply via email to