減色処理のプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
asbel

減色処理のプログラムについて

#1

投稿記事 by asbel » 9年前

下記のソース内について、inbmpに読み込んだビットマップで変換をしている部分があるのですが、こちらの部分を新たに追加したgausbmpの処理を行った後のデータでこの処理をやりたいのですがどうにもうまくいきません。
inbmpの部分をgausbmpに書き換えたところ、変換が行われずgausbmpの画像が出力されてしまいます。
質問がわかりにくいかもしれませんがどなたかアドバイスを頂けないでしょうか?

コード:

//#define D_euc	20.00		//ユークリッド距離の閾値。高いと、誤差拡散法の対象になる画素が減る。
//#define N		40		//最小二乗法の検索範囲
//#define N2		8		//最小二乗法の検索範囲の閾値	閾値が高いと検索範囲に近づく。
#define SAI_ON  1			// 1:最小二乗法を行う。 2:行わない。

#pragma warning(disable : 4996)
#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
#include <limits.h>
#include <math.h>
#include <float.h>
#include <assert.h>
#include <time.h>
#include <iostream>
#include "BmpIoLib.h"
#include "RGB.h"
#include "Claster.h"

#include <map>
#include <vector>
#include <string>

double D_euc = 100.0;	//ユークリッド距離の閾値。高いと、誤差拡散法の対象になる画素が減る。
int N = 10;			//最小二乗法の検索範囲
int N2 = 5;			//最小二乗法の検索範囲の閾値	閾値が高いと検索範囲に近づく。

using namespace std;

typedef CRGB< unsigned char > RGB_UC;
typedef CRGB< double > RGB_D;

IBMP* TranseBmp( const IBMP *pBmp, int BPP );
map< RGB_UC, int > CountColor( const IBMP *pBmp );
void BibBitmap( const IBMP *pBmp1, unsigned char *pBib );
void TranseColor_U256(const map< RGB_UC, int> &mapColor, const IBMP *sBmp, IBMP *dBmp, int BPP);
void Clastering( const pair< RGB_D, RGB_D > &range, vector< CClaster< RGB_D > > *pvClaster, unsigned int cnt );
unsigned int SearchColor( const RGB_UC *pIdxColor, unsigned int ColorCnt, const RGB_UC &rC, map< RGB_UC, int > *pIC );
void Edakari( int PixSize, vector< CClaster< RGB_D > > *pvClaster, unsigned int cnt );
void TranseColor_O256(const map< RGB_UC, int > &mapColor, const IBMP *sBmp, IBMP *dBmp, int BPP);

IBMP* Transgaus(const IBMP *pBmp, int BPP);

int bunpu[512];


IBMP *Bmp_gaus;			//ガウシアンフィルタ後のBMP


int help()
{
	fprintf( stderr, "dcol InputFile OutputFile [-b BitCount] [-d diza]\n" );
	fprintf( stderr, "BitCount : 1 or 4 or 8, default is 8.\n" );
	return 1;
}

int main( int argc, char *argv[] )
{
	IBMP *inbmp = NULL;
	IBMP *outbmp = NULL;
	FILE *infile = NULL;
	FILE *outfile = NULL;
	int BitPerPix;
	int r = 1;
	int i;
	clock_t start, end;

	IBMP *gausbmp = NULL;  //ガウシアンフィルタ後のBMP
	IBMP *gausinbmp = NULL;
	FILE *gausinfile = NULL;

	//#defineの変数部分をここでやる。変数を変更するたびにビルドする手間を省くため。(バッチ用)
	/*
	help()の中身かこれでやると変わるのでここに追記。
	fprintf( stderr, "dcol InputFile OutputFile [-b BitCount] [-d diza]\n" );
	が
	fprintf( stderr, "dcol InputFile OutputFile D_euc N N2 D_sai [-b BitCount] [-d diza]\n" );
	となるので注意
	*/
	D_euc = atof(argv[3]);
	N = atoi(argv[4]);
	N2 = atoi(argv[5]);

	//デバッグ用(変数がしっかり入ってるか確認するためのもの)
	printf("ユークリッド:%.2f\t検索範囲:%d\t範囲の閾値:%d\n",D_euc,N,N2);


	if ( argc < 3 ) return help();

	
	// bunpuを初期化
	for(i=0;i<512;i++) bunpu[i] = 0;


	// 引数の値を取得
	BitPerPix = 8;
	for ( i = 3; i < argc; i++ ) {
		if ( string( "-b" ) == string( argv[i] ) && i < argc - 1 ) {
			BitPerPix = atoi( argv[i+1] );
			i++;
		}
	}

	if ( BitPerPix != 1 && BitPerPix != 4 && BitPerPix != 8 )
		return help();


	start = clock();
	// 入力ファイルを開く
	infile = fopen( argv[1], "rb" );
	if ( NULL == infile ) {
		fprintf( stderr, "Failed to open file. : %s\n", argv[1] );
		goto ERR_EXIT;
	}

	// ビットマップを読み込む
	inbmp = BmpIO_Load( infile );
	if ( NULL == inbmp ) {
		fprintf( stderr, "Failed to load bitmap. : %s\n", argv[1] );
		goto ERR_EXIT;
	}


	// ガウシアンフィルタ
	gausbmp = Transgaus( inbmp, 24 );

	// 出力用のファイルを開く
	outfile = fopen("gausout.bmp", "wb");
	if (NULL == outfile) {
		fprintf(stderr, "Failed to open file. : %s\n", "gausout.bmp");
		goto ERR_EXIT;
	}

	// イメージを出力する
	if (!BmpIO_Save(outfile, gausbmp)) {
		fprintf(stderr, "Failed to save bitmap. : %s\n", "gausout.bmp");
		goto ERR_EXIT;
	}
	fclose(outfile);



	// 変換する
	outbmp = TranseBmp(inbmp, BitPerPix);
	if ( NULL == outbmp ) {
		fprintf( stderr, "Failed to transerate bitmap.\n" );
		goto ERR_EXIT;
	}

	// 出力用のファイルを開く
	outfile = fopen( argv[2], "wb" );
	if ( NULL == outfile ) {
		fprintf( stderr, "Failed to open file. : %s\n", argv[2] );
		goto ERR_EXIT;
	}

	// イメージを出力する
	if ( !BmpIO_Save( outfile, outbmp ) ) {
		fprintf( stderr, "Failed to save bitmap. : %s\n", argv[2] );
		goto ERR_EXIT;
	}

	end = clock();

    printf("計算時間は%.2f秒です\n", (double)(end - start)/CLOCKS_PER_SEC);

	r = 0;

ERR_EXIT:
	if ( inbmp ) BmpIO_DeleteBitmap( inbmp );
	if ( outbmp ) BmpIO_DeleteBitmap( outbmp );
	inbmp = NULL;
	outbmp = NULL;
	if ( infile ) fclose( infile );
	if ( outfile ) fclose( outfile );
	infile = NULL;
	outfile = NULL;

	return r;
}

