+int swf_SetJPEGBits(TAG * t, char *fname, int quality)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JPEGBITS *out;
+ FILE *f;
+ U8 *scanline;
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ if ((f = fopen(fname, "rb")) == NULL) {
+ fprintf(stderr, "rfxswf: file open error\n");
+ return -1;
+ }
+
+ jpeg_stdio_src(&cinfo, f);
+ jpeg_read_header(&cinfo, TRUE);
+ jpeg_start_decompress(&cinfo);
+
+ out =
+ swf_SetJPEGBitsStart(t, cinfo.output_width, cinfo.output_height,
+ quality);
+ scanline = (U8 *) rfx_alloc(4 * cinfo.output_width);
+
+ if (scanline) {
+ int y;
+ U8 *js = scanline;
+ if (cinfo.out_color_space == JCS_GRAYSCALE) {
+ for (y = 0; y < cinfo.output_height; y++) {
+ int x;
+ jpeg_read_scanlines(&cinfo, &js, 1);
+ for (x = cinfo.output_width - 1; x >= 0; x--) {
+ js[x * 3] = js[x * 3 + 1] = js[x * 3 + 2] = js[x];
+ }
+ swf_SetJPEGBitsLines(out, (U8 **) & js, 1);
+ }
+ } else if (cinfo.out_color_space == JCS_RGB) {
+ for (y = 0; y < cinfo.output_height; y++) {
+ jpeg_read_scanlines(&cinfo, &js, 1);
+ swf_SetJPEGBitsLines(out, (U8 **) & js, 1);
+ }
+ } else if (cinfo.out_color_space == JCS_YCCK) {
+ //FIXME
+ fprintf(stderr, "Error: Can't convert YCCK to RGB.\n");
+ return -1;
+ } else if (cinfo.out_color_space == JCS_YCbCr) {
+ for (y = 0; y < cinfo.output_height; y++) {
+ int x;
+ for (x = 0; x < cinfo.output_width; x++) {
+ int y = js[x * 3 + 0];
+ int u = js[x * 3 + 1];
+ int v = js[x * 3 + 1];
+ js[x * 3 + 0] = y + ((360 * (v - 128)) >> 8);
+ js[x * 3 + 1] =
+ y - ((88 * (u - 128) + 183 * (v - 128)) >> 8);
+ js[x * 3 + 2] = y + ((455 * (u - 128)) >> 8);
+ }
+ }
+ } else if (cinfo.out_color_space == JCS_CMYK) {
+ for (y = 0; y < cinfo.output_height; y++) {
+ int x;
+ jpeg_read_scanlines(&cinfo, &js, 1);
+ /* This routine seems to work for now-
+ It's a mixture of 3 different
+ CMYK->RGB conversion routines I found in the
+ web. (which all produced garbage)
+ I'm happily accepting suggestions. (mk) */
+ for (x = 0; x < cinfo.output_width; x++) {
+ int white = 255 - js[x * 4 + 3];
+ js[x * 3 + 0] = white - ((js[x * 4] * white) >> 8);
+ js[x * 3 + 1] = white - ((js[x * 4 + 1] * white) >> 8);
+ js[x * 3 + 2] = white - ((js[x * 4 + 2] * white) >> 8);
+ }
+ swf_SetJPEGBitsLines(out, (U8 **) & js, 1);
+ }
+ }
+ }
+
+ swf_SetJPEGBitsFinish(out);
+ jpeg_finish_decompress(&cinfo);
+ fclose(f);
+
+ return 0;
+}
+
+/* jpeg_source_mgr functions */
+static void tag_init_source(struct jpeg_decompress_struct *cinfo)
+{
+ TAG *tag = (TAG *) cinfo->client_data;
+ if (tag->id == ST_DEFINEBITSJPEG3) {
+ swf_SetTagPos(tag, 6);
+ } else {
+ swf_SetTagPos(tag, 2);
+ }
+ cinfo->src->bytes_in_buffer = 0;
+}
+static boolean tag_fill_input_buffer(struct jpeg_decompress_struct *cinfo)
+{
+ TAG *tag = (TAG *) cinfo->client_data;
+ if (tag->data[tag->pos + 0] == 0xff &&
+ tag->data[tag->pos + 1] == 0xd9 &&
+ tag->data[tag->pos + 2] == 0xff &&
+ tag->data[tag->pos + 3] == 0xd8) {
+ tag->pos += 4;
+ }
+ if (tag->pos >= tag->len) {
+ cinfo->src->next_input_byte = 0;
+ cinfo->src->bytes_in_buffer = 0;
+ return 0;
+ }
+ cinfo->src->next_input_byte = &tag->data[tag->pos];
+ cinfo->src->bytes_in_buffer = 1; //tag->len - tag->pos;
+ tag->pos += 1;
+ return 1;
+}
+static void tag_skip_input_data(struct jpeg_decompress_struct *cinfo, long count)
+{
+ TAG *tag = (TAG *) cinfo->client_data;
+ cinfo->src->next_input_byte = 0;
+ cinfo->src->bytes_in_buffer = 0;
+ tag->pos += count;
+}
+static boolean tag_resync_to_restart(struct jpeg_decompress_struct *cinfo, int desired)
+{
+ return jpeg_resync_to_restart(cinfo, desired);
+}
+static void tag_term_source(struct jpeg_decompress_struct *cinfo)
+{
+ TAG *tag = (TAG *) cinfo->client_data;
+}
+RGBA *swf_JPEG2TagToImage(TAG * tag, int *width, int *height)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ struct jpeg_source_mgr mgr;
+ RGBA *dest;
+ int y;
+ int offset = 0;
+ int oldtaglen = 0;
+ *width = 0;
+ *height = 0;
+
+ if (tag->id == ST_DEFINEBITSJPEG) {
+ fprintf(stderr, "rfxswf: extracting from definebitsjpeg not yet supported\n");
+ return 0;
+ }
+ if (tag->id == ST_DEFINEBITSJPEG3) {
+#ifdef HAVE_ZLIB
+ offset = swf_GetU32(tag);
+ oldtaglen = tag->len;
+ tag->len = offset+6;
+#else
+ fprintf(stderr, "rfxswf: extracting from definebitsjpeg3 not possible: no zlib\n");
+ return 0;
+#endif
+ }
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+ cinfo.client_data = (void *) tag;
+ cinfo.src = &mgr;
+ cinfo.src->init_source = tag_init_source;
+ cinfo.src->fill_input_buffer = tag_fill_input_buffer;
+ cinfo.src->skip_input_data = tag_skip_input_data;
+ cinfo.src->resync_to_restart = jpeg_resync_to_restart;
+ cinfo.src->term_source = tag_term_source;
+ cinfo.out_color_space = JCS_RGB;
+
+ jpeg_read_header(&cinfo, TRUE);
+ *width = cinfo.image_width;
+ *height = cinfo.image_height;
+ dest =
+ rfx_alloc(sizeof(RGBA) * cinfo.image_width * cinfo.image_height);
+
+ jpeg_start_decompress(&cinfo);
+ for (y = 0; y < cinfo.output_height; y++) {
+ RGBA *line = &dest[y * cinfo.image_width];
+ U8 *to = (U8 *) line;
+ int x;
+ jpeg_read_scanlines(&cinfo, &to, 1);
+ for (x = cinfo.output_width - 1; x >= 0; --x) {
+ int r = to[x * 3 + 0];
+ int g = to[x * 3 + 1];
+ int b = to[x * 3 + 2];
+ line[x].r = r;
+ line[x].g = g;
+ line[x].b = b;
+ line[x].a = 255;
+ }
+ }
+
+ jpeg_finish_decompress(&cinfo);
+
+ jpeg_destroy_decompress(&cinfo);
+
+#ifdef HAVE_ZLIB
+ if(offset) {
+ U32 datalen = cinfo.output_width*cinfo.output_height;
+ U8* alphadata = (U8*)rfx_alloc(datalen);
+ int error;
+ tag->len = oldtaglen;
+ swf_SetTagPos(tag, 6+offset);
+ error = uncompress(alphadata, &datalen, &tag->data[tag->pos], tag->len - tag->pos);
+ if (error != Z_OK) {
+ fprintf(stderr, "rfxswf: Zlib error %d while extracting definejpeg3\n", error);
+ return 0;
+ }
+ for(y=0;y<cinfo.output_height;y++) {
+ RGBA*line = &dest[y*cinfo.output_width];
+ U8*aline = &alphadata[y*cinfo.output_width];
+ int x;
+ for(x=0;x<cinfo.output_width;x++) {
+ line[x].a = aline[x];
+ }
+ }
+ free(alphadata);
+ }
+#endif
+ return dest;