C言語 メモリ上にある、PNGデータをlibpngを介して読み込むサンプル。
メモリ上に確保したPNGデータをlibpngに読み込んでもらってlibpngから画像データを取得してみる感じです。
/* read_png_from_mem.c * メモリ上にある、PNGデータをlibpngを介して読み込むサンプル。 * 参考: * http://d.hatena.ne.jp/yoya/20080714 * http://diary.awm.jp/~yoya/data/2008/07/14/png_test.c * http://gmoon.jp/png/ */ #include <stdio.h> #include <stdlib.h> #include <png.h> typedef struct my_png_buffer_ { unsigned char *data; /* PNGのデータが入ったメモリへのポインタ */ unsigned long data_len; /* PNGのデータの長さ。 */ unsigned long data_offset; /* 読み込み時用のオフセット */ } my_png_buffer; void test(void); void png_memread_func(png_structp png_ptr, png_bytep buf, png_size_t size); int main(void) { test(); return 0; } /* メモリ上のPNGデータをlibpngの指定するメモリにコピー(読み込み)。 * * この関数は、png_set_read_fn関数の第三引数に指定される事により、PNG画像の * データ読み込み時にコールバック(実行)されるようになります。 * * png_structp png_ptr png_set_read_fnで一番目の引数に指定された * png_structp構造体。 * この構造体からpng_set_read_fnで * 二番目の引数に指定されたデータ * (つまり、ストリームへのポインタ)を * png_get_io_ptr()で取得できます。 * * png_bytep buf コピー(読み込み)先となるメモリ。 * * png_size_t size コピーすべき(読み込むべき)長さ(バイト)。 */ void png_memread_func(png_structp png_ptr, png_bytep buf, png_size_t size){ /* 読み込むメモリの長さを表示。 */ printf("memRead - size =\t%04ld bytes\n", size); /* ストリームとして指定したデータを取得。 */ my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); /* 読み込むメモリの長さとオフセット(今までに読み込んだメモリの長さ)が * データの長さを越えていないかチェック。 */ if (png_buff->data_offset + size <= png_buff->data_len) { /* メモリのコピー */ memcpy(buf, png_buff->data + png_buff->data_offset, size); /* オフセットに今し方読み込んだメモリの長さを追加。 */ png_buff->data_offset += size; /* オフセットを表示 */ //printf("memRead - offset =\t%08ld bytes\n", png_buff->data_offset); } else { png_error(png_ptr,"png_mem_read_func failed"); } } void test(void) { png_structp png_ptr; png_infop info_ptr; my_png_buffer png_buf; FILE *fp; /* ファイルオープン */ if((fp = fopen("image.png", "rb")) == NULL){ fprintf(stderr, "%s%s\n","error::", "can not open image."); exit(EXIT_FAILURE); } /* ファイルサイズの取得 */ fseek(fp, 0L, SEEK_END); fgetpos(fp, &(png_buf.data_len)); fseek(fp, 0L, SEEK_SET); printf("filesize = %ld\n", png_buf.data_len); /* PNGデータ用のメモリ確保 */ png_buf.data = calloc(png_buf.data_len, 1); /* ファイル読み込み */ fread(png_buf.data, 1, png_buf.data_len, fp); /* オフセットはまだゼロ。 */ png_buf.data_offset = 0; /* ファイルを閉じます */ fclose(fp); /* PNGファイルかどうかの確認 */ int is_png; is_png = png_check_sig((png_bytep)png_buf.data, 8); if (! is_png) { fprintf(stderr, "%s%s\n", "error::", "is not PNG!"); exit(EXIT_FAILURE); } /* png_ptr構造体を確保・初期化します */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr==NULL){ exit(EXIT_FAILURE); } /* info_ptr構造体を確保・初期化します */ info_ptr=png_create_info_struct(png_ptr); if(info_ptr==NULL){ png_destroy_read_struct(&png_ptr,NULL,NULL); exit(EXIT_FAILURE); } /* ファイルの読み込み時に使用するデータ及び、関数を指定します。 */ png_set_read_fn(png_ptr,(png_voidp)&png_buf, (png_rw_ptr)png_memread_func); /* 画像情報の取得 */ png_uint_32 width,height; int bit_depth,color_type,interlace_type; int compression_type,filter_type; /* 画像情報を読み込みます。 */ printf("\nstart\treading information.\n"); png_read_info(png_ptr,info_ptr); printf("exit\treading information.\n\n"); printf("\nstart\tgetting IHDR chunk.\n"); png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type, &interlace_type,&compression_type,&filter_type); printf("exit\tgetting IHDR chunk.\n\n"); printf("(width, height)=(%ld,%ld) bpp=%d color_type=%d\n", width, height, bit_depth, color_type); //printf("\n", width, height); /* 画像イメージの取得 */ unsigned char **image; int i, j; /* 以下3行は2次元配列を確保します */ image = (png_bytepp)malloc(height * sizeof(png_bytep)); for (i = 0; i < height; i++) image[i] = (png_bytep)malloc( png_get_rowbytes(png_ptr, info_ptr)); /* イメージを読み込みます */ printf("\nstart\treading image.\n"); png_read_image(png_ptr, image); printf("exit\treading image.\n\n"); /* 読み込みが終了したのでPNGデータの入ったメモリを開放。 */ free(png_buf.data); for(i = 0; i < height; i+=height/38){ //printf("%d, %d, ", i, j); for(j = 0; j < width; j+=width/38) { printf("%02x", image[i][j*4]); } printf("\n"); } /* 以下2行は2次元配列を解放します */ for (i = 0; i < height; i++) free(image[i]); free(image); png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)NULL); }
参考:
(ファイルでなく)配列変数で PNGデータを libpng に渡す方法 - yoyaのメモ
http://diary.awm.jp/~yoya/data/2008/07/14/png_test.c
PNG 利用術