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 RFXSWF_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 RFXSWF_empty_output_buffer(j_compress_ptr cinfo)
36 { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
37 swf_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 RFXSWF_term_destination(j_compress_ptr cinfo)
44 { JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
45 swf_SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE-dmgr->mgr.free_in_buffer);
47 dmgr->mgr.free_in_buffer = 0;
50 JPEGBITS * swf_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 = RFXSWF_init_destination;
65 jpeg->mgr.empty_output_buffer = RFXSWF_empty_output_buffer;
66 jpeg->mgr.term_destination = RFXSWF_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 swf_SetJPEGBitsLines(JPEGBITS * jpegbits,U8 ** data,int n)
95 { JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
97 jpeg_write_scanlines(&jpeg->cinfo,data,n);
101 int swf_SetJPEGBitsLine(JPEGBITS * jpegbits,U8 * data)
102 { return swf_SetJPEGBitsLines(jpegbits,&data,1);
105 int swf_SetJPEGBitsFinish(JPEGBITS * jpegbits)
106 { JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
107 if (!jpeg) return -1;
108 jpeg_finish_compress(&jpeg->cinfo);
113 void swf_SetJPEGBits2(TAG * tag,U16 width,U16 height,RGBA* bitmap, int quality)
117 jpeg = swf_SetJPEGBitsStart(tag,width,height,quality);
118 for (y=0;y<height;y++)
119 { U8 scanline[3*width];
121 for (x=0;x<width;x++)
122 { scanline[p++] = bitmap[width*y+x].r;
123 scanline[p++] = bitmap[width*y+x].g;
124 scanline[p++] = bitmap[width*y+x].b;
126 swf_SetJPEGBitsLine(jpeg,scanline);
128 swf_SetJPEGBitsFinish(jpeg);
131 int swf_SetJPEGBits(TAG * t,char * fname,int quality)
132 { struct jpeg_decompress_struct cinfo;
133 struct jpeg_error_mgr jerr;
138 cinfo.err = jpeg_std_error(&jerr);
139 jpeg_create_decompress(&cinfo);
141 if ((f=fopen(fname,"rb"))==NULL) return -1;
143 jpeg_stdio_src(&cinfo,f);
144 jpeg_read_header(&cinfo, TRUE);
145 jpeg_start_decompress(&cinfo);
147 out = swf_SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
148 scanline = (U8*)malloc(4*cinfo.output_width);
153 if(cinfo.out_color_space == JCS_GRAYSCALE) {
154 for (y=0;y<cinfo.output_height;y++)
156 jpeg_read_scanlines(&cinfo,&js,1);
157 for(x=cinfo.output_width-1;x>=0;x--) {
158 js[x*3] = js[x*3+1] = js[x*3+2] = js[x];
160 swf_SetJPEGBitsLines(out,(U8**)&js,1);
163 else if(cinfo.out_color_space == JCS_RGB)
165 for (y=0;y<cinfo.output_height;y++)
166 { jpeg_read_scanlines(&cinfo,&js,1);
167 swf_SetJPEGBitsLines(out,(U8**)&js,1);
170 else if(cinfo.out_color_space == JCS_YCCK)
173 fprintf(stderr, "Error: Can't convert YCCK to RGB.\n");
176 else if(cinfo.out_color_space == JCS_YCbCr)
178 for (y=0;y<cinfo.output_height;y++) {
180 for(x=0;x<cinfo.output_width;x++) {
185 js[x*3+0] = y + ((360*(v-128))>>8);
186 js[x*3+1] = y - ((88*(u-128)-183*(v-128))>>8);
187 js[x*3+2] = y + ((455 * (u-128))>>8);
191 else if(cinfo.out_color_space == JCS_CMYK)
193 for (y=0;y<cinfo.output_height;y++)
195 jpeg_read_scanlines(&cinfo,&js,1);
196 /* This routine seems to work for now-
197 It's a mixture of 3 different
198 CMYK->RGB conversion routines I found in the
199 web. (which all produced garbage)
200 I'm happily accepting suggestions. (mk)*/
201 for(x=0;x<cinfo.output_width;x++) {
202 int white = 255 - js[x*4+3];
203 js[x*3+0] = white - ((js[x*4]*white)>>8);
204 js[x*3+1] = white - ((js[x*4+1]*white)>>8);
205 js[x*3+2] = white - ((js[x*4+2]*white)>>8);
207 swf_SetJPEGBitsLines(out,(U8**)&js,1);
212 swf_SetJPEGBitsFinish(out);
213 jpeg_finish_decompress(&cinfo);
219 #endif // _JPEGLIB_INCLUDED_
221 // Lossless compression texture based on zlib
223 #ifdef _ZLIB_INCLUDED_
225 int RFXSWF_deflate_wraper(TAG * t,z_stream * zs,U8 * data,boolean finish)
227 { int status = deflate(zs,Z_SYNC_FLUSH);
229 if (zs->avail_out == 0)
230 { swf_SetBlock(t,data,zs->next_out-data);
232 zs->avail_out = OUTBUFFER_SIZE;
236 { if (finish) deflate(zs,Z_FINISH);
243 fprintf(stderr,"rfxswf: zlib compression error (%i)\n",status);
251 int swf_SetLosslessBits(TAG * t,U16 width,U16 height,void * bitmap,U8 bitmap_flags)
256 switch (bitmap_flags)
258 return swf_SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
260 bps = BYTES_PER_SCANLINE(sizeof(U16)*width);
269 swf_SetU8(t,bitmap_flags);
271 swf_SetU16(t,height);
273 if ((data=malloc(OUTBUFFER_SIZE)))
276 memset(&zs,0x00,sizeof(z_stream));
280 if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
281 { zs.avail_in = bps*height;
284 zs.avail_out = OUTBUFFER_SIZE;
286 if (RFXSWF_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
287 if (zs.next_out>data) swf_SetBlock(t,data,zs.next_out-data);
292 } else res = -3; // zlib error
294 } else res = -2; // memory error
299 int swf_SetLosslessBitsIndexed(TAG * t,U16 width,U16 height,U8 * bitmap,RGBA * palette,U16 ncolors)
300 { RGBA * pal = palette;
301 int bps = BYTES_PER_SCANLINE(width);
305 if (!pal) // create default palette for grayscale images
307 pal = malloc(256*sizeof(RGBA));
308 for (i=0;i<256;i++) { pal[i].r = pal[i].g = pal[i].b = i; pal[i].a = 0xff;}
312 if ((ncolors<2)||(ncolors>256)||(!t)) return -1; // parameter error
314 swf_SetU8(t,BMF_8BIT);
316 swf_SetU16(t,height);
317 swf_SetU8(t,ncolors-1); // number of pal entries
319 if ((data=malloc(OUTBUFFER_SIZE)))
322 memset(&zs,0x00,sizeof(z_stream));
326 if (deflateInit(&zs,Z_DEFAULT_COMPRESSION)==Z_OK)
327 { U8 * zpal; // compress palette
328 if ((zpal = malloc(ncolors*4)))
332 /* be careful with ST_DEFINEBITSLOSSLESS2, because
333 the Flash player produces great bugs if you use too many
334 alpha colors in your palette. The only sensible result that
335 can be archeived is setting one color to r=0,b=0,g=0,a=0 to
336 make transparent parts in sprites. That's the cause why alpha
337 handling is implemented in lossless routines of rfxswf.
339 Indeed: I haven't understood yet how flash player handles
340 alpha values different from 0 and 0xff in lossless bitmaps...
343 if (swf_GetTagID(t)==ST_DEFINEBITSLOSSLESS2) // have alpha channel?
344 { for (i=0;i<ncolors;i++)
351 zs.avail_in = 4*ncolors;
354 { for (i=0;i<ncolors;i++) // pack RGBA structures to RGB
360 zs.avail_in = 3*ncolors;
365 zs.avail_out = OUTBUFFER_SIZE;
367 if (RFXSWF_deflate_wraper(t,&zs,data,FALSE)<0) res = -3;
371 zs.avail_in = (bps*height*sizeof(U8));
373 if (RFXSWF_deflate_wraper(t,&zs,data,TRUE)<0) res = -3;
377 if (zs.next_out>data) swf_SetBlock(t,data,zs.next_out-data);
380 } else res = -2; // memory error
381 } else res = -3; // zlib error
385 if (!palette) free(pal);
390 int swf_SetLosslessBitsGrayscale(TAG * t,U16 width,U16 height,U8 * bitmap)
391 { return swf_SetLosslessBitsIndexed(t,width,height,bitmap,NULL,256);
395 #endif // _ZLIB_INCLUDED_
397 #undef OUTBUFFER_SIZE