OSDN Git Service

lossless tag と gif の相互変換ルーチンを実装 (まだ作りかけ)
authoryoya <yoya@7c90b180-03d5-4157-b861-58a559ae9d1e>
Sun, 1 Feb 2009 14:43:57 +0000 (14:43 +0000)
committeryoya <yoya@7c90b180-03d5-4157-b861-58a559ae9d1e>
Sun, 1 Feb 2009 14:43:57 +0000 (14:43 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/swfed/trunk@103 7c90b180-03d5-4157-b861-58a559ae9d1e

src/config.m4
src/swf_gif.c [new file with mode: 0644]
src/swf_gif.h [new file with mode: 0644]

index 69d20f6..fcf525e 100644 (file)
@@ -59,5 +59,5 @@ if test "$PHP_SWFED" != "no"; then
   dnl
   dnl PHP_SUBST(SWFED_SHARED_LIBADD)
 
-  PHP_NEW_EXTENSION(swfed, swfed.c swf_object.c swf_header.c swf_rect.c swf_tag.c swf_tag_jpeg.c swf_tag_edit.c swf_tag_action.c swf_tag_lossless.c swf_tag_sound.c swf_rgb.c swf_rgba.c swf_argb.c swf_xrgb.c swf_action.c swf_jpeg.c bitstream.c jpeg_segment.c swf_png.c swf_debug.c, $ext_shared)
+  PHP_NEW_EXTENSION(swfed, swfed.c swf_object.c swf_header.c swf_rect.c swf_tag.c swf_tag_jpeg.c swf_tag_edit.c swf_tag_action.c swf_tag_lossless.c swf_tag_sound.c swf_rgb.c swf_rgba.c swf_argb.c swf_xrgb.c swf_action.c swf_jpeg.c bitstream.c jpeg_segment.c swf_png.c swf_gif.c swf_debug.c, $ext_shared)
 fi
diff --git a/src/swf_gif.c b/src/swf_gif.c
new file mode 100644 (file)
index 0000000..8844e6c
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gif_lib.h>
+#include <string.h>
+#include "bitstream.h"
+#include "swf_rgb.h"  // Lossless  format=3
+#include "swf_rgba.h" // Lossless2 format=3
+#include "swf_xrgb.h" // Lossless  format=5
+#include "swf_argb.h" // Lossless2 format=5
+#include "swf_gif.h"
+
+typedef struct my_gif_buffer_ {
+    unsigned char *data;
+    unsigned long data_len;
+    unsigned long data_offset;
+} my_gif_buffer;
+
+typedef unsigned char gif_byte;
+typedef gif_byte *    gif_bytep;
+typedef gif_bytep *   gif_bytepp;
+typedef unsigned long gif_uint_32;
+typedef struct {
+    unsigned char red, green, blue;
+    unsigned char alpha;
+} gif_color;
+typedef gif_color *   gif_colorp;
+
+
+/*
+ * gif read
+ */
+
+int gif_data_read_func(GifFileType* GifFile, GifByteType* buf, int count) {
+    my_gif_buffer *gif_buff = (my_gif_buffer *) GifFile->UserData;
+    if (gif_buff->data_offset + count <= gif_buff->data_len) {
+        memcpy(buf, gif_buff->data + gif_buff->data_offset, count);
+        gif_buff->data_offset += count;
+    } else {
+        fprintf(stderr, "! gif_buff->data_offset(%lu) + count(%d) <= gif_buff->data_len(%lu)\n",
+                gif_buff->data_offset, count, gif_buff->data_len);
+        return 0;
+    }
+    return count;
+}
+
+/*
+ * gif write
+ */
+
+int gif_data_write_func(GifFileType* GifFile, const GifByteType* buf, int count)
+{
+    my_gif_buffer *gif_buff = (my_gif_buffer *) GifFile->UserData;
+    unsigned long new_data_len;
+    if (gif_buff->data_offset + count > gif_buff->data_len) {
+        new_data_len = 2 * gif_buff->data_len;
+        if (gif_buff->data_offset + count > new_data_len) {
+            new_data_len = gif_buff->data_offset + count;
+        }
+        gif_buff->data = realloc(gif_buff->data, new_data_len);
+        if (gif_buff->data == NULL) {
+            fprintf(stderr, "gif_data_write_func: can't realloc: new_data_len(%lu), data_len(%lu)\n",
+                    new_data_len, gif_buff->data_len);
+            return 0;
+        }
+        gif_buff->data_len = new_data_len;
+    }
+    memcpy(gif_buff->data + gif_buff->data_offset, buf, count);
+    gif_buff->data_offset += count;
+    return count;
+}
+
+/*
+ * getTransparentIndex
+ */
+int getTransparentIndex(SavedImage Image) {
+    int i;
+    unsigned char transparent_index = -1;
+    if ((Image.ExtensionBlockCount == 0) || (Image.ExtensionBlocks == NULL)) {
+        return -1;
+    }
+    for (i = 0 ; i < Image.ExtensionBlockCount ; i++ ) {
+        ExtensionBlock Block = Image.ExtensionBlocks[i];
+        if (Block.Function == GRAPHICS_EXT_FUNC_CODE){
+            int gcntl_flag = Block.Bytes[0];
+            if (gcntl_flag & 0x01) {
+                transparent_index = Block.Bytes[3];
+                return transparent_index;
+            }
+        }
+    }
+    return transparent_index;
+}
+
+/*
+ *
+ */
+
+void *
+gifconv_gif2lossless(unsigned char *gif_data, unsigned long gif_data_len,
+                     int *tag_no, int *format,
+                     unsigned short *width, unsigned short *height,
+                     void **colormap, int *colormap_count) {
+    GifFileType *GifFile = NULL;
+    ColorMapObject *ColorMap = NULL;
+    my_gif_buffer gif_buff;
+    int bpp; // , color_type;
+    gif_uint_32 gif_width = 0, gif_height = 0;
+    gif_bytep gif_image_data_ref = NULL;
+    gif_uint_32 x, y;
+    
+    void *image_data = NULL;
+    gif_colorp palette = NULL;
+    int palette_num = 0;
+//    gif_bytep trans = NULL;
+//    int num_trans = 0;
+    int trans_index = -1;
+
+    SavedImage Image;
+
+    gif_buff.data = gif_data;
+    gif_buff.data_len = gif_data_len;
+    gif_buff.data_offset = 0;
+    GifFile = DGifOpen(& gif_buff, gif_data_read_func);
+    if (GifFile == NULL) {
+        fprintf(stderr, "gifconv_gif2lossless: can't open GIFFile\n");
+        return NULL;
+    }
+    if (DGifSlurp(GifFile) == GIF_ERROR) {
+        fprintf(stderr, "gifconv_gif2lossless: DGifSlurp failed\n");
+        return NULL;
+    }
+    Image = GifFile->SavedImages[0];
+    ColorMap = GifFile->SColorMap;
+    if (ColorMap == NULL) {
+        ColorMap = Image.ImageDesc.ColorMap;
+    }
+    gif_width  = GifFile->SWidth;
+    gif_height = GifFile->SHeight;
+    bpp = ColorMap->BitsPerPixel;
+    trans_index = getTransparentIndex(Image);
+
+    *width  = (unsigned short) gif_width;
+    *height = (unsigned short) gif_height;
+    *format = 3;
+
+    if (trans_index != -1) {
+        *tag_no = 36; // DefineBitsLossless2
+    } else {
+        *tag_no = 20; // DefineBitsLossless
+    }
+
+    if (bpp != 8) {
+        fprintf(stderr, "gifconv_gif2lossless: bpp=%d not implemented yet. accept only bpp=8\n", bpp);
+        if (GifFile) {
+            DGifCloseFile(GifFile);
+        }
+        return NULL;
+    }
+    
+    /*
+     * image copy
+     */
+    int i;
+//    *colormap_count = palette_num;
+    *colormap_count = 256; // XXX
+    if (trans_index == 0) {
+        swf_rgb_t *result_colormap = malloc(sizeof(swf_rgb_t) * palette_num);   // Lossless
+        for (i=0 ; i < palette_num ; i++) {
+            result_colormap[i].red   = palette[i].red;
+            result_colormap[i].green = palette[i].green;
+            result_colormap[i].blue  = palette[i].blue;
+        }
+        *colormap = result_colormap;
+    } else {
+        swf_rgba_t *result_colormap = malloc(sizeof(swf_rgba_t) * palette_num);   // Lossless2
+        for (i=0 ; i < palette_num ; i++) {
+            result_colormap[i].red   = palette[i].red;
+            result_colormap[i].green = palette[i].green;
+            result_colormap[i].blue  = palette[i].blue;
+            if (i == trans_index) {
+                result_colormap[i].alpha  = 0x0;
+            } else {
+                result_colormap[i].alpha  = 0xff;
+            }
+        }
+        *colormap = result_colormap;
+    }
+    unsigned char *indices_data = malloc(((gif_width+ 3) & -4) * gif_height);
+    gif_image_data_ref = Image.RasterBits;
+    i = 0;
+    for (y=0 ; y < gif_height ; y++) {
+        for (x=0 ; x < gif_width ; x++) {
+            indices_data[x+y*((gif_width + 3) & -4)] = gif_image_data_ref[i];
+            i++;
+        }
+    }
+    image_data = indices_data;
+    /*
+     * destruct
+     */
+    if (GifFile) {
+        DGifCloseFile(GifFile);
+    }
+    return image_data;
+}
+
+unsigned char *
+gifconv_lossless2gif(void *image_data,
+                     unsigned short width, unsigned short height,
+                     void *index_data,
+                     unsigned short index_data_count,
+                     int tag_no, int format,
+                     unsigned long *length) {
+    GifFileType *GifFile = NULL;
+    GifColorType *Colors = NULL;
+    int ColorCount;
+    my_gif_buffer gif_buff;
+    gif_uint_32 gif_width = 0, gif_height = 0;
+    int bpp;
+    gif_bytep gif_image_data = NULL;
+    gif_uint_32 x, y;
+    gif_colorp gif_palette = NULL;
+//    int trans_index = -1;
+    int i;
+    if (format != 3) {
+        fprintf(stderr, "jpegconv_lossless2gif: format=%d not implemented yes.\n", format);
+        return NULL;
+    }
+    bpp = 8;
+    gif_width = width;
+    gif_height = height;
+    ColorCount = 256;
+    Colors = calloc(sizeof(GifColorType), ColorCount);
+    
+    gif_buff.data = NULL;
+    gif_buff.data_len = 0;
+    gif_buff.data_offset = 0;
+    GifFile = EGifOpen(& gif_buff, gif_data_write_func);
+    if (GifFile == NULL) {
+        fprintf(stderr, "gifconv_lossless2gif: can't open GIFFile\n");
+        return NULL;
+    }
+    GifFile->SWidth  = gif_width;
+    GifFile->SHeight = gif_height;
+    GifFile->SColorResolution = bpp;
+
+    gif_palette = (gif_colorp) malloc(sizeof(gif_color)*index_data_count);
+    
+    if (tag_no == 20) {
+        swf_rgb_t *rgb_list  = index_data;
+        for (i=0 ; i < index_data_count ; i++) {
+            Colors[i].Red   = rgb_list[i].red;
+            Colors[i].Green = rgb_list[i].green;
+            Colors[i].Blue  = rgb_list[i].blue;
+        }
+    } else {
+        swf_rgba_t *rgba_list  = index_data;
+        for (i=0 ; i < index_data_count ; i++) {
+//            if (rgba_list[i].alpha)
+            Colors[i].Red   = rgba_list[i].red;
+            Colors[i].Green = rgba_list[i].green;
+            Colors[i].Blue  = rgba_list[i].blue;
+//                gif_palette[i].alpha = ;
+        }
+    }
+    GifFile->SBackGroundColor = 0; // XXX
+    gif_image_data = (gif_bytep) calloc(sizeof(unsigned char), gif_width * gif_height);
+    i = 0;
+    for (y=0 ; y < gif_height ; y++) {
+        for (x=0 ; x < gif_width ; x++) {
+            unsigned char *data = image_data;
+            gif_image_data[i] = data[x + y*((gif_width +3) & -4)];
+            i++;
+        }
+    }
+
+    GifFile->SavedImages[0].RasterBits = gif_image_data;
+    GifFile->SColorMap = MakeMapObject(ColorCount, Colors);
+    EGifSpew(GifFile); // XXX
+
+    free(gif_image_data);
+
+    if (GifFile) {
+        EGifCloseFile(GifFile);
+    }
+    *length = gif_buff.data_offset;
+    return gif_buff.data;
+}
diff --git a/src/swf_gif.h b/src/swf_gif.h
new file mode 100644 (file)
index 0000000..7559f8f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  +----------------------------------------------------------------------+
+  | Author: yoya@awm.jp                                                  |
+  +----------------------------------------------------------------------+
+*/
+
+extern void *
+gifconv_gif2lossless(unsigned char *gif_data, unsigned long gif_data_len,
+                     int *tag, int *format,
+                     unsigned short *width, unsigned short *height,
+                     void **colormap, int *colormap_count);
+
+extern unsigned char *
+gifconv_lossless2gif(void *image_data,
+                     unsigned short width, unsigned short height,
+                     void *index_data,
+                     unsigned short index_data_count,
+                     int tag, int format,
+                     unsigned long *length);