3 Bitmap functions (needs libjpeg)
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
10 This file is distributed under the GPL, see file COPYING for details
14 #define OUTBUFFER_SIZE 0x8000
16 #ifdef _JPEGLIB_INCLUDED_
18 typedef struct _JPEGDESTMGR
19 { struct jpeg_destination_mgr mgr;
22 struct jpeg_compress_struct cinfo;
23 struct jpeg_error_mgr jerr;
24 } JPEGDESTMGR, * LPJPEGDESTMGR;
26 // Destination manager callbacks
28 void swf_init_destination(j_compress_ptr cinfo)
29 { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
30 dmgr->buffer = (JOCTET*)malloc(OUTBUFFER_SIZE);
31 dmgr->mgr.next_output_byte = dmgr->buffer;
32 dmgr->mgr.free_in_buffer = OUTBUFFER_SIZE;
35 boolean swf_empty_output_buffer(j_compress_ptr cinfo)
36 { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
37 SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE);
38 dmgr->mgr.next_output_byte = dmgr->buffer;
39 dmgr->mgr.free_in_buffer = OUTBUFFER_SIZE;
43 void swf_term_destination(j_compress_ptr cinfo)
44 { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
45 SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE-dmgr->mgr.free_in_buffer);
47 dmgr->mgr.free_in_buffer = 0;
50 JPEGBITS * SetJPEGBitsStart(TAG * t,int width,int height,int quality)
54 // redirect compression lib output to local SWF Tag structure
56 jpeg = (JPEGDESTMGR *)malloc(sizeof(JPEGDESTMGR));
57 if (!jpeg) return NULL;
59 memset(jpeg,0x00,sizeof(JPEGDESTMGR));
60 jpeg->cinfo.err = jpeg_std_error(&jpeg->jerr);
62 jpeg_create_compress(&jpeg->cinfo);
64 jpeg->mgr.init_destination = swf_init_destination;
65 jpeg->mgr.empty_output_buffer = swf_empty_output_buffer;
66 jpeg->mgr.term_destination = swf_term_destination;
70 jpeg->cinfo.dest = (struct jpeg_destination_mgr *)jpeg;
74 jpeg->cinfo.image_width = width;
75 jpeg->cinfo.image_height = height;
76 jpeg->cinfo.input_components = 3;
77 jpeg->cinfo.in_color_space = JCS_RGB;
79 jpeg_set_defaults(&jpeg->cinfo);
80 jpeg_set_quality(&jpeg->cinfo,quality,TRUE);
82 // write tables to SWF
84 jpeg_write_tables(&jpeg->cinfo);
86 // compess image to SWF
88 jpeg_suppress_tables(&jpeg->cinfo, TRUE);
89 jpeg_start_compress(&jpeg->cinfo, FALSE);
91 return (JPEGBITS *)jpeg;
94 int SetJPEGBitsLines(JPEGBITS * jpegbits,U8 ** data,int n)
95 { JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
97 jpeg_write_scanlines(&jpeg->cinfo,data,n);
101 int SetJPEGBitsLine(JPEGBITS * jpegbits,U8 * data)
102 { return SetJPEGBitsLines(jpegbits,&data,1);
105 int SetJPEGBitsFinish(JPEGBITS * jpegbits)
106 { JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
107 if (!jpeg) return -1;
108 jpeg_finish_compress(&jpeg->cinfo);
113 int SetJPEGBits(TAG * t,char * fname,int quality)
114 { struct jpeg_decompress_struct cinfo;
115 struct jpeg_error_mgr jerr;
120 cinfo.err = jpeg_std_error(&jerr);
121 jpeg_create_decompress(&cinfo);
123 if ((f=fopen(fname,"rb"))==NULL) return -1;
126 jpeg_stdio_src(&cinfo,f);
127 jpeg_read_header(&cinfo, TRUE);
128 jpeg_start_decompress(&cinfo);
130 out = SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
131 scanline = (U8*)malloc(4*cinfo.output_width);
136 for (y=0;y<cinfo.output_height;y++)
137 { jpeg_read_scanlines(&cinfo,&js,1);
138 SetJPEGBitsLines(out,(U8**)&js,1);
142 SetJPEGBitsFinish(out);
143 jpeg_finish_decompress(&cinfo);
149 #endif // _JPEGLIB_INCLUDED_
151 // Lossless compression texture based on zlib
153 #ifdef _ZLIB_INCLUDED_
155 int swf_deflate_wraper(TAG * t,z_stream * zs,U8 * data,boolean finish)
157 { int status = deflate(zs,Z_SYNC_FLUSH);
159 if (zs->avail_out == 0)
160 { SetBlock(t,data,zs->next_out-data);
162 zs->avail_out = OUTBUFFER_SIZE;
166 { if (finish) deflate(zs,Z_FINISH);
173 fprintf(stderr,"rfxswf: zlib compression error (%i)\n",status);
182 int SetLosslessBits(TAG * t,U16 width,U16 height,void * bitmap,U8 bitmap_flags)
187 switch (bitmap_flags)
189 return SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
191 bps = BYTES_PER_SCANLINE(sizeof(U16)*width);
200 SetU8(t,bitmap_flags);
204 if (data=malloc(OUTBUFFER_SIZE))
207 memset(&zs,0x00,sizeof(z_stream));
211 if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
212 { zs.avail_in = bps*height;
215 zs.avail_out = OUTBUFFER_SIZE;
217 if (swf_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
218 if (zs.next_out>data) SetBlock(t,data,zs.next_out-data);
223 } else res = -3; // zlib error
225 } else res = -2; // memory error
230 int SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * palette,U16 ncolors)
231 { RGBA * pal = palette;
232 int bps = BYTES_PER_SCANLINE(width);
236 if (!pal) // create default palette for grayscale images
238 pal = malloc(256*sizeof(RGBA));
239 for (i=0;i<256;i++) { pal[i].r = pal[i].g = pal[i].b = i; pal[i].a = 0xff;}
243 if ((ncolors<2)||(ncolors>256)||(!t)) return -1; // parameter error
248 SetU8(t,ncolors-1); // number of pal entries
250 if (data=malloc(OUTBUFFER_SIZE))
253 memset(&zs,0x00,sizeof(z_stream));
257 if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
258 { U8 * zpal; // compress palette
259 if (zpal = malloc(ncolors*4))
263 /* be careful with ST_DEFINEBITSLOSSLESS2, because
264 the Flash player produces great bugs if you use too many
265 alpha colors in your palette. The only sensible result that
266 can be archeived is setting one color to r=0,b=0,g=0,a=0 to
267 make transparent parts in sprites. That's the cause why alpha
268 handling is implemented in lossless routines of rfxswf.
270 Indeed: I haven't understood yet how flash player handles
271 alpha values different from 0 and 0xff in lossless bitmaps...
274 if (GetTagID(t)==ST_DEFINEBITSLOSSLESS2) // have alpha channel?
275 { for (i=0;i<ncolors;i++)
282 zs.avail_in = 4*ncolors;
285 { for (i=0;i<ncolors;i++) // pack RGBA structures to RGB
291 zs.avail_in = 3*ncolors;
296 zs.avail_out = OUTBUFFER_SIZE;
298 if (swf_deflate_wraper(t,&zs,data,FALSE)<0) res = -3;
302 zs.avail_in = (bps*height*sizeof(U8));
304 if (swf_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
308 if (zs.next_out>data) SetBlock(t,data,zs.next_out-data);
311 } else res = -2; // memory error
312 } else res = -3; // zlib error
316 if (!palette) free(pal);
321 int SetLosslessBitsGrayscale(TAG * t,U16 width,U16 height,U8 * bitmap)
322 { return SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
326 #endif // _ZLIB_INCLUDED_
328 #undef OUTBUFFER_SIZE