File xv-more-bmp-formats.patch of Package xv

From e1d01328aa87af48e17947304fe5bf08a9096419 Mon Sep 17 00:00:00 2001
From: "Matthew A. Lukowicz" <matt@pancakehut>
Date: Wed, 7 Feb 2024 00:08:25 -0500
Subject: [PATCH] Add support for more PC BMP formats.

---
 src/xvbmp.c |  203 ++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 151 insertions(+), 52 deletions(-)

--- src/xvbmp.c
+++ src/xvbmp.c	2024-02-07 11:41:04.894069678 +0000
@@ -26,9 +26,13 @@
 #define BI_JPEG      4   /* BMP version 5 (not yet supported) */
 #define BI_PNG       5   /* BMP version 5 (not yet supported) */
 
-#define WIN_OS2_OLD 12
-#define WIN_NEW     40
-#define OS2_NEW     64
+#define BMPV2       12
+#define BMPV3       40
+#define MS_ADOBE_V2 52	/* FIXME: Loads with corrupt colors */
+#define MS_ADOBE_V3 56	/* FIXME: Loads with corrput colors */
+#define OS2_BMPV2   64
+#define BMPV4       108
+#define BMPV5	    124
 
 #if (defined(UINT_MAX) && UINT_MAX != 0xffffffffU)
 #  error XV's BMP code requires 32-bit unsigned integer type, but u_int isn't
@@ -36,14 +40,14 @@
 
 static long filesize;
 
-static int   loadBMP1   PARM((FILE *, byte *, u_int, u_int));
-static int   loadBMP4   PARM((FILE *, byte *, u_int, u_int, u_int));
-static int   loadBMP8   PARM((FILE *, byte *, u_int, u_int, u_int));
-static int   loadBMP16  PARM((FILE *, byte *, u_int, u_int, u_int *));
-static int   loadBMP24  PARM((FILE *, byte *, u_int, u_int, u_int));
-static int   loadBMP32  PARM((FILE *, byte *, u_int, u_int, u_int *));
-static u_int getshort   PARM((FILE *));
-static u_int getint     PARM((FILE *));
+static int   loadBMP1   PARM((FILE *, byte *, u_int, u_int, int));
+static int   loadBMP4   PARM((FILE *, byte *, u_int, u_int, u_int, int));
+static int   loadBMP8   PARM((FILE *, byte *, u_int, u_int, u_int, int));
+static int   loadBMP16  PARM((FILE *, byte *, u_int, u_int, u_int *, int));
+static int   loadBMP24  PARM((FILE *, byte *, u_int, u_int, u_int, int));
+static int   loadBMP32  PARM((FILE *, byte *, u_int, u_int, u_int *, int));
+static u_int getshort  PARM((FILE *));
+static u_int getint    PARM((FILE *));
 static void  putshort   PARM((FILE *, int));
 static void  putint     PARM((FILE *, int));
 static void  writeBMP1  PARM((FILE *, byte *, int, int));