// 色の変換を行う
IBMP* TranseBmp( const IBMP *pBmp, int BPP )
{
	IBMP *rBmp = NULL;
	map< RGB_UC, int > mapColor;

	if ( NULL == pBmp ) return NULL;
	if ( BmpIO_GetBitPerPixcel( pBmp ) == BPP )
		return BmpIO_CopyBitmap( pBmp );

	// 出力用のイメージを構築
	rBmp = BmpIO_CreateBitmap( pBmp->width, pBmp->height, BPP );
	if ( NULL == rBmp ) return NULL;

	// 色を数え上げる
	mapColor = CountColor( pBmp );

	// 変換する
	if ( mapColor.size() <= (unsigned int)( 0x1 << BPP ) ) {
		TranseColor_U256( mapColor, pBmp, rBmp, BPP );
	}
	else {
		TranseColor_O256( mapColor, pBmp, rBmp, BPP );
	}

	return rBmp;
}

// 色の変化が大きい部分を抽出する。
// pBibには、各ピクセルごとの傾きの大きさを格納する。
void BibBitmap( const IBMP *pBmp1, unsigned char *pBib )
{
	int i, j, k, l;
	int width, height;
	double sum;
	RGB_UC pTable[3][3];	// 作業用に、注目しているピクセルの周囲のピクセルを保持する。
	int stbl[4][2][2] = {
		{ { 0, 0 }, { 2, 2 } },
		{ { 1, 0 }, { 1, 2 } },
		{ { 2, 0 }, { 0, 2 } },
		{ { 0, 1 }, { 2, 1 } }
	};

	// イメージの幅と高さを取得
	width = BmpIO_GetWidth( pBmp1 );
	height = BmpIO_GetHeight( pBmp1 );

	for ( i = 0; i < height; i++ ) {
		for ( j = 0; j < width; j++ ) {
			// ( j, i )のピクセルを取得する。
			pTable[1][1] = RGB_UC( BmpIO_GetR( j, i, pBmp1 ), BmpIO_GetG( j, i, pBmp1 ), BmpIO_GetB( j, i, pBmp1 ) );

			// ( j, i )の周囲にあるピクセルを取得する。
			for ( k = -1; k < 2; k++ ) {
				for ( l = -1; l < 2; l++ ) {
					// 画像の範囲外の部分は、( j, i )と同じ値にしておく。
					if ( j + l < 0 || j + l >= width || i + k < 0 || i + k >= height )
						pTable[ k + 1 ][ l + 1 ] = pTable[1][1];
					else
						pTable[ k + 1 ][ l + 1 ] = RGB_UC( BmpIO_GetR( j, i, pBmp1 ), BmpIO_GetG( j, i, pBmp1 ), BmpIO_GetB( j, i, pBmp1 ) );
				}
			}

			// 向かい合うピクセル同士で、色の差を求め、合計する。
			sum = 0.0;
			for ( k = 0; k < 4; k++ )
				sum += pTable[ stbl[k][0][0] ][ stbl[k][0][1] ].Distance( pTable[ stbl[k][1][0] ][ stbl[k][1][1] ] );

			// 「差の合計」を1~255の範囲に調節する。
			sum = sum * 255.0 / 1774.0 + 1.0;
			pBib[ i * width + j ] = (unsigned char)sum;
		}
	}
}


// 使用されている色を数え上げる
// (単純にピクセル数を求めるだけではない)
map< RGB_UC, int > CountColor( const IBMP *pBmp )
{
	int i;
	int j;
	RGB_UC rgb;
	map< RGB_UC, int > mapColor;	// 色のヒストグラムを保持する
	map< RGB_UC, int >::iterator itr = mapColor.end();
	int width;
	int height;
	unsigned char *pBib;
	unsigned char omomi;

	// イメージの幅と高さを取得する。
	height = BmpIO_GetHeight( pBmp );
	width = BmpIO_GetWidth( pBmp );

	// 色の変化が大きいところを抽出する
	pBib = (unsigned char*)malloc( sizeof( unsigned char ) * height * width );
	BibBitmap( pBmp, pBib );

	for ( i = 0; i < height; i++ ) {
		for ( j = 0; j < width; j++ ) {
			// ピクセルの「重み」を求める
			// (変化が少ないところを優先する。)
			omomi = 256 - pBib[ i * width + j ];

			// 色を取得
			rgb = RGB_UC( BmpIO_GetR( j, i, pBmp ), BmpIO_GetG( j, i, pBmp ) , BmpIO_GetB( j, i, pBmp ) );

			// 前と同じ色ならmapの検索を省略する。
			if ( itr != mapColor.end() && itr->first == rgb ) {
				itr->second += omomi;
				continue;
			}

			// ヒストグラムを保持するmapを検索する。
			itr = mapColor.find( rgb );

			if ( itr == mapColor.end() )
				mapColor.insert( pair< RGB_UC, int >( rgb, omomi ) );
			else
				itr->second += omomi;
		}
	}
	return mapColor;
}

