📄 swfdec_image.c
字号:
/* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> * 2005-2006 Eric Anholt <eric@anholt.net> * 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <zlib.h>#include <string.h>#include "jpeg.h"#include "swfdec_image.h"#include "swfdec_cache.h"#include "swfdec_debug.h"#include "swfdec_swf_decoder.h"static void merge_alpha (SwfdecImage * image, unsigned char *image_data, unsigned char *alpha);static void swfdec_image_colormap_decode (SwfdecImage * image, unsigned char *dest, unsigned char *src, unsigned char *colormap, int colormap_len);G_DEFINE_TYPE (SwfdecImage, swfdec_image, SWFDEC_TYPE_CACHED)static voidswfdec_image_unload (SwfdecCached *cached){ SwfdecImage *image = SWFDEC_IMAGE (cached); if (image->surface) { cairo_surface_destroy (image->surface); image->surface = NULL; } else if (image->data) { g_free (image->data); } image->data = NULL;}static voidswfdec_image_dispose (GObject *object){ SwfdecImage * image = SWFDEC_IMAGE (object); if (image->jpegtables) { swfdec_buffer_unref (image->jpegtables); image->jpegtables = NULL; } if (image->raw_data) { swfdec_buffer_unref (image->raw_data); image->raw_data = NULL; } G_OBJECT_CLASS (swfdec_image_parent_class)->dispose (object);}static voidswfdec_image_class_init (SwfdecImageClass * g_class){ GObjectClass *object_class = G_OBJECT_CLASS (g_class); SwfdecCachedClass *cached_class = SWFDEC_CACHED_CLASS (g_class); object_class->dispose = swfdec_image_dispose; cached_class->unload = swfdec_image_unload;}static voidswfdec_image_init (SwfdecImage * image){}intswfdec_image_jpegtables (SwfdecSwfDecoder * s, guint tag){ SwfdecBits *bits = &s->b; SWFDEC_DEBUG ("swfdec_image_jpegtables"); if (s->jpegtables) { SWFDEC_FIXME ("duplicate DefineJPEGTables tag. Deleting first one"); swfdec_buffer_unref (s->jpegtables); } s->jpegtables = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}inttag_func_define_bits_jpeg (SwfdecSwfDecoder * s, guint tag){ SwfdecBits *bits = &s->b; int id; SwfdecImage *image; SWFDEC_LOG ("tag_func_define_bits_jpeg"); id = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" id = %d", id); image = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_IMAGE); if (!image) return SWFDEC_STATUS_OK; image->type = SWFDEC_IMAGE_TYPE_JPEG; if (!s->jpegtables) { SWFDEC_ERROR("No global JPEG tables available"); } else { image->jpegtables = swfdec_buffer_ref (s->jpegtables); } image->raw_data = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}/** * swfdec_jpeg_decode_argb: * * This is a wrapper around jpeg_decode_argb() that takes two segments, * strips off (sometimes bogus) start-of-image and end-of-image codes, * concatenates them, and puts new SOI and EOI codes on the resulting * buffer. This makes a real JPEG image out of the crap in SWF files. */static gbooleanswfdec_jpeg_decode_argb (unsigned char *data1, int length1, unsigned char *data2, int length2, void *outdata, int *width, int *height){ gboolean ret; if (data2) { unsigned char *tmpdata; int tmplength; tmplength = length1 + length2; tmpdata = g_malloc (tmplength); memcpy (tmpdata, data1, length1); memcpy (tmpdata + length1, data2, length2); ret = jpeg_decode_argb (tmpdata, tmplength, outdata, width, height); g_free (tmpdata); } else { ret = jpeg_decode_argb (data1, length1, outdata, width, height); } return ret;}static voidswfdec_image_jpeg_load (SwfdecImage *image){ gboolean ret; if (image->jpegtables) { ret = swfdec_jpeg_decode_argb ( image->jpegtables->data, image->jpegtables->length, image->raw_data->data, image->raw_data->length, (void *)&image->data, &image->width, &image->height); } else { ret = swfdec_jpeg_decode_argb ( image->raw_data->data, image->raw_data->length, NULL, 0, (void *)&image->data, &image->width, &image->height); } if (!ret) { return; } swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); image->rowstride = image->width * 4; SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height);}inttag_func_define_bits_jpeg_2 (SwfdecSwfDecoder * s, guint tag){ SwfdecBits *bits = &s->b; int id; SwfdecImage *image; id = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" id = %d", id); image = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_IMAGE); if (!image) return SWFDEC_STATUS_OK; image->type = SWFDEC_IMAGE_TYPE_JPEG2; image->raw_data = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}static voidswfdec_image_jpeg2_load (SwfdecImage *image){ gboolean ret; ret = swfdec_jpeg_decode_argb (image->raw_data->data, image->raw_data->length, NULL, 0, (void *)&image->data, &image->width, &image->height); if (!ret) { return; } swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); image->rowstride = image->width * 4; SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height);}inttag_func_define_bits_jpeg_3 (SwfdecSwfDecoder * s, guint tag){ SwfdecBits *bits = &s->b; guint id; SwfdecImage *image; id = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" id = %d", id); image = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_IMAGE); if (!image) return SWFDEC_STATUS_OK; image->type = SWFDEC_IMAGE_TYPE_JPEG3; image->raw_data = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}static voidswfdec_image_jpeg3_load (SwfdecImage *image){ SwfdecBits bits; SwfdecBuffer *buffer; int jpeg_length; gboolean ret; swfdec_bits_init (&bits, image->raw_data); jpeg_length = swfdec_bits_get_u32 (&bits); buffer = swfdec_bits_get_buffer (&bits, jpeg_length); if (buffer == NULL) return; ret = swfdec_jpeg_decode_argb (buffer->data, buffer->length, NULL, 0, (void *)&image->data, &image->width, &image->height); swfdec_buffer_unref (buffer); if (!ret) { return; } swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); image->rowstride = image->width * 4; buffer = swfdec_bits_decompress (&bits, -1, image->width * image->height); if (buffer) { merge_alpha (image, image->data, buffer->data); swfdec_buffer_unref (buffer); } else { SWFDEC_WARNING ("cannot set alpha channel information, decompression failed"); } SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height);}static voidmerge_alpha (SwfdecImage * image, unsigned char *image_data, unsigned char *alpha){ int x, y; unsigned char *p; for (y = 0; y < image->height; y++) { p = image_data + y * image->rowstride; for (x = 0; x < image->width; x++) { p[SWFDEC_COLOR_INDEX_ALPHA] = *alpha; p += 4; alpha++; } }}static voidswfdec_image_lossless_load (SwfdecImage *image){ int format; guint color_table_size; unsigned char *ptr; SwfdecBits bits; int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2); swfdec_bits_init (&bits, image->raw_data); format = swfdec_bits_get_u8 (&bits); SWFDEC_LOG (" format = %d", format); image->width = swfdec_bits_get_u16 (&bits); SWFDEC_LOG (" width = %d", image->width); image->height = swfdec_bits_get_u16 (&bits); SWFDEC_LOG (" height = %d", image->height); if (format == 3) { color_table_size = swfdec_bits_get_u8 (&bits) + 1; } else { color_table_size = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -