new lossless image functions (alpha channel still buggy, but I suspect the flash...
authorboehme <boehme>
Sun, 28 Oct 2001 18:57:31 +0000 (18:57 +0000)
committerboehme <boehme>
Sun, 28 Oct 2001 18:57:31 +0000 (18:57 +0000)
lib/modules/swfbits.c

index 2ecc39d..da8be39 100644 (file)
 
 */
 
-#ifdef _JPEGLIB_INCLUDED_
 #define OUTBUFFER_SIZE 0x8000
 
+#ifdef _JPEGLIB_INCLUDED_
+
 typedef struct _JPEGDESTMGR
 { struct jpeg_destination_mgr mgr;
   TAG *  t;
@@ -145,7 +146,185 @@ int SetJPEGBits(TAG * t,char * fname,int quality)
   return 0;
 }
 
-#undef OUTBUFFER_SIZE
+#endif // _JPEGLIB_INCLUDED_
+
+// Lossless compression texture based on zlib
+
+#ifdef _ZLIB_INCLUDED_
+
+int swf_deflate_wraper(TAG * t,z_stream * zs,U8 * data,boolean finish)
+{ while (1)
+  { int status = deflate(zs,Z_SYNC_FLUSH);
+
+    if (zs->avail_out == 0)
+    { SetBlock(t,data,zs->next_out-data);
+      zs->next_out = data;
+      zs->avail_out = OUTBUFFER_SIZE;
+    }
+    
+    if (zs->avail_in==0)
+    { if (finish) deflate(zs,Z_FINISH);
+      break;
+    }
+
+    if (status!=Z_OK)
+    {
+#ifdef DEBUG_RFXSWF
+      fprintf(stderr,"rfxswf: zlib compression error (%i)\n",status);
 #endif
+      return status;
+    }
+
+  }
+  return 0;
+}
+
+int SetLosslessBits(TAG * t,U16 width,U16 height,void * bitmap,U8 bitmap_flags)
+{ int res = 0;
+  int bps;
+  U8 * data;
+  
+  switch (bitmap_flags)
+  { case BMF_8BIT:
+      return SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
+    case BMF_16BIT:
+      bps = BYTES_PER_SCANLINE(sizeof(U16)*width);
+      break;
+    case BMF_32BIT:
+      bps = width*4;
+      break;
+    default:
+      return -1;
+  }
+  
+  SetU8(t,bitmap_flags);
+  SetU16(t,width);
+  SetU16(t,height);
+
+  if (data=malloc(OUTBUFFER_SIZE))
+  { z_stream zs;
+      
+    memset(&zs,0x00,sizeof(z_stream));
+    zs.zalloc = Z_NULL;
+    zs.zfree  = Z_NULL;
+
+    if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
+    { zs.avail_in         = bps*height;
+      zs.next_in          = bitmap;
+      zs.next_out         = data;
+      zs.avail_out        = OUTBUFFER_SIZE;
+
+      if (swf_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
+      if (zs.next_out>data) SetBlock(t,data,zs.next_out-data);
+
+      deflateEnd(&zs);
+      
+      
+    } else res = -3; // zlib error
+    free(data);
+  } else res = -2; // memory error
+  
+  return res;
+}
+
+int SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * palette,U16 ncolors)
+{ RGBA * pal = palette;
+  int bps = BYTES_PER_SCANLINE(width);
+  U8 * data;
+  int res = 0;
+    
+  if (!pal)     // create default palette for grayscale images
+  { int i;
+    pal = malloc(256*sizeof(RGBA));
+    for (i=0;i<256;i++) { pal[i].r = pal[i].g = pal[i].b = i; pal[i].a = 0xff;}
+    ncolors = 256;
+  }
+  
+  if ((ncolors<2)||(ncolors>256)||(!t)) return -1; // parameter error
+
+  SetU8(t,BMF_8BIT);
+  SetU16(t,width);
+  SetU16(t,height);
+  SetU8(t,ncolors-1); // number of pal entries
+
+  if (data=malloc(OUTBUFFER_SIZE))
+  { z_stream zs;
+
+    memset(&zs,0x00,sizeof(z_stream));
+    zs.zalloc = Z_NULL;
+    zs.zfree  = Z_NULL;
+
+    if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
+    { U8 * zpal;                    // compress palette
+      if (zpal = malloc(ncolors*4))
+      { U8 * pp = zpal;
+        int i;
+
+    /* be careful with ST_DEFINEBITSLOSSLESS2, because
+       the Flash player produces great bugs if you use too many
+       alpha colors in your palette. The only sensible result that
+       can be archeived is setting one color to r=0,b=0,g=0,a=0 to
+       make transparent parts in sprites. That's the cause why alpha
+       handling is implemented in lossless routines of rfxswf.
+
+       Indeed: I haven't understood yet how flash player handles
+       alpha values different from 0 and 0xff in lossless bitmaps...
+    */
+
+        if (GetTagID(t)==ST_DEFINEBITSLOSSLESS2)  // have alpha channel?
+        { for (i=0;i<ncolors;i++)         
+          { pp[0] = pal[i].r;
+            pp[1] = pal[i].g;
+            pp[2] = pal[i].b;
+            pp[3] = pal[i].a;
+            pp+=4; 
+          }
+          zs.avail_in = 4*ncolors;
+        }
+        else
+        { for (i=0;i<ncolors;i++)         // pack RGBA structures to RGB 
+          { pp[0] = pal[i].r;
+            pp[1] = pal[i].g;
+            pp[2] = pal[i].b;
+            pp+=3;
+          }
+          zs.avail_in         = 3*ncolors;
+        }
+
+        zs.next_in          = zpal;
+        zs.next_out         = data;
+        zs.avail_out        = OUTBUFFER_SIZE;
+
+        if (swf_deflate_wraper(t,&zs,data,FALSE)<0) res = -3;
+
+                                    // compress bitmap
+        zs.next_in = bitmap;
+        zs.avail_in = (bps*height*sizeof(U8));
+
+        if (swf_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
+
+        deflateEnd(&zs);
+
+        if (zs.next_out>data) SetBlock(t,data,zs.next_out-data);
+
+        free(zpal);
+      } else res = -2; // memory error
+    } else res = -3; // zlib error
+    free(data);
+  } else res = -2;
+  
+  if (!palette) free(pal);
+
+  return res;
+}
+
+int SetLosslessBitsGrayscale(TAG * t,U16 width,U16 height,U8 * bitmap)
+{ return SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
+}
+
+
+#endif // _ZLIB_INCLUDED_
+
+#undef OUTBUFFER_SIZE
+
 
-// insert zlib/PNG functions here