// 使用されている色が256色以下だった場合
// (使用されている全ての色をカラーテーブルに登録、
//  各ピクセルには、一致する色を保持している、カラーテーブルのインデックス値を設定する。)
void TranseColor_U256( const map< RGB_UC, int > &mapColor, const IBMP *sBmp, IBMP *dBmp, int BPP )
{
	int i, j;
	map< RGB_UC, int > mapIndex;	// 色に対応するインデックスを保持する
	map< RGB_UC, int >::iterator itr;
	RGB_UC rgb;
	const unsigned int ColorCnt = ( 0x1 << BPP );	// 色数

	assert( ColorCnt >= mapColor.size() );

	// 色に対応するインデックスを生成
	// カラーテーブルに値を設定
	mapIndex = mapColor;
	i = 0;
	for ( itr = mapIndex.begin(); itr != mapIndex.end(); itr++ ) {
		// 色に対するインデックス値を設定
		itr->second = i;
		// カラーテーブルに色を設定
		BmpIO_SetColorTableR( i, dBmp, itr->first.r );
		BmpIO_SetColorTableG( i, dBmp, itr->first.g );
		BmpIO_SetColorTableB( i, dBmp, itr->first.b );
		i++;
	}

	// ピクセルにインデックス値を設定
	for ( i = 0; i < BmpIO_GetHeight( sBmp ); i++ ) {
		for ( j = 0; j < BmpIO_GetWidth( sBmp ); j++ ) {
			// 色を取得
			rgb = RGB_UC( BmpIO_GetR( j, i, sBmp ), BmpIO_GetG( j, i, sBmp ), BmpIO_GetB( j, i, sBmp ) );

			// インデックスの値を設定
			itr = mapIndex.find( rgb );
			if ( itr != mapIndex.end() )
				BmpIO_SetPixcel( j, i, dBmp, itr->second );
			else
				BmpIO_SetPixcel( j, i, dBmp, 0 );
		}
	}
}

// クラスタ分析により、近い色をまとめる
void Clastering( const pair< RGB_D, RGB_D > &range, vector< CClaster< RGB_D > > *pvClaster, unsigned int cnt )
{
	vector< pair< RGB_D, RGB_D > > vSubRange;
	vector< vector< CClaster< RGB_D > > > vSubClaster;
	unsigned int i, j;
	bool flg;
	const RGB_D RANGE_MIN( 0.0, 0.0, 0.0 );
	const RGB_D RANGE_MAX( 256.0, 256.0, 256.0 );

	


	if ( pvClaster->size() <= 1 ) return ;

	// 指定された領域を分割する
	vSubRange = range.first.DiviteRange( range.second );

	for ( i = 0; i < vSubRange.size(); i++ )
		vSubClaster.push_back( vector< CClaster< RGB_D > >() );

	// 分割された領域に含まれる点を求める
	for ( i = 0; i < pvClaster->size(); i++ ) {
		for ( j = 0; j < vSubRange.size(); j++ ) {
			if ( (*pvClaster)[i].GetValue().IsIncluded( vSubRange[j].first, vSubRange[j].second ) )
				break;
		}
		if ( j < vSubClaster.size() )
			vSubClaster[j].push_back( (*pvClaster)[i] );
	}

	// それぞれの領域ごと、クラスタ分析を実施する
	for ( i = 0; i < vSubClaster.size(); i++ ) {
		double wcnt = (double)cnt * ( (double)vSubClaster[i].size() / (double)pvClaster->size() );
		Clastering( vSubRange[i], &(vSubClaster[i]), (int)wcnt + 1 );
	}
	pvClaster->clear();

	// 分析結果をpvClasterに戻す
	for ( i = 0; i < vSubClaster.size(); i++ ) {
		for ( j = 0; j < vSubClaster[i].size(); j++ )
			pvClaster->push_back( vSubClaster[i][j] );
		vSubClaster[i].clear();
	}
	vSubClaster.swap( vector< vector< CClaster< RGB_D > > >() );

	// 近い距離にある点をまとめる。
	flg = true;
	while ( flg && pvClaster->size() > cnt ) {
		double w = DBL_MAX;
		int pair1 = -1, pair2 = -1;
		flg = false;

		// 一番近い距離にあるクラスタを求める
		for ( i = 0; i < pvClaster->size() - 1; i++ ) {
			double wd1 = (*pvClaster)[i].GetValue().DistFromBoundary( range.first, range.second, RANGE_MIN, RANGE_MAX );

			for ( j = i + 1; j < pvClaster->size(); j++ ) {
				// 二点間の距離と領域の淵からの距離を求める
				double d1 = (*pvClaster)[i].GetValue().Distance( (*pvClaster)[j].GetValue() );
				double wd2 = (*pvClaster)[j].GetValue().DistFromBoundary( range.first, range.second, RANGE_MIN, RANGE_MAX );

				// 二点間の距離が今までの中で最も近く、
				// かつ、領域の淵からの距離よりも、二点間の距離の方が近かったら、その値を退避する。
				// (領域の外側には点がある可能性がある)
				if ( d1 < wd1 && d1 < wd2 && d1 < w ) {
					w = d1;
					pair1 = i;
					pair2 = j;
				}
			}
		}
		if ( w < DBL_MAX && pair1 >= 0 && pair2 >= 0 ) {
			// 二つのクラスタを融合する
			(*pvClaster)[pair1] = (*pvClaster)[pair1] + (*pvClaster)[pair2];
			pvClaster->erase( pvClaster->begin() + pair2 );
			flg = true;
		}
	}
	
}

// 面積が閾値以下しかない奴は、近い色に併合してしまう
// (処理速度向上のため)
void Edakari( int PixSize, vector< CClaster< RGB_D > > *pvClaster, unsigned int cnt )
{
	unsigned int i, j, k;
	double w1, w2;
	const int SIKII = (int)(PixSize * 0.0001);

	if ( pvClaster->size() == 0 ) return ;
	if ( (*pvClaster)[0].GetCount() <= SIKII ) return ;

	i =(unsigned int)( pvClaster->size() - 1);
	while ( pvClaster->size() >= cnt && (*pvClaster)[i].GetCount() <= SIKII ) {
		// 最も近い色を検索する
		k = 0;
		w1 = DBL_MAX;
		for ( j = 0; j < i && (*pvClaster)[j].GetCount() > SIKII ; j++ ) {
			w2 = (*pvClaster)[i].GetValue().Distance( (*pvClaster)[i].GetValue() );
			if ( w2 < w1 ) {
				w1 = w2;
				k = j;
			}
		}
		// 併合する
		(*pvClaster)[k] = (*pvClaster)[k] + (*pvClaster)[i];
		pvClaster->pop_back();
		i = i - 1;
	}
}

