スポンサーリンク

libpng 16bit PNG_COLOR_TYPE_GRAY 読み込み

前記事で出力した16bit grayscale画像を読み込む。

この場合も入力画像の一画素の前後を反転させなければならない。

読み込んだ画像
なぜかぼけるので拡大図
#pragma once

#include <cstdlib>
#include <iostream>
#include <bitset>

#include <png.h>

#pragma comment(lib,"libpng16d.lib")

//エラーの時強制終了
void abort_(const char* c) {
  printf(c);
  abort();
}

//! @brief pngファイル読み込み関数
//! @param [in] file_name ファイル名
//! @param [out] width 画像幅(ピクセル)
//! @param [out] height 画像高さ(ピクセル)
//! @param [out] color_type RGBかRGBAか...等
//! @param [out] bit_depth チャンネルのビット数
//! @param [out] row_pointers 画像データへのポインタのポインタ
void read_png(
  const char* file_name,
  int* width,
  int* height,
  png_byte* color_type,
  png_byte* bit_depth,
  png_bytep** row_pointers

) {

  png_byte  header[8];    // 8 is the maximum size that can be checked

  FILE* fp = fopen(file_name, "rb");
  if (!fp) {
    abort_("[read_png_file] File could not be opened for reading");
  }
  fread(header, 1, 8, fp);
  if (png_sig_cmp(header, 0, 8)) {
    abort_("[read_png_file] File is not recognized as a PNG file");
  }


  png_structp png_ptr;
  png_infop info_ptr;

  /* initialize stuff */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (!png_ptr)
    abort_("[read_png_file] png_create_read_struct failed");

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    abort_("[read_png_file] png_create_info_struct failed");

  if (setjmp(png_jmpbuf(png_ptr)))
    abort_("[read_png_file] Error during init_io");

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);

  png_read_info(png_ptr, info_ptr);

  /////////////////////////////////////////
  // 画像情報の取得
  *width = png_get_image_width(png_ptr, info_ptr);
  *height = png_get_image_height(png_ptr, info_ptr);
  *color_type = png_get_color_type(png_ptr, info_ptr);
  *bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  //
  /////////////////////////////////////////

  int number_of_passes;
  number_of_passes = png_set_interlace_handling(png_ptr);
  png_read_update_info(png_ptr, info_ptr);

  /* read file */
  if (setjmp(png_jmpbuf(png_ptr)))
    abort_("[read_png_file] Error during read_image");

  /////////////////////////////////////////
  // 画像の読み込み
  *row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * *height);

  for (int y = 0; y < *height; y++)
    (*row_pointers)[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr));

  png_read_image(png_ptr, *row_pointers);
  //
  /////////////////////////////////////////


  fclose(fp);
}

int main()
{
  int width;
  int height;
  png_byte color_type;
  png_byte bit_depth;

  png_bytep* row_pointers;

  ////////////////////////////////
  // 画像読み込み
  read_png(
    R"(c:\test\test_16bit_1x4.png)",
    &width,
    &height,
    &color_type,
    &bit_depth,
    &row_pointers
  );
  //
  ////////////////////////////////

  std::cout << "width : " << width << std::endl;
  std::cout << "height: " << height << std::endl;
  std::cout << "colortype: " << (int)color_type << std::endl;
  std::cout << "bitdepth: " << (int)bit_depth << std::endl;

  ////////////////////////////////
  //今回は1ビットグレイスケール画像だけを対象にする
  if ((color_type != PNG_COLOR_TYPE_GRAY) ||
    (bit_depth != 16)
    ) {
    return -1;
  }
  //
  ////////////////////////////////

  ////////////////////////////////
  // 内容を表示
  png_bytep yhead = row_pointers[0];
  png_bytep xpix = yhead;
  unsigned short* pp = (unsigned short*)xpix;

  std::swap(((unsigned char*)(&pp[0]))[0], ((unsigned char*)(&pp[0]))[1]);
  std::swap(((unsigned char*)(&pp[1]))[0], ((unsigned char*)(&pp[1]))[1]);
  std::swap(((unsigned char*)(&pp[2]))[0], ((unsigned char*)(&pp[2]))[1]);
  std::swap(((unsigned char*)(&pp[3]))[0], ((unsigned char*)(&pp[3]))[1]);

  std::cout << "[0]" << std::bitset<16>(pp[0]) << std::endl;
  std::cout << "[1]" << std::bitset<16>(pp[1]) << std::endl;
  std::cout << "[2]" << std::bitset<16>(pp[2]) << std::endl;
  std::cout << "[3]" << std::bitset<16>(pp[3]) << std::endl;
  //
  ///////////////////////////////////////////////
  ///////////////////////////////////////////////
  // メモリの解放
  for (size_t i = 0; i < (size_t)height; i++) {
    png_bytep yhead = row_pointers[i];
    free(yhead);
  }
  free(row_pointers);
  //
  ///////////////////////////////////////////////

  int i;
  std::cin >> i;

}

実行結果

libpngを試す(CMakeビルド)

libpngを試す(ファイル読み込み)

libpngを試す(ファイル書き込み)

libpng 1bit / 4bit PNG_COLOR_TYPE_GRAY 出力

libpng PNG_COLOR_TYPE_PALETTEでパレットを使った出力

libpng 1bit Grayscale画像の読み込み

libpng パレット色(PNG_COLOR_TYPE_PALETTE)画像の読み込み

libpng 16bit PNG_COLOR_TYPE_GRAY 読み込み

libpng 16bit PNG_COLOR_TYPE_GRAY 出力

setjmp / longjmp

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: