ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
まーさ
記事: 20
登録日時: 12年前

ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

#1

投稿記事 by まーさ » 12年前

ppm(P6)形式の画像(4行目までがテキスト、5行目からがバイナリ)の読み込みがうまくいきません。

4行目までの読み込みは、用意した string変数に格納され、cout で出力することで正しいと確認しています。
5行目(以下のコードでは「★うまくいかない部分★」と記載)以降で、ファイルを途中までしか読み取れず困っています。

途中までというのは、以下のように判断しています。

・画像格納配列image をファイルに出力すると、途中までになってします。
・画像格納配列image への読み込んだ unsined char値 を確認すると、途中から 全て0 になっている。

関係があるかわからないのですが、バイナリエディタで見たところ、1A 62 46 1F … から読み込まれいません。
また先頭 1A の ADDRESS は[横:0C、縦:390]です。

コード:

    std::ifstream file;
    // 画像格納配列
    unsigned char image[4000][4000][3];
    
    // 読み込んだ画像の解像度
    int width = 0;
    int height = 0;
    // 読み込んだ画像の諧調数
    int max_gray = 0;

    // 画像のpath
    string name = "読み込む画像のpath"

  file.open(name);

  //1行目の取得(画像の形式)
  std::string line;
    getline(file, line);

    // 3行目の取得(画像の解像度)
    while ( width == 0 || height == 0 ){
        std::string line;
        std::getline(file, line);
        // 2行目のコメント行を飛ばす
        if ( line.at(0) != '#' ) {
            sscanf_s( line.c_str(), "%d %d", &width, &height );
        }
    }

    // 4行目の取得(画像の諧調数)
    while ( max_gray == 0 ){
        std::string line;
        std::getline(file, line);
        if ( buffer[0] != '#' ){
            sscanf_s( line.c_str(), "%d", &max_gray );
        }
    }
  
    // 5行目の以降の取得…★うまくいかない部分★
    for(y=0;y<height;++y){
      for(x=0;x<width;++x){
        for(col=0;col<3;++col){
          file.read(reinterpret_cast<char*>(&image[x][y][col]), 1);
        }
      }
    }
エラー処理や例外処理は省いて掲載しています。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

#2

投稿記事 by みけCAT » 12年前

こちらでコンパイル可能なコードを作成し、192×128の画像と1024×1024の画像でテストしましたが、正常に動作するようでした。
読み込めない画像のサンプルをアップロードすることはできるでしょうか?(著作権に気をつけてください)

コード:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>

#define sscanf_s sscanf
#define buffer line

int main(void) {
	int x,y,col;

	std::ifstream file;
	// 画像格納配列
	//unsigned char image[4000][4000][3];
	static unsigned char image[4000][4000][3];
	
	// 読み込んだ画像の解像度
	int width = 0;
	int height = 0;
	// 読み込んだ画像の諧調数
	int max_gray = 0;

	// 画像のpath
	//string name = "test.ppm";
	const char* name = "test.ppm";

	file.open(name);

	//1行目の取得(画像の形式)
	std::string line;
	getline(file, line);
 
	// 3行目の取得(画像の解像度)
	while ( width == 0 || height == 0 ){
		std::string line;
		std::getline(file, line);
		// 2行目のコメント行を飛ばす
		if ( line.at(0) != '#' ) {
			sscanf_s( line.c_str(), "%d %d", &width, &height );
		}
	}
 
	// 4行目の取得(画像の諧調数)
	while ( max_gray == 0 ){
		std::string line;
		std::getline(file, line);
		if ( buffer[0] != '#' ){
			sscanf_s( line.c_str(), "%d", &max_gray );
		}
	}

	// 5行目の以降の取得…★うまくいかない部分★
	for(y=0;y<height;++y){
		for(x=0;x<width;++x){
			for(col=0;col<3;++col){
				file.read(reinterpret_cast<char*>(&image[x][y][col]), 1);
			}
		}
	}

	// 検証
	printf("line = %s\n",line.c_str());
	printf("width = %d, height = %d\n",width,height);
	printf("max_gray = %d\n",max_gray);
	puts("image data:");
	for(y=0;y<height;y++) {
		for(x=0;x<width;x++) {
			for(col=0;col<3;col++) {
				printf("%3d%c",(int)image[x][y][col],
					x+1==width && col+1==3?'\n':' ');
			}
		}
	}
	return 0;
}
添付ファイル
ppm_read.zip
検証に使用したデータ
(240.19 KiB) ダウンロード数: 163 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

#3

投稿記事 by みけCAT » 12年前

バイナリファイルはバイナリモードで開かないと、改行コードが自動変換されてデータが壊れる可能性があります。
まーささんが提示したコードの14行目を

コード:

file.open(name,file.in | file.binary);
としてください。
添付ファイル
ppm_read2.zip
検証用ファイル
(407.48 KiB) ダウンロード数: 131 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

まーさ
記事: 20
登録日時: 12年前

Re: ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

#4

投稿記事 by まーさ » 12年前

みけCATさん、ありがとうございます。

バイナリモードのご指摘もいただきありがとうございます。試してみます。

画像のサイズが大きいため、firestorageにアップロードいたしました。
http://xfs.jp/SHE7Se

解凍後、test.ppmが読み込み用画像、test_out.ppmが読み込んだ後、出力したデータです。
出力用コードは以下です。

コード:

    char name[] = "出力用ファイル名"
    // 画像用ループ変数
    int x,y,col;

    std::ofstream file;
    file.open(name, std::ios::out|std::ios::binary|std::ios::trunc);

    // PPMタイプ
    file << "P6" << std::endl;
    // コメント
    file << "# PPM image created by masa." << std::endl;
    // 解像度
    file << width << " " << height << std::endl; 
    // 諧調数
    file << "255" << std::endl;
    /* 画像データの出力 */
    for(y=0;y<height;y++){
        for(x=0;x<width;x++){
            for(col=0;col<3;col++){
               file.write(reinterpret_cast<char*>(&image[x][y][col]), 1);
            }
        }
    }
    file.close();

まーさ
記事: 20
登録日時: 12年前

Re: ppm形式(4行目までテキスト、5行目からバイナリ)の画像ファイル読み込みがうまくいきません

#5

投稿記事 by まーさ » 12年前

みけCATさん、先ほどいただいたバイナリモードのアドバイスを実践したところ、うまくいきました。
とても助かりました、ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る