@@ -62,11 +66,13 @@ int LoadBMP(fname, pinfo)
 /*******************************************/
 {
   FILE       *fp;
-  int        i, c, c1, rv, bPad;
-  u_int      bfSize, bfOffBits, biSize, biWidth, biHeight, biPlanes;
+  int        i, c, c1, rv, bPad, rightsideup = 0;
+  u_int      bfSize, bfOffBits, biSize, biWidth, biPlanes;
   u_int      biBitCount, biCompression, biSizeImage, biXPelsPerMeter;
   u_int      biYPelsPerMeter, biClrUsed, biClrImportant;
+  u_int      npixels;
   u_int      colormask[3];
+  int        biHeight;
   char       buf[512], rgb_bits[16];
   const char *cmpstr, *bname;
   byte       *pic24, *pic8;
@@ -95,7 +101,8 @@ int LoadBMP(fname, pinfo)
 
   biSize          = getint(fp);
 
-  if (biSize == WIN_NEW || biSize == OS2_NEW) {
+  if (biSize == BMPV3 || biSize == OS2_BMPV2 ||biSize == MS_ADOBE_V2 || 
+  	biSize == MS_ADOBE_V3 || biSize == BMPV4 || biSize == BMPV5) {
     biWidth         = getint(fp);
     biHeight        = getint(fp);
     biPlanes        = getshort(fp);
@@ -121,6 +128,22 @@ int LoadBMP(fname, pinfo)
     biClrUsed       = biClrImportant  = 0;
   }
 
+  /* Height could be negative for uncompressed BMP files if data is
+     stored right-side-up */
+  npixels = biWidth * biHeight;
+  if (biWidth != 0 && npixels/biWidth != biHeight && biCompression == BI_RGB) {
+    u_int negHeight, npixels2;
+
+    negHeight = biHeight * -1;
+    npixels2 = biWidth * negHeight;
+
+    if (npixels2/biWidth == negHeight) {
+      biHeight = negHeight;
+      npixels = npixels2;
+      rightsideup = 1;
+    }
+  }
+
   if (DEBUG>1) {
     fprintf(stderr,"\nLoadBMP:\tbfSize=%d, bfOffBits=%d\n",bfSize,bfOffBits);
     fprintf(stderr,"\t\tbiSize=%d, biWidth=%d, biHeight=%d, biPlanes=%d\n",
@@ -140,7 +163,6 @@ int LoadBMP(fname, pinfo)
       biPlanes!=1 || biCompression>BI_PNG ||
       biWidth<=0 || biHeight<=0 ||
       (biClrUsed && biClrUsed > (1 << biBitCount))) {
-
     sprintf(buf,
 	    "Unsupported BMP type (%dx%d, Bits=%d, Colors=%d, Planes=%d, "
 	    "Compr=%d)",
@@ -175,7 +197,7 @@ int LoadBMP(fname, pinfo)
 
 
   bPad = 0;
-  if (biSize != WIN_OS2_OLD) {
+  if (biSize != BMPV2) {
     /* skip ahead to colormap, using biSize */
     c = biSize - 40;    /* 40 bytes read from biSize to biClrImportant */
     for (i=0; i<c; i++)
@@ -191,6 +213,9 @@ int LoadBMP(fname, pinfo)
     bPad -= 12;
   }
 
+  if (biClrUsed > (1 << biBitCount))
+    biClrUsed = (1 << biBitCount);
+
   /* load up colormap, if any */
   if (biBitCount == 1 || biBitCount == 4 || biBitCount == 8) {
     int i, cmaplen;
@@ -200,7 +225,7 @@ int LoadBMP(fname, pinfo)
       pinfo->b[i] = getc(fp);
       pinfo->g[i] = getc(fp);
       pinfo->r[i] = getc(fp);
-      if (biSize != WIN_OS2_OLD) {
+      if (biSize != BMPV2) {
 	getc(fp);
 	bPad -= 4;
       }
@@ -218,7 +243,7 @@ int LoadBMP(fname, pinfo)
     }
   }
 
-  if (biSize != WIN_OS2_OLD) {
+  if (biSize != BMPV2) {
     /* Waste any unused bytes between the colour map (if present)
        and the start of the actual bitmap data. */
 
@@ -231,21 +256,18 @@ int LoadBMP(fname, pinfo)
   /* create pic8 or pic24 */
 
   if (biBitCount==16 || biBitCount==24 || biBitCount==32) {
-    u_int npixels = biWidth * biHeight;
     u_int count = 3 * npixels;
 
     if (biWidth == 0 || biHeight == 0 || npixels/biWidth != biHeight ||
         count/3 != npixels)
       return (bmpError(bname, "image dimensions too large"));
-    pic24 = (byte *) calloc((size_t) count, (size_t) 1);
+    pic24 = (byte *) calloc((size_t) (count + 1), (size_t) 1);
     if (!pic24) return (bmpError(bname, "couldn't malloc 'pic24'"));
   }
   else {
-    u_int npixels = biWidth * biHeight;
-
     if (biWidth == 0 || biHeight == 0 || npixels/biWidth != biHeight)
       return (bmpError(bname, "image dimensions too large"));
-    pic8 = (byte *) calloc((size_t) npixels, (size_t) 1);
+    pic8 = (byte *) calloc((size_t) (npixels + 1), (size_t) 1);
     if (!pic8) return(bmpError(bname, "couldn't malloc 'pic8'"));
   }
 
@@ -254,23 +276,24 @@ int LoadBMP(fname, pinfo)
   /* load up the image */
   switch (biBitCount) {
   case 1:
-    rv = loadBMP1(fp, pic8, biWidth, biHeight);
+    rv = loadBMP1(fp, pic8, biWidth, biHeight, rightsideup);
     break;
   case 4:
-    rv = loadBMP4(fp, pic8, biWidth, biHeight, biCompression);
+    rv = loadBMP4(fp, pic8, biWidth, biHeight, biCompression, rightsideup);
     break;
   case 8:
-    rv = loadBMP8(fp, pic8, biWidth, biHeight, biCompression);
+    rv = loadBMP8(fp, pic8, biWidth, biHeight, biCompression, rightsideup);
     break;
   case 16:
     rv = loadBMP16(fp, pic24, biWidth, biHeight,           /*  v-- BI_RGB */
-                   biCompression == BI_BITFIELDS? colormask : NULL);
+                   biCompression == BI_BITFIELDS? colormask : NULL,
+                   rightsideup);
     break;
   default:
     if (biBitCount == 32 && biCompression == BI_BITFIELDS)
-      rv = loadBMP32(fp, pic24, biWidth, biHeight, colormask);
+      rv = loadBMP32(fp, pic24, biWidth, biHeight, colormask, rightsideup);
     else /* 24 or (32 and BI_RGB) */
-      rv = loadBMP24(fp, pic24, biWidth, biHeight, biBitCount);
+      rv = loadBMP24(fp, pic24, biWidth, biHeight, biBitCount, rightsideup);
     break;
   }
 
@@ -314,9 +337,14 @@ int LoadBMP(fname, pinfo)
   pinfo->frmType = F_BMP;
   pinfo->colType = F_FULLCOLOR;
 
-  sprintf(pinfo->fullInfo, "%sBMP, %d bit%s per pixel%s.  (%ld bytes)",
-	  ((biSize==WIN_OS2_OLD) ? "Old OS/2 " :
-	   (biSize==WIN_NEW)     ? "Windows "  : ""),
+  sprintf(pinfo->fullInfo, "%s, %d bit%s per pixel%s.  (%ld bytes)",
+	  ((biSize==BMPV2)       ? "Windows BMP v2 " :
+	   (biSize==BMPV3)       ? "Windows BMP v3 " :
+	   (biSize==MS_ADOBE_V2) ? "BITMAPV2INFOHEADER " :
+	   (biSize==MS_ADOBE_V3) ? "BITMAPV3INFOHEADER " :
+	   (biSize==OS2_BMPV2)   ? "OS/2 BMP 2.0 " :
+	   (biSize==BMPV4)       ? "Windows BMP v4 " :
+	   (biSize==BMPV5)       ? "Windows BMP v5 " : ""),
 	  biBitCount,  (biBitCount == 1) ? "" : "s",
 	  cmpstr, filesize);
 
@@ -333,19 +361,31 @@ int LoadBMP(fname, pinfo)
 
 
 /*******************************************/
-static int loadBMP1(fp, pic8, w, h)
+static int loadBMP1(fp, pic8, w, h, rightsideup)
      FILE *fp;
      byte *pic8;
      u_int  w,h;
+     int rightsideup;
 {
-  int   i,j,c,bitnum,padw;
+  int   i,j,c,bitnum,padw,ibegin,iend,iinc;
   byte *pp = pic8 + ((h - 1) * w);
   size_t l = w*h;
 
   c = 0;
   padw = ((w + 31)/32) * 32;  /* 'w', padded to be a multiple of 32 */
 
-  for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+  if (rightsideup) {
+    ibegin = 0;
+    iend = h;
+    iinc = 1;
+  }
+  else {
+    ibegin = h-1;
+    iend = -1;
+    iinc = -1;
+  }
+
+  for (i = ibegin; i != iend && (pp - pic8 <= l); i += iinc) {
     pp = pic8 + (i * w);
     if ((i&0x3f)==0) WaitCursor();
     for (j=bitnum=0; j<padw; j++,bitnum++) {
@@ -368,12 +408,14 @@ static int loadBMP1(fp, pic8, w, h)
 
 
 /*******************************************/
-static int loadBMP4(fp, pic8, w, h, comp)
+static int loadBMP4(fp, pic8, w, h, comp, rightsideup)
      FILE *fp;
      byte *pic8;
      u_int  w,h,comp;
+     int rightsideup;
 {
   int   i,j,c,c1,x,y,nybnum,padw,rv;
+  int   begin, end, inc;
   byte *pp = pic8 + ((h - 1) * w);
   size_t l = w*h;
 
@@ -381,9 +423,20 @@ static int loadBMP4(fp, pic8, w, h, comp
   c = c1 = 0;
 
   if (comp == BI_RGB) {   /* read uncompressed data */
+    if (rightsideup) {
+      begin = 0;
+      end = h;
+      inc = 1;
+    }
+    else {
+      begin = h-1;
+      end = -1;
+      inc = -1;
+    }
+
     padw = ((w + 7)/8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */
 
-    for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+    for (i = begin; i != end && (pp - pic8 <= l); i += inc) {
       pp = pic8 + (i * w);
       if ((i&0x3f)==0) WaitCursor();
 
@@ -454,24 +507,37 @@ static int loadBMP4(fp, pic8, w, h, comp
 
 
 /*******************************************/
-static int loadBMP8(fp, pic8, w, h, comp)
+static int loadBMP8(fp, pic8, w, h, comp, rightsideup)
      FILE *fp;
      byte *pic8;
      u_int  w,h,comp;
+     int rightsideup;
 {
   int   i,j,c,c1,padw,x,y,rv;
+  int   begin, end, inc;
   byte *pp = pic8 + ((h - 1) * w);
   size_t l = w*h;
   byte *pend;
 
   rv = 0;
 
-  pend = pic8 + w * h;
+  pend = pic8 + l;
 
   if (comp == BI_RGB) {   /* read uncompressed data */
+    if (rightsideup) {
+      begin = 0;
+      end = h;
+      inc = 1;
+    }
+    else {
+      begin = h-1;
+      end = -1;
+      inc = -1;
+    }
+
     padw = ((w + 3)/4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
 
-    for (i=h-1; i>=0 && (pp - pic8 <= l); i--) {
+    for (i = begin; i != end && (pp - pic8 <= l); i += inc) {
       pp = pic8 + (i * w);
       if ((i&0x3f)==0) WaitCursor();
 
@@ -534,12 +600,13 @@ static int loadBMP8(fp, pic8, w, h, comp
 
 
 /*******************************************/
-static int loadBMP16(fp, pic24, w, h, mask)
+static int loadBMP16(fp, pic24, w, h, mask, rightsideup)
      FILE  *fp;
      byte  *pic24;
      u_int w, h, *mask;
+     int rightsideup;
 {
-  int	 x, y;
+  int	 x, y, ybegin, yend, yinc;
   byte	*pp = pic24 + ((h - 1) * w * 3);
   size_t l = w*h*3;
   u_int	 buf, colormask[6];
@@ -611,7 +678,18 @@ static int loadBMP16(fp, pic24, w, h, ma
 	    colorbits[2], colormask[2], bitshift[2], bitshift2[2],
 	    colormask[5], bitshift[5], bitshift2[5]);
 
-  for (y = h-1; y >= 0 && (pp - pic24 <= l); y--) {
+  if (rightsideup) {
+    ybegin = 0;
+    yend = h;
+    yinc = 1;
+  }
+  else {
+    ybegin = h-1;
+    yend = -1;
+    yinc = -1;
+  }
+
+  for (y = ybegin; y != yend && (pp - pic24 <= l); y += yinc) {
     pp = pic24 + (3 * w * y);
     if ((y&0x3f)==0) WaitCursor();
 
@@ -638,12 +716,13 @@ static int loadBMP16(fp, pic24, w, h, ma
 
 
 /*******************************************/
-static int loadBMP24(fp, pic24, w, h, bits)   /* also handles 32-bit BI_RGB */
+static int loadBMP24(fp, pic24, w, h, bits, rightsideup)   /* also handles 32-bit BI_RGB */
      FILE *fp;
      byte *pic24;
      u_int  w,h, bits;
+     int rightsideup;
 {
-  int   i,j,padb,rv;
+  int   i,j,padb,rv,ibegin,iend,iinc;
   byte *pp = pic24 + ((h - 1) * w * 3);
   size_t l = w*h*3;
 
@@ -652,7 +731,18 @@ static int loadBMP24(fp, pic24, w, h, bi
   padb = (4 - ((w*3) % 4)) & 0x03;  /* # of pad bytes to read at EOscanline */
   if (bits==32) padb = 0;
 
-  for (i=h-1; i>=0; i--) {
+  if (rightsideup) {
+    ibegin = 0;
+    iend = h;
+    iinc = 1;
+  }
+  else {
+    ibegin = h-1;
+    iend = -1;
+    iinc = -1;
+  }
+
+  for (i=ibegin; i != iend; i+=iinc) {
     pp = pic24 + (i * w * 3);
     if ((i&0x3f)==0) WaitCursor();
 
@@ -676,12 +766,13 @@ static int loadBMP24(fp, pic24, w, h, bi
 
 
 /*******************************************/
-static int loadBMP32(fp, pic24, w, h, colormask) /* 32-bit BI_BITFIELDS only */
+static int loadBMP32(fp, pic24, w, h, colormask, rightsideup) /* 32-bit BI_BITFIELDS only */
      FILE  *fp;
      byte  *pic24;
      u_int w, h, *colormask;
+     int rightsideup;
 {
-  int	 x, y;
+  int	 x, y, ybegin, yend, yinc;
   byte	*pp;
   u_int	 buf;
   int	 i, bit, bitshift[3], colorbits[3], bitshift2[3];
@@ -722,7 +813,18 @@ static int loadBMP32(fp, pic24, w, h, co
 	    colorbits[1], colormask[1], bitshift[1], bitshift2[1],
 	    colorbits[2], colormask[2], bitshift[2], bitshift2[2]);
 
-  for (y = h-1; y >= 0; y--) {
+  if (rightsideup) {
+    ybegin = 0;
+    yend = h;
+    yinc = 1;
+  }
+  else {
+    ybegin = h-1;
+    yend = -1;
+    yinc = -1;
+  }
+
+  for (y = ybegin; y != yend; y += yinc) {
     pp = pic24 + (3 * w * y);
     if ((y&0x3f)==0) WaitCursor();
 
@@ -1078,6 +1180,3 @@ static int bmpError(fname, st)
   SetISTR(ISTR_WARNING,"%s:  %s", fname, st);
   return 0;
 }
-
-
-
openSUSE Build Service is sponsored by