「りも」トップページへ
TIPS index へ

GdkPixbuf から PNG ファイルをセーブする

Mar.15.2000

libpng の基本とその使用方法。
画像データをファイルに保存する手段として libpng を扱う実験。 特に GdkPixbuf のデータを libpng で保存する方法。
純粋に書き出せれば良いので、本当に基礎的な事のみ扱う。


・ libpng 概説

libpng は PNG形式の画像ファイルを取り扱う為のライブラリです。 これを用いることにより比較的容易に PNG 形式を読み書きするプログラムが 作成できます。

・ GdkPixbuf を PNG で保存する

GdkPixbuf のバッファで保持されている画像を libpng によって PNG 形式で セーブする関数です。下記ソースを参照してください。

void  png_save(GdkPixbuf *pic, gchar *fname)
{
  FILE *fp;
  png_structp png_ptr;
  png_infop info_ptr;

  fp = fopen(fname, "wb");
  if (fp == NULL) {
    return;
  }

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
				    NULL, NULL, NULL);

  if (png_ptr == NULL) {
    fclose(fp);
    return;
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    fclose(fp);
    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    return;
  }

  if (setjmp(png_ptr->jmpbuf)) {
    fclose(fp);
    png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
    return;
  }

  /* ----- libpng にストリームを渡す */
  png_init_io(png_ptr, fp);

  /* ----- png タイプの設定 */
  if (gdk_pixbuf_get_has_alpha(pic) == TRUE) {
    png_set_IHDR(png_ptr, info_ptr,	
		 gdk_pixbuf_get_width(pic),
		 gdk_pixbuf_get_height(pic),
		 8,
		 PNG_COLOR_TYPE_RGB_ALPHA,
		 PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_BASE,
		 PNG_FILTER_TYPE_BASE);
  }
  else {
    png_set_IHDR(png_ptr, info_ptr,	
		 gdk_pixbuf_get_width(pic),
		 gdk_pixbuf_get_height(pic),
		 8,
		 PNG_COLOR_TYPE_RGB,
		 PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_BASE,
		 PNG_FILTER_TYPE_BASE);
  }

  /* ----- インフォメーションヘッダー書出し */
  png_write_info(png_ptr, info_ptr);

  /* ----- ピクセル書出し */
  { 
    png_uint_32  k, height;
    png_bytep row_pointers[gdk_pixbuf_get_height(pic)];
    height = gdk_pixbuf_get_height(pic);
    for(k=0; k<height; k++) {
      row_pointers[k] = gdk_pixbuf_get_pixels(pic) +
	(gdk_pixbuf_get_rowstride(pic) * k);
    }
    png_write_image(png_ptr, row_pointers);
  }

  /* ----- 書き出しの終了、後始末 */
  png_write_end(png_ptr, info_ptr);
  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

  fclose(fp);

  return;
}


rero2@yuumu.rim.or.jp