- fprintf(stderr, "rfxswf: unknown bitmap type %d\n", bitmap_flags);
- return -1;
- }
-
- swf_SetU8(t,bitmap_flags);
- swf_SetU16(t,width);
- swf_SetU16(t,height);
-
- { 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;
-
- if (RFXSWF_deflate_wraper(t,&zs,TRUE)<0) res = -3;
- deflateEnd(&zs);
-
- } else res = -3; // zlib error
- }
- return res;
-}
-
-int swf_SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * palette,U16 ncolors)
-{ RGBA * pal = palette;
- int bps = BYTES_PER_SCANLINE(width);
- int res = 0;
-
- if (!pal) // create default palette for grayscale images
- { int i;
- pal = rfx_alloc(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)) {
- fprintf(stderr, "rfxswf: unsupported number of colors: %d\n", ncolors);
- return -1; // parameter error
- }
-
- swf_SetU8(t,BMF_8BIT);
- swf_SetU16(t,width);
- swf_SetU16(t,height);
- swf_SetU8(t,ncolors-1); // number of pal entries
-
- { 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 = rfx_alloc(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 (swf_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;
-
- if (RFXSWF_deflate_wraper(t,&zs,FALSE)<0) res = -3;
-
- // compress bitmap
- zs.next_in = bitmap;
- zs.avail_in = (bps*height*sizeof(U8));
-
- if (RFXSWF_deflate_wraper(t,&zs,TRUE)<0) res = -3;
-
- deflateEnd(&zs);
-
- rfx_free(zpal);
- } else res = -2; // memory error
- } else res = -3; // zlib error
- }
-
- if (!palette) rfx_free(pal);
-
- return res;
-}
-
-int swf_SetLosslessBitsGrayscale(TAG * t,U16 width,U16 height,U8 * bitmap)
-{ return swf_SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
-}
-
-RGBA* swf_DefineLosslessBitsTagToImage(TAG*tag, int*dwidth, int*dheight)
-{
- int id,format,height, width, pos;
- U32 datalen, datalen2;
+ fprintf(stderr, "rfxswf: unknown bitmap type %d\n", bitmap_flags);
+ return -1;
+ }
+
+ swf_SetU8(t, bitmap_flags);
+ swf_SetU16(t, width);
+ swf_SetU16(t, height);
+
+ {
+ 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 = (Bytef *)bitmap;
+
+ if (RFXSWF_deflate_wraper(t, &zs, TRUE) < 0)
+ res = -3;
+ deflateEnd(&zs);
+
+ } else
+ res = -3; // zlib error
+ }
+ return res;
+}
+
+int swf_SetLosslessBitsIndexed(TAG * t, U16 width, U16 height, U8 * bitmap, RGBA * palette, U16 ncolors)
+{
+ RGBA *pal = palette;
+ int bps = BYTES_PER_SCANLINE(width);
+ int res = 0;
+
+ if (!pal) // create default palette for grayscale images
+ {
+ int i;
+ pal = (RGBA*)rfx_alloc(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)) {
+ fprintf(stderr, "rfxswf: unsupported number of colors: %d\n",
+ ncolors);
+ return -1; // parameter error
+ }
+
+ swf_SetU8(t, BMF_8BIT);
+ swf_SetU16(t, width);
+ swf_SetU16(t, height);
+ swf_SetU8(t, ncolors - 1); // number of pal entries
+
+ {
+ 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 = (U8*)rfx_alloc(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 (swf_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;
+
+ if (RFXSWF_deflate_wraper(t, &zs, FALSE) < 0)
+ res = -3;
+
+ // compress bitmap
+ zs.next_in = bitmap;
+ zs.avail_in = (bps * height * sizeof(U8));
+
+ if (RFXSWF_deflate_wraper(t, &zs, TRUE) < 0)
+ res = -3;
+
+ deflateEnd(&zs);
+
+ rfx_free(zpal);
+ } else
+ res = -2; // memory error
+ } else
+ res = -3; // zlib error
+ }
+
+ if (!palette)
+ rfx_free(pal);
+
+ return res;
+}
+
+int swf_SetLosslessBitsGrayscale(TAG * t, U16 width, U16 height, U8 * bitmap)
+{
+ return swf_SetLosslessBitsIndexed(t, width, height, bitmap, NULL, 256);
+}
+
+void swf_PreMultiplyAlpha(RGBA*data, int width, int height)
+{
+ int num = width*height;
+ int t;
+ for(t=0;t<num;t++) {
+ data[t].r = ((int)data[t].r*data[t].a)/255;
+ data[t].g = ((int)data[t].g*data[t].a)/255;
+ data[t].b = ((int)data[t].b*data[t].a)/255;
+ }
+}
+
+/* expects mem to be non-premultiplied */
+void swf_SetLosslessImage(TAG*tag, RGBA*data, int width, int height)
+{
+ int hasalpha = swf_ImageHasAlpha(data, width, height);
+ int num;
+ if(!hasalpha) {
+ tag->id = ST_DEFINEBITSLOSSLESS;
+ } else {
+ tag->id = ST_DEFINEBITSLOSSLESS2;
+ /* FIXME: we're destroying the callers data here */
+ swf_PreMultiplyAlpha(data, width, height);
+ }
+ num = swf_ImageGetNumberOfPaletteEntries(data, width, height, 0);
+ if(num>1 && num<=256) {
+ RGBA*palette = (RGBA*)malloc(sizeof(RGBA)*num);
+ int width2 = BYTES_PER_SCANLINE(width);
+ U8*data2 = (U8*)malloc(width2*height);
+ int len = width*height;
+ int x,y;
+ int r;
+ swf_ImageGetNumberOfPaletteEntries(data, width, height, palette);
+ for(y=0;y<height;y++) {
+ RGBA*src = &data[width*y];
+ U8*dest = &data2[width2*y];
+ for(x=0;x<width;x++) {
+ RGBA col = src[x];
+ for(r=0;r<num;r++) {
+ if(*(U32*)&col == *(U32*)&palette[r]) {
+ dest[x] = r;
+ break;
+ }
+ }
+ if(r==num) {
+ fprintf(stderr, "Internal error: Couldn't find color %02x%02x%02x%02x in palette (%d entries)\n",
+ col.r, col.g, col.b, col.a, num);
+ dest[x] = 0;
+ }
+ }
+ }
+ swf_SetLosslessBitsIndexed(tag, width, height, data2, palette, num);
+ free(data2);
+ free(palette);
+ } else {
+ swf_SetLosslessBits(tag, width, height, data, BMF_32BIT);
+ }
+}
+
+RGBA *swf_DefineLosslessBitsTagToImage(TAG * tag, int *dwidth, int *dheight)
+{
+ int id, format, height, width, pos;
+ uLongf datalen, datalen2;