// カラーテーブルの中から一番近い色を検索する
unsigned int SearchColor( const RGB_UC *pIdxColor, unsigned int ColorCnt, const RGB_UC &rC, map< RGB_UC, int > *pIC )
{
	double w = DBL_MAX;
	unsigned int min_idx;
	unsigned int i;
	map< RGB_UC, int >::iterator itr;

	// キャッシュを検索する
	itr = pIC->find( rC );
	if ( itr != pIC->end() )
		return itr->second;

	for ( i = 0; i < ColorCnt; i++ ) {
		double w2 = pIdxColor[i].Distance( rC );
		if ( w2 < w ) {
			w = w2;
			min_idx = i;
			// 十分に近い色が見つかったら、その時点で検索を打ち切る
			if ( w < 1.7321 ) break;
		}
	}
	pIC->insert( pair< RGB_UC, int >( rC, min_idx ) );
	return min_idx;
}

void TranseColor_O256(const map< RGB_UC, int > &mapColor, const IBMP *sBmp, IBMP *dBmp, int BPP )
{
	vector< CClaster< RGB_D > > vClaster;
	map< RGB_UC, int >::const_iterator itr_c;
	map< RGB_UC, int > mapIndexCash;
	unsigned int i, j;
	unsigned int height;
	unsigned int width;
	const unsigned int ColorCnt = ( 0x1 << BPP );
	CRGB< int > *pBuf[2];
	RGB_UC *pIdxCol;
	double pop=0.0;

	// イメージの幅と高さを取得する
	height = (unsigned int)BmpIO_GetHeight( sBmp );
	width = (unsigned int)BmpIO_GetWidth( sBmp );

	// 誤差を保持するためのバッファを用意する。
	pBuf[0] = new CRGB< int >[ width + 1 ];
	pBuf[1] = new CRGB< int >[ width + 1 ];

	// カラーテーブルの値を保持する
	pIdxCol = new RGB_UC[ ColorCnt ];

	// 色の情報をクラスタの配列に格納する
	for ( itr_c = mapColor.begin(); itr_c != mapColor.end(); itr_c++ )
		vClaster.push_back( CClaster< RGB_D >( RGB_D( itr_c->first.r, itr_c->first.g, itr_c->first.b ), itr_c->second ) );

	// 細かい奴を除去してしまう
	Edakari( height * width, &vClaster, ColorCnt );

	// クラスタ分析により、色を抽出する
	Clastering( pair< RGB_D, RGB_D >( RGB_D( 0.0, 0.0, 0.0 ), RGB_D( 360.0, 256.0, 256.0 ) ), &vClaster, ColorCnt );

	// カラーテーブルに値を設定
	for ( i = 0; i < ColorCnt; i++ ) {
		CRGB< double > wrgb = vClaster[i].GetValue();
		pIdxCol[i] = RGB_UC( (unsigned char)wrgb.r, (unsigned char)wrgb.g, (unsigned char)wrgb.b );
		BmpIO_SetColorTableR( i, dBmp, pIdxCol[i].r );
		BmpIO_SetColorTableG( i, dBmp, pIdxCol[i].g );
		BmpIO_SetColorTableB( i, dBmp, pIdxCol[i].b );
	}

			unsigned int k;
			int t, q;
			double Aqr, Aqg, Aqb, Atr, Atg, Atb , Bqr, Bqg, Bqb, Btr, Btg, Btb;
			int widx1;
			int widx2;
			int wv;
			int Bq, Bt, Cqr, Cqg, Cqb, Ctr, Ctg, Ctb, Dqr, Dqg, Dqb, Dtr, Dtg, Dtb, Eq, Et;
			int Drgbr,Drgbg,Drgbb,Urgbr,Urgbg,Urgbb;
			int qNf,qNb,tNf,tNb;
	// ピクセルにインデックス値を設定
	for ( i = 0; i < height; i++ ) {
		for ( j = 0; j < width; j++ ) {
			/*unsigned int k;
			int t, q;
			double Aqr, Aqg, Aqb, Atr, Atg, Atb;
			int widx1 = i % 2;
			int widx2 = ( i + 1 ) % 2;
			int wv;
			int Bq, Bt, Cqr, Cqg, Cqb, Ctr, Ctg, Ctb, Dqr, Dqg, Dqb, Dtr, Dtg, Dtb, Eq, Et;
			*/
			widx1 = i % 2;
			widx2 = ( i + 1 ) % 2;

			unsigned char similarRi,similarGi,similarBi, similarRj,similarGj,similarBj;

			RGB_UC rgb2;


			t=q=0;
			Bq=Bt=Cqr=Cqg=Cqb=Ctr=Ctg=Ctb=Dqr=Dqg=Dqb=Dtr=Dtg=Dtb=Eq=Et=0;
			qNf=qNb=tNf=tNb=0;

			// 色を取得
			RGB_UC rgb( BmpIO_GetR( j, i, sBmp ), BmpIO_GetG( j, i, sBmp ), BmpIO_GetB( j, i, sBmp ) );		
			int ikm,ikp,jkm,jkp;
//			unsigned char similarRi,similarGi,similarBi, similarRj,similarGj,similarBj;

			//検索範囲の閾値の初期値設定下側
			Drgbr = rgb.r/2;
			Drgbg = rgb.g/2;
			Drgbb = rgb.b/2;
			//検索範囲の閾値の初期値設定上側
			Urgbr = rgb.r/2;
			Urgbg = rgb.g/2;
			Urgbb = rgb.b/2;


//最小二乗法 ここの処理をそっくり変更する。
			for ( q = -1; q >= -N; q-- ) {
					unsigned int i2, j2;
					i2 = i+q;
					j2 = j;
					if(i2<0) i2=0;
					if(i2>=height) i2 = height-1;
					RGB_UC rgb3( BmpIO_GetR( j2, i2, sBmp ), BmpIO_GetG( j2, i2, sBmp ), BmpIO_GetB( j2, i2, sBmp ) );
						Urgbr = Drgbr;
						Urgbg = Drgbg;
						Urgbb = Drgbb;
					if(i2>0 && i2<height-1){
						RGB_UC rgb4( BmpIO_GetR( j2, i2-1, sBmp ), BmpIO_GetG( j2, i2-1, sBmp ), BmpIO_GetB( j2, i2-1, sBmp ) );
						Urgbr = rgb4.r/2.0;
						Urgbg = rgb4.g/2.0;
						Urgbb = rgb4.b/2.0;
					}


					//printf("%.1f %.1f %.1f \t%.1f %.1f %.1f(%d %d %d)\n",Drgbr,Drgbg,Drgbb,Urgbr,Urgbg,Urgbb,rgb3.r,rgb3.g,rgb3.b);

					//エッジの判定をしている部分
					if((Drgbr+Urgbr-rgb3.r)*(Drgbr+Urgbr-rgb3.r) + (Drgbg+Urgbg-rgb3.g)*(Drgbg+Urgbg-rgb3.g) + (Drgbb+Urgbb-rgb3.b)*(Drgbb+Urgbb-rgb3.b)>=(N2*N2)){
						break;
					}

					Bq+=q*q;
					Cqr+=rgb3.r;
					Dqr+=q*rgb3.r;
					Cqg+=rgb3.g;
					Dqg+=q*rgb3.g;
					Cqb+=rgb3.b;
					Dqb+=q*rgb3.b;
					Eq+=q;
					Drgbr=rgb3.r/2.0; Drgbg=rgb3.g/2.0; Drgbb=rgb3.b/2.0;
			}
			qNb = abs(q)-1;
			Drgbr = rgb.r/2.0;
			Drgbg = rgb.g/2.0;
			Drgbb = rgb.b/2.0;


			for ( q = 0; q <= N; q++ ) {
					unsigned int i2, j2;
					i2 = i+q;
					j2 = j;
					if(i2<0) i2=0;
					if(i2>=height) i2 = height-1;
					RGB_UC rgb3( BmpIO_GetR( j2, i2, sBmp ), BmpIO_GetG( j2, i2, sBmp ), BmpIO_GetB( j2, i2, sBmp ) );
						Urgbr = Drgbr;
						Urgbg = Drgbg;
						Urgbb = Drgbb;
					if(i2>0 && i2<height-1){
						RGB_UC rgb4( BmpIO_GetR( j2, i2+1, sBmp ), BmpIO_GetG( j2, i2+1, sBmp ), BmpIO_GetB( j2, i2+1, sBmp ) );
						Urgbr = rgb4.r/2.0;
						Urgbg = rgb4.g/2.0;
						Urgbb = rgb4.b/2.0;
					}


					//printf("%.1f %.1f %.1f \t%.1f %.1f %.1f(%d %d %d)\n",Drgbr,Drgbg,Drgbb,Urgbr,Urgbg,Urgbb,rgb3.r,rgb3.g,rgb3.b);
				
					//エッジの判定
					//if((Drgbr+N2<rgb3.r)||(Drgbr-N2>rgb3.r)||(Drgbg+N2<rgb3.g)||(Drgbg-N2>rgb3.g)||(Drgbb+N2<rgb3.b)||(Drgbb-N2>rgb3.b)) break;
					if((Drgbr+Urgbr-rgb3.r)*(Drgbr+Urgbr-rgb3.r) + (Drgbg+Urgbg-rgb3.g)*(Drgbg+Urgbg-rgb3.g) + (Drgbb+Urgbb-rgb3.b)*(Drgbb+Urgbb-rgb3.b)>=(N2*N2)){
						break;
					}
					Bq+=q*q;
					Cqr+=rgb3.r;
					Dqr+=q*rgb3.r;
					Cqg+=rgb3.g;
					Dqg+=q*rgb3.g;
					Cqb+=rgb3.b;
					Dqb+=q*rgb3.b;
					Eq+=q;
					Drgbr=rgb3.r/2.0; Drgbg=rgb3.g/2.0; Drgbb=rgb3.b/2.0;
			}
			if(q==0){
				qNf=q;
			}
			else{
				qNf = q-1;
			}
			Drgbr = rgb.r/2;
			Drgbg = rgb.g/2;
			Drgbb = rgb.b/2;

			for ( t = -1; t >= -N; t-- ) {
					unsigned int i2, j2;
					i2 = i;
					j2 = j+t;
					if(j2<0) j2=0;
					if(j2>=width) j2 = width-1;
					RGB_UC rgb3( BmpIO_GetR( j2, i2, sBmp ), BmpIO_GetG( j2, i2, sBmp ), BmpIO_GetB( j2, i2, sBmp ) );
						Urgbr = Drgbr;
						Urgbg = Drgbg;
						Urgbb = Drgbb;
					if(j2>0 && j2<width-1){
						RGB_UC rgb4( BmpIO_GetR( j2-1, i2, sBmp ), BmpIO_GetG( j2-1, i2, sBmp ), BmpIO_GetB( j2-1, i2, sBmp ) );
						Urgbr = rgb4.r/2.0;
						Urgbg = rgb4.g/2.0;
						Urgbb = rgb4.b/2.0;
					}


					//printf("%.1f %.1f %.1f \t%.1f %.1f %.1f(%d %d %d)\n",Drgbr,Drgbg,Drgbb,Urgbr,Urgbg,Urgbb,rgb3.r,rgb3.g,rgb3.b);

					//エッジの判定
					//if((Drgbr+N2<rgb3.r)||(Drgbr-N2>rgb3.r)||(Drgbg+N2<rgb3.g)||(Drgbg-N2>rgb3.g)||(Drgbb+N2<rgb3.b)||(Drgbb-N2>rgb3.b)) break;
					if((Drgbr+Urgbr-rgb3.r)*(Drgbr+Urgbr-rgb3.r) + (Drgbg+Urgbg-rgb3.g)*(Drgbg+Urgbg-rgb3.g) + (Drgbb+Urgbb-rgb3.b)*(Drgbb+Urgbb-rgb3.b)>=(N2*N2)){
						break;
					}

					Bt+=t*t;
					Ctr+=rgb3.r;
					Dtr+=t*rgb3.r;
					Ctg+=rgb3.g;
					Dtg+=t*rgb3.g;
					Ctb+=rgb3.b;
					Dtb+=t*rgb3.b;
					Et+=t;
					Drgbr=rgb3.r/2.0; Drgbg=rgb3.g/2.0; Drgbb=rgb3.b/2.0;
			}
			tNb = abs(t)-1;
			Drgbr = rgb.r/2.0;
			Drgbg = rgb.g/2.0;
			Drgbb = rgb.b/2.0;

			for ( t = 0; t <= N; t++ ) {
					unsigned int i2, j2;
					i2 = i;
					j2 = j+t;
					if(j2<0) j2=0;
					if(j2>=width) j2 = width-1;
					RGB_UC rgb3( BmpIO_GetR( j2, i2, sBmp ), BmpIO_GetG( j2, i2, sBmp ), BmpIO_GetB( j2, i2, sBmp ) );
						Urgbr = Drgbr;
						Urgbg = Drgbg;
						Urgbb = Drgbb;
					if(j2>0 && j2<width-1){
						RGB_UC rgb4( BmpIO_GetR( j2+1, i2, sBmp ), BmpIO_GetG( j2+1, i2, sBmp ), BmpIO_GetB( j2+1, i2, sBmp ) );
						Urgbr = rgb4.r/2.0;
						Urgbg = rgb4.g/2.0;
						Urgbb = rgb4.b/2.0;
					}


					//printf("%.1f %.1f %.1f \t%.1f %.1f %.1f(%d %d %d)\n",Drgbr,Drgbg,Drgbb,Urgbr,Urgbg,Urgbb,rgb3.r,rgb3.g,rgb3.b);

					//エッジの判定
			//printf("1: %d %d  %d \n", i,j, (int)((Drgbr+Urgbr-rgb3.r)*(Drgbr+Urgbr-rgb3.r) + (Drgbg+Urgbg-rgb3.g)*(Drgbg+Urgbg-rgb3.g) + (Drgbb+Urgbb-rgb3.b)*(Drgbb+Urgbb-rgb3.b)));
					if((Drgbr+Urgbr-rgb3.r)*(Drgbr+Urgbr-rgb3.r) + (Drgbg+Urgbg-rgb3.g)*(Drgbg+Urgbg-rgb3.g) + (Drgbb+Urgbb-rgb3.b)*(Drgbb+Urgbb-rgb3.b)>=(N2*N2)){
						break;
					}

					Bt+=t*t;
					Ctr+=rgb3.r;
					Dtr+=t*rgb3.r;
					Ctg+=rgb3.g;
					Dtg+=t*rgb3.g;
					Ctb+=rgb3.b;
					Dtb+=t*rgb3.b;
					Et+=t;
					Drgbr=rgb3.r/2.0; Drgbg=rgb3.g/2.0; Drgbb=rgb3.b/2.0;
			}
			if(t==0){
				tNf=t;
			}
			else{
				tNf = t-1;
			}
			Aqr=(double)((qNb+qNf+1)*Dqr-Cqr*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq); //傾き
			Aqg=(double)((qNb+qNf+1)*Dqg-Cqg*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq);
			Aqb=(double)((qNb+qNf+1)*Dqb-Cqb*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq);
			Atr=(double)((tNb+tNf+1)*Dtr-Ctr*Et)/(double)((tNb+tNf+1)*Bt-Et*Et);
			Atg=(double)((tNb+tNf+1)*Dtg-Ctg*Et)/(double)((tNb+tNf+1)*Bt-Et*Et);
			Atb=(double)((tNb+tNf+1)*Dtb-Ctb*Et)/(double)((tNb+tNf+1)*Bt-Et*Et);
			//
			Bqr=(double)(Bq*Cqr-Dqr*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq);		     //切片
			Bqg=(double)(Bq*Cqg-Dqg*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq);
			Bqb=(double)(Bq*Cqb-Dqb*Eq)/(double)((qNb+qNf+1)*Bq-Eq*Eq);
			Btr=(double)(Bt*Cqr-Dtr*Et)/(double)((qNb+qNf+1)*Bt-Et*Et);
			Btg=(double)(Bt*Cqg-Dtg*Et)/(double)((qNb+qNf+1)*Bt-Et*Et);
			Btb=(double)(Bt*Cqb-Dtb*Et)/(double)((qNb+qNf+1)*Bt-Et*Et);

			RGB_UC rgb3;
			//縦マイナス方向の一番近い色を検索
			rgb3.r=(unsigned char)(Aqr * (-qNb) + Bqr); rgb3.g=(unsigned char)(Aqg * (-qNb) + Bqg); rgb3.b=(unsigned char)(Aqb * (-qNb) + Bqb);
			ikm = SearchColor( pIdxCol, ColorCnt, rgb3, &mapIndexCash );

			//縦プラス方向の一番近い色を検索
			rgb3.r=(unsigned char)(Aqr * (qNf) + Bqr); rgb3.g=(unsigned char)(Aqg * (qNf) + Bqg); rgb3.b=(unsigned char)(Aqb * (qNf) + Bqb);
			ikp = SearchColor( pIdxCol, ColorCnt, rgb3, &mapIndexCash );
			
			//横マイナス方向の一番近い色を検索
			rgb3.r=(unsigned char)(Atr * (-tNb) + Btr); rgb3.g=(unsigned char)(Atg * (-tNb) + Btg); rgb3.b=(unsigned char)(Atb * (-tNb) + Btb);
			jkm = SearchColor( pIdxCol, ColorCnt, rgb3, &mapIndexCash );
			
			//横プラス方向の一番近い色を検索
			rgb3.r=(unsigned char)(Atr * (tNf) + Btr); rgb3.g=(unsigned char)(Atg * (tNf) + Btg); rgb3.b=(unsigned char)(Atb * (tNf) + Btb);
			jkp = SearchColor( pIdxCol, ColorCnt, rgb3, &mapIndexCash );
			
			//上の6つが0に近い時閾値処理をする。それ以外はディザ法適用



			if(((ikm==ikp) && (jkm==jkp)) || !SAI_ON){			//四方の端がすべて同じ画素値であれば、ユークリッド距離による閾値処理を行う
				int k_th_tmp;
				int k_de_tmp;
//閾値法で画素を出してみる。
{
	wv = rgb.r;
	rgb2.r = wv;
	wv = rgb.g;
	rgb2.g = wv;
	wv = rgb.b;
	rgb2.b = wv;

	k_th_tmp = SearchColor( pIdxCol, ColorCnt, rgb2, &mapIndexCash );
}
//誤差拡散法で画素を出してみる。
{
	wv = rgb.r + pBuf[widx1][j].r;
	if ( wv > 255 ) rgb2.r = 255;
	else if ( wv < 0 ) rgb2.r = 0;
	else rgb2.r = wv;

	wv = rgb.g + pBuf[widx1][j].g;
	if ( wv > 255 ) rgb2.g = 255;
	else if ( wv < 0 ) rgb2.g = 0;
	else rgb2.g = wv;
			
	wv = rgb.b + pBuf[widx1][j].b;
	if ( wv > 255 ) rgb2.b = 255;
	else if ( wv < 0 ) rgb2.b = 0;
	else rgb2.b = wv;

	k_de_tmp = SearchColor( pIdxCol, ColorCnt, rgb2, &mapIndexCash );
}

				
				// 閾値法による結果と誤差拡散法による結果が異なるときにのみ、誤差の値を抽出する。
				if(k_th_tmp!=k_de_tmp)
				printf("%f \n", (float)(sqrt((double)(pBuf[widx1][j].r*pBuf[widx1][j].r)+(double)(pBuf[widx1][j].g*pBuf[widx1][j].g)+(double)(pBuf[widx1][j].b*pBuf[widx1][j].b))));
			//ユークリッド距離による閾値処理
			//sqrt(pBuf[widx1][j].r*pBuf[widx1][j].r+pBuf[widx1][j].g*pBuf[widx1][j].g+pBuf[widx1][j].b*pBuf[widx1][j].b)
				if((sqrt((double)(pBuf[widx1][j].r*pBuf[widx1][j].r)+(double)(pBuf[widx1][j].g*pBuf[widx1][j].g)+(double)(pBuf[widx1][j].b*pBuf[widx1][j].b))<D_euc))
				//&&(sqrt((double)(pBuf[widx1][j].r*pBuf[widx1][j].r)+(double)(pBuf[widx1][j].g*pBuf[widx1][j].g)+(double)(pBuf[widx1][j].b*pBuf[widx1][j].b))<10))
				{

					wv = rgb.r;
					rgb2.r = wv;
					wv = rgb.g;
					rgb2.g = wv;
					wv = rgb.b;
					rgb2.b = wv;
					

				}
				else{

					// 取得した色に、誤差の値を加算する。
					// (合計した結果、0を下回ったら0で打ち切る。255を超えたら255で打ち切る。)
					wv = rgb.r + pBuf[widx1][j].r;
					if ( wv > 255 )
						rgb2.r = 255;
					else if ( wv < 0 )
						rgb2.r = 0;
					else
						rgb2.r = wv;

					wv = rgb.g + pBuf[widx1][j].g;
					if ( wv > 255 )
						rgb2.g = 255;
					else if ( wv < 0 )
						rgb2.g = 0;
					else
						rgb2.g = wv;
			
					wv = rgb.b + pBuf[widx1][j].b;
					if ( wv > 255 )
						rgb2.b = 255;
					else if ( wv < 0 )
						rgb2.b = 0;
					else
						rgb2.b = wv;
				}
			}
			else{
					wv = rgb.r + pBuf[widx1][j].r;
					if ( wv > 255 )
						rgb2.r = 255;
					else if ( wv < 0 )
						rgb2.r = 0;
					else
						rgb2.r = wv;

					wv = rgb.g + pBuf[widx1][j].g;
					if ( wv > 255 )
						rgb2.g = 255;
					else if ( wv < 0 )
						rgb2.g = 0;
					else
						rgb2.g = wv;
			
					wv = rgb.b + pBuf[widx1][j].b;
					if ( wv > 255 )
						rgb2.b = 255;
					else if ( wv < 0 )
						rgb2.b = 0;
					else
						rgb2.b = wv;
					

			}
			//printf("x=%d, y=%d : %d %d %d %f \n", i, j, pBuf[widx1][j].r, pBuf[widx1][j].g, pBuf[widx1][j].b,
			//			(sqrt((double)(pBuf[widx1][j].r*pBuf[widx1][j].r)+(double)(pBuf[widx1][j].g*pBuf[widx1][j].g)+(double)(pBuf[widx1][j].b*pBuf[widx1][j].b))));

			// 一番近い色を検索する
			k = SearchColor( pIdxCol, ColorCnt, rgb2, &mapIndexCash );

			// 誤差をバッファに設定
			CRGB< int > drgb( (int)rgb.r - (int)pIdxCol[k].r, (int)rgb.g - (int)pIdxCol[k].g, (int)rgb.b - (int)pIdxCol[k].b );
			CRGB< int > drgb3 = drgb * 3;
			CRGB< int > drgb3_waru_8 = drgb3 / 8;	// 誤差の3/8を求める
			pBuf[widx1][ j + 1 ] += drgb3_waru_8;	// 右側には3/8
			pBuf[widx2][j] += drgb3_waru_8;		// 下側にには3/8
			pBuf[widx2][ j + 1 ] = drgb - ( drgb3_waru_8 * 2 );	// 右下には1/4(つまり、誤差の余りの分)
			pBuf[widx1][j] = CRGB< int >( 0, 0, 0 );	// 念のため
			

			// ピクセルに色を設定する
			BmpIO_SetPixcel( j, i, dBmp, k );
			
		}
	}


	//for(i=0;i<270;i++) printf("%d  %d \n", i, bunpu[i]);


}





