フラッシュ 抽出したデータの取扱
後々にフラッシュの解析等も解説したいと思う.
艦これ(艦娘)のフラッシュには, 画像データがJPEGとして入っている場合がある.
フラッシュのJPEGタグについては下記のリンクを見ていただきたい.
Flash SWF format - Jpeg - Yoya Wiki
画像データの後ろにアルファ値, つまり透明色が配置されている.
その透明色のみを画像にすると(ここでは大淀さん)
左が抽出したJPEGデータ, 右がアルファ値のみを画像としたデータ.
これをPNGに変換すると,
これがサンプルコード.
手順は
・JPEGのRGBを取得
・ALPHAの取得
・RGBA配列としてPNGに保存
のような感じです.
ちなみに013.jpg, 013.alphaなどがありますが'013'はswf内のイメージIDです.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <jpeglib.h> #include <png.h> #define JPEG_PATH "./013.jpg" #define ALPHA_PATH "./013.alpha" /* src/main.c */ unsigned char **jpeg_src( int *width, int *height, unsigned char **src); unsigned char **alpha_src(const int width, const int height, unsigned char **src); int build_png( int width, int height, unsigned char **alpha, unsigned char **src); int main(int argc, char *argv[]) { int i; int width = 0; int height = 0; unsigned char **alpha = NULL; unsigned char **jpeg = NULL; /* unsigned char **型のjpegデータの取得 */ jpeg = jpeg_src(&width, &height, jpeg); /* unsigned char **型のalphaデータの取得 */ alpha = alpha_src(width, height, alpha); build_png(width, height, alpha, jpeg); /* 終了処理 */ for(i = 0; i < height; i++) free(jpeg[i]); free(jpeg); for(i = 0; i < height; i++) free(alpha[i]); free(alpha); return 0; } unsigned char **jpeg_src( int *width, int *height, unsigned char **src) { int i; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; FILE *fp; if((fp = fopen(JPEG_PATH, "rb")) == NULL) { perror(JPEG_PATH); return NULL; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); *width = cinfo.output_width; *height = cinfo.output_height; src = (unsigned char **)calloc( *height, sizeof(unsigned char **)); for(i = 0; i < *height; i++) src[i] = (unsigned char *)calloc( *width, sizeof(unsigned char *)); while(cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, src + cinfo.output_scanline, cinfo.output_height - cinfo.output_scanline); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return src; } unsigned char **alpha_src( const int width, const int height, unsigned char **src) { int i; FILE *fp; size_t bytes = 0; if((fp = fopen(ALPHA_PATH, "r")) == NULL) { perror(ALPHA_PATH); return NULL; } src = (unsigned char **)calloc(height, sizeof(unsigned char **)); for(i = 0; i < height; i++) src[i] = (unsigned char *)calloc(width, sizeof(unsigned char *)); for(i = 0; i < height; i++) { if((bytes = fread(src[i], sizeof(unsigned char), width, fp)) != width) { return NULL; } if(bytes == 0) break; } fclose(fp); return src; } int build_png( int width, int height, unsigned char **alpha, unsigned char **src) { int i, j; FILE *fp; png_structp png_ptr; png_infop info_ptr; unsigned char **data; if((fp = fopen("./013.png", "wb")) == NULL) { return EOF; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE); /* 画像データの変換 */ data = (unsigned char **)calloc(height, sizeof(unsigned char **)); for(i = 0; i < height; i++) { data[i] = (unsigned char *)calloc(width, sizeof(unsigned char *)); for(j = 0; j < width; j++) { data[i][j * 4 + 0] = src[i][j * 3 + 0]; /* Red */ data[i][j * 4 + 1] = src[i][j * 3 + 1]; /* Green */ data[i][j * 4 + 2] = src[i][j * 3 + 2]; /* Blue */ data[i][j * 4 + 3] = alpha[i][j]; /* Alpha */ } } /* pngの書き込み */ png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, data); png_write_end(png_ptr, info_ptr); /* png_ptr等の破棄 */ png_destroy_write_struct(&png_ptr, &info_ptr); /* data領域の解放 */ for(i = 0; i < height; i++) free(data[i]); free(data); fclose(fp); return 1; }