| マトリクスサイズ | bluenoiseex()が発生する値の範囲 | ファイルサイズ | bluenoise()が発生する値の範囲 |
|---|---|---|---|
| 256×256 | 0~0x0000ffff(0~ 65,535) | 埋め込みデータなのでファイルなし | 0~0x00007fff(0~32767) |
| 512×512 | 0~0x0003ffff(0~ 262,143) | 1メガバイト | 0~0x00007fff(0~32767) |
| 1024×1024 | 0~0x000fffff(0~ 1,048,575) 百万。乱数系列の代用には十分 | 4メガバイト | 0~0x00007fff(0~32767) |
| 2048×2048 | 0~0x003fffff(0~ 4,194,303) | 16メガバイト | 0~0x00007fff(0~32767) |
| 4096×4096 | 0~0x00ffffff(0~ 16,777,215) 24bitカラー画像の色数 | 64メガバイト | 0~0x00007fff(0~32767) |
| 8192×8192 | 0~0x03ffffff(0~ 67,108,863) 印刷幅8メートルの特殊なプリンタ(国宝のアーカイブ作成用)で唯一の利用実績 | 256メガバイト | 0~0x00007fff(0~32767) |
| 16384×16384 | 0~0x0fffffff(0~268,435,455) この精度を使っている例はゼロ(CYMK用の8192×8192マトリクス4枚に分割などが考えられる) | 1024メガバイト(1ギガバイト) | 0~0x00007fff(0~32767) |
/////////////////////////////// // ブルーノイズ系列のシード設定 // int seed; seed値 // 返り値 // 負....エラー(INITIALIZE_ERROR...初期化エラー(クラスのインスタンス生成に失敗:メモリ不足)) typedef int (__stdcall* SBLUENOISE)(int seed); extern SBLUENOISE sbluenoise; ///////////////////////// // ブルーノイズ系列の取得(0~RAND_MAX) // RAND_MAXは0x7fff(32767)なので粗い // 返り値 // 負....エラー(INITIALIZE_ERROR...初期化エラー(クラスのインスタンス生成に失敗:メモリ不足)) // ブルーノイズ系列 typedef int (__stdcall* BLUENOISE)(); extern BLUENOISE bluenoise; ///////////////////////// // 精細なブルーノイズ系列の取得(0~size*size) // ファイルを使わないサイズ(256*256)でも0~65535と細かい // 256* 256 0~0x0000ffff(0~ 65,536-1) ファイルを使わない // 512* 512 0~0x0003ffff(0~ 262,144-1) 1Mバイト // 1024* 1024 0~0x000fffff(0~ 1,048,576-1) 4Mバイト // 2048* 2048 0~0x003fffff(0~ 4,194,304-1) 16Mバイト // 4096* 4096 0~0x00ffffff(0~ 16,777,216-1) 64Mバイト // 8192* 8192 0~0x03ffffff(0~ 67,108,864-1) 256Mバイト // 16384*16384 0~0x0fffffff(0~268,435,456-1) 1024Mバイト(1Gバイト) // 返り値 // 負....エラー(INITIALIZE_ERROR...初期化エラー(クラスのインスタンス生成に失敗:メモリ不足)) // ブルーノイズ系列 typedef int (__stdcall* BLUENOISEEX)(); extern BLUENOISEEX bluenoiseex; ///////////////////////// // ブルーノイズ マトリクス保存・読込フォルダの設定、マトリクスサイズの設定 // 通常(0~RAND_MAX)の範囲のブルーノイズの生成では設定しない // bluenoiseex()で精細なブルーノイズを取得する目的がある場合に設定する // 入力 // const char* pfolder; マトリクスファイルの存在する/を生成するフォルダ名 // NULLあるいは""を指す場合は256×256サイズの組み込みマトリクスを利用する // int size; マトリクスサイズ(512/1024/2048/4096/8192/16384) // 1024の場合、1024×1024のブルーノイズマトリクスを生成する。ファイルサイズは4メガバイト // 返り値 // 負....エラー(INITIALIZE_ERROR...初期化エラー(クラスのインスタンス生成に失敗:メモリ不足)) // 負....エラー(FILE_OPEN_ERROR....保存できない、読み込みできない) // (MEMORY_SHORTAGE....メモリ不足) // 指定したフォルダのsizexsizeraw.datというファイルを読み込む // sizeが1024の場合は1024x1024raw.datというファイル名になる // ファイルが無い場合はファイルを作成する // sizeが大きくなるほど高品質のbluenoiseを生成する typedef int (__stdcall* SETBLUENOISEMATRIX)(const char* pfolder,int size); extern SETBLUENOISEMATRIX setbluenoisematrix;DLLのロードと解放は以下の通り
#include "bluenoisecallback.h"
HINSTANCE bn_dllinstance; // dllインスタンス
// DLL エントリーポイント
SBLUENOISE sbluenoise;
BLUENOISE bluenoise;
BLUENOISEEX bluenoiseex;
SETBLUENOISEMATRIX setbluenoisematrix;
ORDEREDDITHER2 ordereddither2;
ORDEREDDITHER4 ordereddither4;
ORDEREDDITHERLINE2 orderedditherline2;
ORDEREDDITHERLINE4 orderedditherline4;
{
// ....
// ロード
// gmodulepathには、実行ファイルのパスが入っている。
// 実行ファイルのパスに"bluenoisedll.dll"が入っているとする
char filename[FILENAME_MAX];
sprintf(filename,"%sbluenoisedll.dll",gmodulepath);
bn_dllinstance = LoadLibrary(filename);
if(bn_dllinstance == NULL) {
char buffer[512];
sprintf(buffer,"DLLファイル bluenoisedll.dll のロードに失敗しました");
AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION);
return(2);
}
sbluenoise = (SBLUENOISE)GetProcAddress(bn_dllinstance,"sbluenoise");
bluenoise = (BLUENOISE)GetProcAddress(bn_dllinstance,"bluenoise");
bluenoiseex = (BLUENOISEEX)GetProcAddress(bn_dllinstance,"bluenoiseex");
setbluenoisematrix = (SETBLUENOISEMATRIX)GetProcAddress(bn_dllinstance,"setbluenoisematrix");
if(sbluenoise == NULL || bluenoise == NULL || bluenoiseex == NULL || setbluenoisematrix == NULL) {
char buffer[512];
sprintf(buffer,"DLLファイル bluenoisedll.dll(or bluenoiseutf8dll) のバージョンが異なります");
AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION);
FreeLibrary(bn_dllinstance);
return(2);
}
ordereddither2 = (ORDEREDDITHER2)GetProcAddress(bn_dllinstance,"ordereddither2");
ordereddither4 = (ORDEREDDITHER2)GetProcAddress(bn_dllinstance,"ordereddither4");
orderedditherline2 = (ORDEREDDITHERLINE2)GetProcAddress(bn_dllinstance,"orderedditherline2");
orderedditherline4 = (ORDEREDDITHERLINE4)GetProcAddress(bn_dllinstance,"orderedditherline4");
if(ordereddither2 == NULL || ordereddither4 == NULL || orderedditherline2 == NULL || orderedditherline4 == NULL) {
char buffer[512];
sprintf(buffer,"DLLファイル bluenoisedll.dll(or bluenoiseutf8dll) のバージョンが異なります\n");
AfxMessageBox(buffer,MB_OK | MB_ICONEXCLAMATION);
FreeLibrary(bn_dllinstance);
return(2);
}
// ....
// 解放
FreeLibrary(bn_dllinstance);
}
// m_editresultにbluenoise系列を1000個設定してエディットボックス等に表示する
void CDlgBluenoise::OnBnClickedMakebluenoise100()
{
m_editresult = "";
char buffer[1024];
for(int i = 0 ; i < 1000 ; i++) {
if(i % 10 == 0) {
sprintf(buffer,"(%03d)",i / 10);
m_editresult += buffer;
}
if(i % 10 == 9) {
sprintf(buffer,"%10d\r\n",bluenoise());
}
else {
sprintf(buffer,"%10d, ",bluenoise());
}
m_editresult += buffer;
}
UpdateData(FALSE);
}
新規のマトリクス(通常は、初期サイズである256×256よりも大きいサイズ)setbluenoisematrix()の呼び出しは以下の通り行う。// 下記サンプルプログラムにおけるフォルダは"g:/tmp/"であるが、通常は他のフォルダを設定する。
// m_editsizeには512~16384の範囲の値が入る void CDlgBluenoise::OnBnClickedSetsize() { UpdateData(TRUE); if(m_editsize == 256) { setbluenoisematrix("",m_editsize); } else { setbluenoisematrix("g:\\tmp\\",m_editsize); } UpdateData(FALSE); }
// 1...ordered dither utility // do ordered dither (for grayscale image only) // for multiplane image(ex. RGB,CMYK), use class library or add API to this library. // input // int width; image width(pixel) // int height; image height(pixel) // int scanlinesize1; scanline size(byte count) of one line image // unsigned char* pdata1; 256 level image // int scanlinesize2; scanline size(byte count) of 2 or 4 level image // output // unsigned char* pdata2; 2 or 4 level image(one pixel is one byte) // 2 level has value(0,255) // 4 level has value(0,85,170,255) // return value // 0>...error(INITIALIZE_ERROR...initialize error(can not make instance of class library : memory shortage) // error(FILE_OPEN_ERROR....can not save or load bluenoise matrix data) // (MEMORY_SHORTAGE..memory shortage) // this library read "sizexsizeraw.dat" in folder specified by setbluenoisematrix() // If "size" is 1024, file name is "1024x1024raw.dat" // If "sizexsizeraw.dat" does not exist, setbluenoisematrix() API genarates the file automatically. // If value of "size" becomes bigger, quality of dithering image becomes higher. typedef int (__stdcall* ORDEREDDITHER2)(int width,int height,int scanlinesize1,unsigned char* pdata1,int scanlinesize2,unsigned char* pdata2); extern ORDEREDDITHER2 ordereddither2; typedef int (__stdcall* ORDEREDDITHER4)(int width,int height,int scanlinesize1,unsigned char* pdata1,int scanlinesize2,unsigned char* pdata2); extern ORDEREDDITHER4 ordereddither4; // ordered dither utility // line by line process // INPUT // int y; line no(0,...height - 1) typedef int (__stdcall* ORDEREDDITHERLINE2)(int width,int y,unsigned char* pdata1,unsigned char* pdata2); extern ORDEREDDITHERLINE2 orderedditherline2; typedef int (__stdcall* ORDEREDDITHERLINE4)(int width,int y,unsigned char* pdata1,unsigned char* pdata2); #extern ORDEREDDITHERLINE4 orderedditherline4;
// 1...組織的ディザリングユーティリティ // グレイスケールイメージに対する組織的ディザリングを実行する // マルチプレーン画像(ex. RGB,CMYK)を対象とした組織的ディザリングは、C++クラスライブラリでサポートしている。 // マルチプレーン画像に対しては、クラスライブラリを使うか、本ライブラリのAPIを拡張する必要がある。 // 入力 // int width; 画像の幅(pixel) // int height; 画像の高さ(pixel) // int scanlinesize1; pdata1のスキャンラインサイズ(byte) 一行の画像のバイト数 // unsigned char* pdata1; 256階調画像(1ピクセル1バイト) // int scanlinesize2; pdata2のスキャンラインサイズ(byte) 一行の画像のバイト数 // output // unsigned char* pdata2; 2 あるいは 4 階調画像(1ピクセル1バイト) // 2 階調の場合は(0/255の2値) // 4 階調の場合は(0/85/170/255の4値) // return value // 負値...エラー(myerrcode.h : INITIALIZE_ERROR...初期化エラー(クラスライブラリのインスタンス作成失敗 : 主にメモリ不足が原因) // エラー(myerrcode.h : FILE_OPEN_ERROR....ブルーノイズデータの保存、読込失敗(生成したブルーノイズ数列を書き込めない、読み込めない) // (myerrcode.h : MEMORY_SHORTAGE....メモリ不足) // 本ライブラリは、setbluenoisematrix()APIで指定したフォルダに"sizexsizeraw.dat"というファイル名でファイルを保存/読込する。 // たとえば"size"が1024の場合、ファイル名は"1024x1024raw.dat" // ファイルが無い場合、setbluenoisematrix()内部で自動的にブルーノイズを作成して"sizexsizeraw.dat"というファイル名で保存する // "size"の値が大きいほど、ディザリングの画質は良くなる typedef int (__stdcall* ORDEREDDITHER2)(int width,int height,int scanlinesize1,unsigned char* pdata1,int scanlinesize2,unsigned char* pdata2); extern ORDEREDDITHER2 ordereddither2; typedef int (__stdcall* ORDEREDDITHER4)(int width,int height,int scanlinesize1,unsigned char* pdata1,int scanlinesize2,unsigned char* pdata2); extern ORDEREDDITHER4 ordereddither4; // 組織的ディザリング // 1行単位でディザリング(プリンタドライバ中で1行ずつディザリングするなど) // 入力 // int y; 行番号(0~height - 1) typedef int (__stdcall* ORDEREDDITHERLINE2)(int width,int y,unsigned char* pdata1,unsigned char* pdata2); extern ORDEREDDITHERLINE2 orderedditherline2; typedef int (__stdcall* ORDEREDDITHERLINE4)(int width,int y,unsigned char* pdata1,unsigned char* pdata2); #extern ORDEREDDITHERLINE4 orderedditherline4;
int width = mppimage[0]->mgetrawwidth(); // 元の256階調グレイスケールイメージの幅(ピクセル)
int height = mppimage[0]->mgetrawheight(); // 元の256階調グレイスケールイメージの高さ(ピクセル)
int scanlinesize = mppimage[0]->mgetrawscanlinesize(); // 元の256階調グレイスケールイメージのスキャンラインサイズ(バイト)
unsigned char* pdata1 = mppimage[0]->mgetrawdata(); // 元の256階調グレイスケールイメージ(scanlinesize * heightバイト)
unsigned char* pdata2 = (unsigned char*)malloc(scanlinesize * height); // 2/4階調ディザリンググレイスケールイメージ(scanlinesize * heightバイト)
// 2階調の場合、輝度値は0/255
// 4階調の場合、輝度値は0/85/170/255
if(pdata2 != NULL) {
ordereddither2(0,width,height,scanlinesize,pdata1,scanlinesize,pdata2);
free(pdata2);
}
ライン処理のサンプルプログラム
int width = mppimage[0]->mgetrawwidth(); // 元の256階調グレイスケールイメージの幅(ピクセル)
int height = mppimage[0]->mgetrawheight(); // 元の256階調グレイスケールイメージの高さ(ピクセル)
int scanlinesize = mppimage[0]->mgetrawscanlinesize(); // 元の256階調グレイスケールイメージのスキャンラインサイズ(バイト)
unsigned char* pdata1 = mppimage[0]->mgetrawdata(); // 元の256階調グレイスケールイメージ(scanlinesize * heightバイト)
unsigned char* pdata2 = (unsigned char*)malloc(scanlinesize * height); // 2/4階調ディザリンググレイスケールイメージ(scanlinesize * heightバイト)
// 2階調の場合、輝度値は0/255
// 4階調の場合、輝度値は0/85/170/255
if(pdata2 != NULL) {
for(int i = 0 ; i < height ; i++) {
unsigned char* ps1 = pdata1 + i * scanlinesize;
unsigned char* ps2 = pdata2 + i * scanlinesize;
orderedditherline4(0,width,i,ps1,ps2);
}
free(pdata2);
}