📄 swfdec_image.c
字号:
} SWFDEC_LOG ("format = %d", format); SWFDEC_LOG ("width = %d", image->width); SWFDEC_LOG ("height = %d", image->height); SWFDEC_LOG ("color_table_size = %d", color_table_size); if (image->width == 0 || image->height == 0) return; swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height); if (format == 3) { SwfdecBuffer *buffer; unsigned char *indexed_data; guint i; guint rowstride = (image->width + 3) & ~3; image->data = g_malloc (4 * image->width * image->height); image->rowstride = image->width * 4; if (have_alpha) { buffer = swfdec_bits_decompress (&bits, -1, color_table_size * 4 + rowstride * image->height); if (buffer == NULL) { SWFDEC_ERROR ("failed to decompress data"); memset (image->data, 0, 4 * image->width * image->height); return; } ptr = buffer->data; for (i = 0; i < color_table_size; i++) {#if G_BYTE_ORDER == G_LITTLE_ENDIAN guint8 tmp = ptr[i * 4 + 0]; ptr[i * 4 + 0] = ptr[i * 4 + 2]; ptr[i * 4 + 2] = tmp;#else guint8 tmp = ptr[i * 4 + 3]; ptr[i * 4 + 3] = ptr[i * 4 + 2]; ptr[i * 4 + 2] = ptr[i * 4 + 1]; ptr[i * 4 + 1] = ptr[i * 4 + 0]; ptr[i * 4 + 0] = tmp;#endif } indexed_data = ptr + color_table_size * 4; } else { buffer = swfdec_bits_decompress (&bits, -1, color_table_size * 3 + rowstride * image->height); if (buffer == NULL) { SWFDEC_ERROR ("failed to decompress data"); memset (image->data, 0, 4 * image->width * image->height); return; } ptr = buffer->data; for (i = color_table_size - 1; i < color_table_size; i--) { guint8 color[3]; color[0] = ptr[i * 3 + 0]; color[1] = ptr[i * 3 + 1]; color[2] = ptr[i * 3 + 2];#if G_BYTE_ORDER == G_LITTLE_ENDIAN ptr[i * 4 + 0] = color[2]; ptr[i * 4 + 1] = color[1]; ptr[i * 4 + 2] = color[0]; ptr[i * 4 + 3] = 255;#else ptr[i * 4 + 0] = 255; ptr[i * 4 + 1] = color[0]; ptr[i * 4 + 2] = color[1]; ptr[i * 4 + 3] = color[2];#endif } indexed_data = ptr + color_table_size * 3; } swfdec_image_colormap_decode (image, image->data, indexed_data, ptr, color_table_size); swfdec_buffer_unref (buffer); } else if (format == 4) { int i, j; guint c; unsigned char *idata; SwfdecBuffer *buffer; if (have_alpha) { SWFDEC_INFO("16bit images aren't allowed to have alpha, ignoring"); have_alpha = FALSE; } buffer = swfdec_bits_decompress (&bits, -1, 2 * ((image->width + 1) & ~1) * image->height); image->data = g_malloc (4 * image->width * image->height); idata = image->data; image->rowstride = image->width * 4; if (buffer == NULL) { SWFDEC_ERROR ("failed to decompress data"); memset (image->data, 0, 4 * image->width * image->height); return; } ptr = buffer->data; /* 15 bit packed */ for (j = 0; j < image->height; j++) { for (i = 0; i < image->width; i++) { c = ptr[1] | (ptr[0] << 8); idata[SWFDEC_COLOR_INDEX_BLUE] = (c << 3) | ((c >> 2) & 0x7); idata[SWFDEC_COLOR_INDEX_GREEN] = ((c >> 2) & 0xf8) | ((c >> 7) & 0x7); idata[SWFDEC_COLOR_INDEX_RED] = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7); idata[SWFDEC_COLOR_INDEX_ALPHA] = 0xff; ptr += 2; idata += 4; } if (image->width & 1) ptr += 2; } swfdec_buffer_unref (buffer); } if (format == 5) { SwfdecBuffer *buffer; int i, j; buffer = swfdec_bits_decompress (&bits, -1, 4 * image->width * image->height); image->rowstride = 4 * image->width; if (buffer == NULL) { SWFDEC_ERROR ("failed to decompress data"); image->data = g_malloc0 (4 * image->width * image->height); return; } ptr = image->data = buffer->data; /* image is stored in 0RGB format. We use ARGB/BGRA. */ for (j = 0; j < image->height; j++) { for (i = 0; i < image->width; i++) { *((guint32 *) ptr) = GUINT32_FROM_BE (*((guint32 *) ptr)); ptr += 4; } } /* FIXME: this can fail if the returned buffer does not contain malloc'd * data at some point in the future */ buffer->data = NULL; buffer->length = 0; swfdec_buffer_unref (buffer); }}inttag_func_define_bits_lossless (SwfdecSwfDecoder * s, guint tag){ SwfdecImage *image; int id; SwfdecBits *bits = &s->b; 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_LOSSLESS; image->raw_data = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}inttag_func_define_bits_lossless_2 (SwfdecSwfDecoder * s, guint tag){ SwfdecImage *image; int id; SwfdecBits *bits = &s->b; 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_LOSSLESS2; image->raw_data = swfdec_bits_get_buffer (bits, -1); return SWFDEC_STATUS_OK;}static voidswfdec_image_colormap_decode (SwfdecImage * image, unsigned char *dest, unsigned char *src, unsigned char *colormap, int colormap_len){ int c; int i; int j; int rowstride; rowstride = (image->width + 3) & ~0x3; SWFDEC_DEBUG ("rowstride %d", rowstride); for (j = 0; j < image->height; j++) { for (i = 0; i < image->width; i++) { c = src[i]; if (colormap_len < 256 && c == 255) { dest[0] = 0; dest[1] = 0; dest[2] = 0; dest[3] = 0; } else if (c >= colormap_len) { SWFDEC_ERROR ("colormap index out of range (%d>=%d) (%d,%d)", c, colormap_len, i, j); dest[0] = 0; dest[1] = 0; dest[2] = 0; dest[3] = 0; } else { memmove (dest, &colormap[c*4], 4); } dest += 4; } src += rowstride; }}static gbooleanswfdec_image_ensure_loaded (SwfdecImage *image){ if (image->raw_data == NULL) return FALSE; if (image->data == NULL) { switch (image->type) { case SWFDEC_IMAGE_TYPE_JPEG: swfdec_image_jpeg_load (image); break; case SWFDEC_IMAGE_TYPE_JPEG2: swfdec_image_jpeg2_load (image); break; case SWFDEC_IMAGE_TYPE_JPEG3: swfdec_image_jpeg3_load (image); break; case SWFDEC_IMAGE_TYPE_LOSSLESS: swfdec_image_lossless_load (image); break; case SWFDEC_IMAGE_TYPE_LOSSLESS2: swfdec_image_lossless_load (image); break; case SWFDEC_IMAGE_TYPE_UNKNOWN: default: g_assert_not_reached (); break; } if (image->data == NULL) { SWFDEC_WARNING ("failed to load image data"); return FALSE; } } else { swfdec_cached_use (SWFDEC_CACHED (image)); } return TRUE;}static gbooleanswfdec_image_has_alpha (SwfdecImage *image){ return image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2 || image->type == SWFDEC_IMAGE_TYPE_JPEG3;}cairo_surface_t *swfdec_image_create_surface (SwfdecImage *image){ static const cairo_user_data_key_t key; g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL); if (!swfdec_image_ensure_loaded (image)) return NULL; if (image->surface) { cairo_surface_reference (image->surface); return image->surface; } if (swfdec_image_has_alpha (image)) { cairo_surface_t *surface; guint8 *data; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, image->width, image->height); /* FIXME: only works if rowstride == image->width * 4 */ data = cairo_image_surface_get_data (surface); memcpy (data, image->data, image->width * image->height * 4); return surface; } else { image->surface = cairo_image_surface_create_for_data (image->data, CAIRO_FORMAT_RGB24, image->width, image->height, image->rowstride); cairo_surface_set_user_data (image->surface, &key, image->data, g_free); cairo_surface_reference (image->surface); return image->surface; }}cairo_surface_t *swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTransform *trans){ static const cairo_user_data_key_t key; cairo_surface_t *surface; guint8 *tdata; const guint8 *sdata; guint i, n; gboolean has_alpha = FALSE; g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL); g_return_val_if_fail (trans != NULL, NULL); /* obvious optimization */ if (swfdec_color_transform_is_identity (trans)) return swfdec_image_create_surface (image); if (!swfdec_image_ensure_loaded (image)) return NULL; tdata = g_try_malloc (image->width * image->height * 4); if (!tdata) { SWFDEC_ERROR ("failed to allocate memory for transformed image"); return NULL; } sdata = image->data; n = image->width * image->height; for (i = 0; i < n; i++) { ((guint32 *) tdata)[i] = swfdec_color_apply_transform_premultiplied (((guint32 *) sdata)[i], trans); /* optimization: check for alpha channel to speed up compositing */ has_alpha = tdata[4 * i + SWFDEC_COLOR_INDEX_ALPHA] != 0xFF; } surface = cairo_image_surface_create_for_data (tdata, has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, image->width, image->height, image->width * 4); cairo_surface_set_user_data (surface, &key, tdata, g_free); return surface;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -