
下記のプログラムはPGM画像に組織的ディザ法を行い、2値化を行うプログラムなのですがうまく作動しません。
どこがダメなのかわかる方回答お願いします。
また、PGMのフォーマットをP5しか読み込むことしか出来ないのですが、これを
P2のアスキーで読み込めるように変更できないでしょうか?
/* 組織的ディザ法のプログラム dither.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"mypgm.h"
#define BLOCK_SIZE 4 /* ブロックの横(=縦)画素数 */
#define NEW_LEVEL 16 /* 擬似階調数(= BLOCK_SIZE の2乗) */
#define MAXWIDTH 1000
#define MAXHEIGHT 1000
/* 原画像 image1[y][x] のディザ画像を作り image2[y][x] に代入 */
void make_dither_image( )
{
double width; /* 16段階画像の階調値の単位幅 */
int x,y,i,j,m,n;
int x_block = x_size1 / BLOCK_SIZE; /* 横のブロック数 */
int y_block = y_size1 / BLOCK_SIZE; /* 縦のブロック数 */
int gray_16 = (int)( image1[y][x] / width ); /* 新しい階調(16階調での値) */
/* Bayer 型ディザ行列 */
int dither_matrix [4][4] = {
{ 0, 8, 2, 10},
{12, 4, 14, 6},
{ 3, 11, 1, 9},
{15, 7, 13, 5}
};
/* 横,縦の画素数がBLOCK_SIZEの倍数であるかのチェック */
if ( x_size1 % BLOCK_SIZE != 0 || y_size1 % BLOCK_SIZE != 0 ){
printf("原画像の横・縦の画素数が不適切です.\n");
exit(1);
}
/* 16階調の画像を作る */ //一度、画像を16階調に変換して(正確にはディザブロック分の1)さらに2階調(白黒)に変換する。
width = MAX_BRIGHTNESS / (double)NEW_LEVEL;
x_size2 = x_size1; y_size2 = y_size1;
for (y = 0; y < y_size1; y ++ ){
for (x = 0; x < x_size1; x ++ ){
if ( gray_16 > NEW_LEVEL - 1 ) gray_16 = NEW_LEVEL - 1;
image2[y][x] = (unsigned char)gray_16;
}
}
/* ディザ画像を作る */
printf("ディザ画像を作ります.\n");
for (i = 0; i < y_block; i ++ ){
for (j = 0; j < x_block; j ++ ){
int x = BLOCK_SIZE * j;
int y = BLOCK_SIZE * i;
for (m = 0; m < BLOCK_SIZE; m ++ ){
for (n = 0; n < BLOCK_SIZE; n ++ ){
if ( image2[y + m][x + n] <= dither_matrix[m][n] ) image2[y + m][x + n] = 0;
else image2[y + m][x + n] = MAX_BRIGHTNESS;
}
}
}
}
}
【mypgm.h】
http://cis.k.hosei.ac.jp/~wakahara/mypgm.h
No.1ベストアンサー
- 回答日時:
P2形式のPGMに対応したいのであれば、画像読み込みルーチンの方をP2に対応させる必要がありますが、
今回挙げられているディザ処理そのものは、今のままでまったく問題はありません。
画像読み込み部の対応ですが、ヘッダ部はP5もP2も同じです。
実データ読み取り部で、P2だった時は fgetc の代わりに、
---
int value;
fscanf(fp, "%d", &value);
image[y][x] = value;
---
といったコードにするだけでいけます。
あと、今回の質問とは直接関係ありませんが、
4×4のディザの階調数は16ではなく17です。(「1が0個」~「1が16個」の17通り)
今のコードだと、一番明るい白が輝度値15にしていますが、15の時は4x4の左下が0になってしまい、全面白ではなく、黒の点が出てきます
この回答への補足
mtaka2さん
回答ありがとうございます。
mtaka2さんの言われたとおりに
int value;
fscanf(fp, "%d", &value);
image[y][x] = value;
に変更いたしましたが、P2のPGMファイルを読み込むと
「ファイルのフォーマットがP5ではありません」
と出てきて、操作を終了してしまいます。
下記のプログラムを変えなければならないのでしょうか?
初心者のために答えがわかりません。教えていただけないでしょうか。
fgets(buffer, MAX_BUFFERSIZE, fp);
if (buffer[0] != 'P' || buffer[1] != '5')
{
printf(" ファイルのフォーマットがP5ではありません\n\n");
exit(1);
No.2
- 回答日時:
・P2(テキスト)形式のpgmは、ファイルの先頭(1行目)が「P2」で始まります。
・P5(バイナリ)形式のpgmは、ファイルの先頭(1行目)が「P5」で始まります。
> if (buffer[0] != 'P' || buffer[1] != '5')
このif文は、「1文字目がP以外」もしくは「2文字目が5以外」だったら、真になり、printfとexitを実行します。
その結果、2文字が「P5」だった時にかぎり、exitしないという動作になります。
ですから「P2専用」にするなら、ここの「5」を「2」にすればOKです。
余力があるなら、「P2」と「P5」のどちらでも終了しないようにして、
P2のときはデータ読み込みにfscanfを使い、P5の時はfgetc、と使い分けるようなコードにした方がいいでしょう。
この回答への補足
コンパイルに成功し、P2のPGMデータも読み込み、ディザ画像を作ることに成功しました。本当にありがとうございます。
しかし、その画像が真っ黒でした…
どうしてなのでしょうか?
何度も初心者の質問をしてしまい、本当にすいません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
2の補数を計算するプログラム
-
画像の拡大・縮小
-
直線補間について
-
分数の足し算をさせるプログラ...
-
whileとifを使い偶数を出すには
-
C++で表を作成したいのです ...
-
| (or) を使った関数の引数の作...
-
最大公約数を求めるプログラム
-
nCrの計算
-
argvのNULLチェック
-
MFCでネガポジ変換
-
intとlongは同じ?
-
遺伝的アルゴリズム
-
Memoから行単位で文字列を取得...
-
低次元なコーディング方法について
-
Enterキーを押されたら次の処理...
-
C言語のfor文です。 繰り返しの...
-
Aの値からBの値を除するとは??
-
#define _CRT_SECURE_NO_WARNIN...
-
*をユーザーが入力した数字の数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
2の補数を計算するプログラム
-
intとlongは同じ?
-
条件が多い場合
-
再起呼び出しの回数をカウント...
-
argvのNULLチェック
-
C言語でDOS画面のプログラム(...
-
カードシャッフルのブログラム...
-
c++ TCHARで文字化け
-
複数の共有メモリの作成
-
C++ Debug Errorについて教えて
-
C++ bmp 透過処理
-
関数とビット列
-
OpenCVによる4値化について
-
コマンドプロンプトのウィンド...
-
ヌメロンのプログラム
-
for 分についてです
-
DXライブラリとC言語 fwrite関...
-
16bitで乱数を生成する方法
-
プログラミングに関して
-
C++で表を作成したいのです ...
おすすめ情報