//ガウシアンフィルタをかける変換
IBMP* Transgaus(const IBMP *pBmp, int BPP)
{
	IBMP *rBmp = NULL;
	map< RGB_UC, int > mapColor;

	unsigned int height;
	unsigned int width;

	double r[5][5];
	double g[5][5];
	double b[5][5];
	// イメージの幅と高さを取得する
	height = (unsigned int)BmpIO_GetHeight(pBmp);
	width = (unsigned int)BmpIO_GetWidth(pBmp);


	if (NULL == pBmp) return NULL;
//	if (BmpIO_GetBitPerPixcel(pBmp) == BPP)
//		return BmpIO_CopyBitmap(pBmp);

	// 出力用のイメージを構築
	rBmp = BmpIO_CreateBitmap(pBmp->width, pBmp->height, BPP);
	if (NULL == rBmp) return NULL;


	// 変換する
	{
		int i = 0;
		int j = 0;


		for (i = 0; i < height; i++) {
			for (j = 0; j < width; j++) {

				// 色を取得
				RGB_UC rgb(BmpIO_GetR(j, i, pBmp), BmpIO_GetG(j, i, pBmp), BmpIO_GetB(j, i, pBmp));

				//上のようにすると、rgb.rが(j ,i)の赤成分、rgb.gが緑成分、rgb.bが青成分になる。
				int dj, di;
				for (dj = 0; dj < 5; dj++) {
					for (di = 0; di < 5; di++) {
						if (j + dj < width && i + di < height) {
							(j + dj, i + di);
							r[dj][di] = rgb.r * 0.299;
							g[dj][di] = rgb.g * 0.587;
							b[dj][di] = rgb.b * 0.114;
						}
						else {
							r[dj][di] = 0.0;
							g[dj][di] = 0.0;
							b[dj][di] = 0.0;
						}
					}
				}
				double filterX[5][5] = {
					{ 1, 4, 6, 4, 1 },
					{ 4, 16, 24, 16, 4 },
					{ 6, 24, 36, 24, 6 },
					{ 4, 16, 24, 16, 4 },
					{ 1, 4, 6, 4, 1 }
				};

				double mult = 256;
				//double Lx = 0.0;

				//赤
				rgb.r = ((filterX[0][0] * r[0][0]) + (filterX[0][1] * r[0][1]) + (filterX[0][2] * r[0][2]) + (filterX[1][0] * r[1][0]) + (filterX[1][1] * r[1][1]) + (filterX[1][2] * r[1][2]) + (filterX[2][0] * r[2][0]) + (filterX[2][1] * r[2][1]) + (filterX[2][2] * r[2][2]) + (filterX[0][3] * r[0][3]) + (filterX[0][4] * r[0][4]) + (filterX[1][3] * r[1][3]) + (filterX[1][4] * r[1][4]) + (filterX[2][3] * r[2][3]) + (filterX[2][4] * r[2][4]) + (filterX[3][0] * r[3][0]) + (filterX[3][1] * r[3][1]) + (filterX[3][2] * r[3][2]) + (filterX[3][3] * r[3][3]) + (filterX[3][4] * r[3][4]) + (filterX[4][0] * r[4][0]) + (filterX[4][1] * r[4][1]) + (filterX[4][2] * r[4][2]) + (filterX[4][3] * r[4][3]) + (filterX[4][4] * r[4][4])) / mult;
				

				//緑
				rgb.g = ((filterX[0][0] * g[0][0]) + (filterX[0][1] * g[0][1]) + (filterX[0][2] * g[0][2]) + (filterX[1][0] * g[1][0]) + (filterX[1][1] * g[1][1]) + (filterX[1][2] * g[1][2]) + (filterX[2][0] * g[2][0]) + (filterX[2][1] * g[2][1]) + (filterX[2][2] * g[2][2]) + (filterX[0][3] * g[0][3]) + (filterX[0][4] * g[0][4]) + (filterX[1][3] * g[1][3]) + (filterX[1][4] * g[1][4]) + (filterX[2][3] * g[2][3]) + (filterX[2][4] * g[2][4]) + (filterX[3][0] * g[3][0]) + (filterX[3][1] * g[3][1]) + (filterX[3][2] * g[3][2]) + (filterX[3][3] * g[3][3]) + (filterX[3][4] * g[3][4]) + (filterX[4][0] * g[4][0]) + (filterX[4][1] * g[4][1]) + (filterX[4][2] * g[4][2]) + (filterX[4][3] * g[4][3]) + (filterX[4][4] * g[4][4])) / mult;
				

				//青
				rgb.b = ((filterX[0][0] * b[0][0]) + (filterX[0][1] * b[0][1]) + (filterX[0][2] * b[0][2]) + (filterX[1][0] * b[1][0]) + (filterX[1][1] * b[1][1]) + (filterX[1][2] * b[1][2]) + (filterX[2][0] * b[2][0]) + (filterX[2][1] * b[2][1]) + (filterX[2][2] * b[2][2]) + (filterX[0][3] * b[0][3]) + (filterX[0][4] * b[0][4]) + (filterX[1][3] * b[1][3]) + (filterX[1][4] * b[1][4]) + (filterX[2][3] * b[2][3]) + (filterX[2][4] * b[2][4]) + (filterX[3][0] * b[3][0]) + (filterX[3][1] * b[3][1]) + (filterX[3][2] * b[3][2]) + (filterX[3][3] * b[3][3]) + (filterX[3][4] * b[3][4]) + (filterX[4][0] * b[4][0]) + (filterX[4][1] * b[4][1]) + (filterX[4][2] * b[4][2]) + (filterX[4][3] * b[4][3]) + (filterX[4][4] * b[4][4])) / mult;
				//rgb.b = Lx;

				//rgb.r /= 2;
				//rgb.g /= 2;
				//rgb.b /= 2;
				double gaussX = (rgb.r + rgb.g + rgb.b);

				// ピクセルに色を設定する
				BmpIO_SetR(j, i, rBmp, gaussX);
				BmpIO_SetG(j, i, rBmp, gaussX);
				BmpIO_SetB(j, i, rBmp, gaussX);
			}
		}




	}

//	rBmp->width = width;
//	rBmp->height = height;
//	rBmp->BitPerPix = pBmp->BitPerPix;
//	rBmp->pColor = pBmp->pColor;
	//unsigned char *pPix;


	return rBmp;
}
長くなってしまって申し訳ないです。

asbel

Re: 減色処理のプログラムについて

#2

投稿記事 by asbel » 9年前

追加部分は124から139ですこちらの処理を施したものを143からの処理を行う画像に使いたいと思っています

あたりめ

Re: 減色処理のプログラムについて

#3

投稿記事 by あたりめ » 9年前

144行目の outbmp = TranseBmp(inbmp, BitPerPix);

outbmp = TranseBmp(gausbmp, BitPerPix);
に変えてもうまくいかないということですか?

asbel

Re: 減色処理のプログラムについて

#4

投稿記事 by asbel » 9年前

はい。そこを変えてもgausbmpの画像が出るだけになってしまいます。

asbel

Re: 減色処理のプログラムについて

#5

投稿記事 by asbel » 9年前

どなたかわかりませんか…?

閉鎖

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