#ifndef __JBXL_CPP_GRAPHIC_DATA_H_ #define __JBXL_CPP_GRAPHIC_DATA_H_ /** グラフィックデータ定義用ヘッダ 依存関係 */ #include "common++.h" #include "tools.h" #include "gheader.h" #include "Vector.h" #include "ClassBox.h" // namespace jbxl { extern int ZeroBase; extern int TempBase; /////////////////////////////////////////////////////////////////////////////////////// // // void free_CmnHead(CmnHead* hd); // 共通ヘッダのメモリ領域を開放する void init_CmnHead(CmnHead* hd); #define freeCmnHead free_CmnHead #define initCmnHead init_CmnHead CmnHead getinfo_CmnHead(CmnHead hd); // ヘッダ情報のみをコピーする // 共通ヘッダCmnHeadから座標を指定して,画像データを取り出す inline uByte& CmnHeadBytePoint(CmnHead hd, int i=0, int j=0, int k=0) { return hd.grptr[(int)i + (int)j*hd.xsize + (int)k*hd.xsize*hd.ysize]; } //template MSGraph copyCmnHead2MSGraph(CmnHead hd, unsigned int mode=CH2MG_NORMAL); //template CmnHead copyMSGraph2CmnHead(MSGraph mgr, unsigned int mode=MG2CH_NORMAL); //////////////////////////////////////////////////////////////////////////////////////////// /** グラフィックデータの構造 (C++) メモリ内での形式. グラフィックデータはファイルから読み込まれた後,メモリ内で, MSGraph<>型のデータ となる.ただし,ヘッダを解析できない場合や,他のインターフェイスにデータを渡す場合は, Common Head 形式に変換される場合もある. ファイル中での形式. ファイルとして扱うことのできるデータは,基本的に Common Head 形式である. ただし,いくつかの形式(Gio.h 参照)は直接読み出すことができる. */ template class MSGraph; template class ExMSGraph; /** template class MSGraph シンプルグラフィックデータ. メモリ中での画像データのデフォルト.ディストラクタはメモリを解放しないので,必ず手動で解放すること. int xs : xサイズ. 4Byte. int ys : yサイズ. 4Byte. int zs : zサイズ. 4Byte. 2Dの場合は 1. T* gp : グラフィックデータへのポインタ. T zero : 画素値のゼロ位. T base : 画措置の底上げの値. 以下は必要に応じて設定. T max : 画素値の最大値 T min : 画素値の最小値 int color : データのカラータイプ int state : エラー制御 T rbound : 画像の境界情報 double RZxy : Z軸の歪.Z軸の間隔を1とした XY軸の間隔.(X or Y)/Z double norm : 規格化定数.フィルタのとき等に使用. */ template class MSGraph { public: int xs; int ys; int zs; T* gp; T zero; // ゼロ位 T base; // ベース public: T max; T min; int color; // データタイプ int state; RBound rbound; double RZxy; // Z軸の歪.Z軸の間隔を1とした XY軸の間隔.(X or Y)/Z double norm; // 規格化定数.フィルタのとき等に使用. public: /* wRateX: ワールド座標系の x成分1ドットに対するスクリーン座標系のドット数. wRateY: ワールド座標系の y成分1ドットに対するスクリーン座標系のドット数. wZeroX: スクリーン座標系の原点に対するワールド座標系の x成分. wZeroY: スクリーン座標系の原点に対するワールド座標系の y成分. wNowX : ペンの現地点の x成分(ワールド座標系) wNowY : ペンの現地点の y成分(ワールド座標系) */ double wRateX; double wRateY; double wZeroX; double wZeroY; double wNowX; double wNowY; // public: MSGraph(int x, int y=1, int z=1, T v=(T)0, T b=(T)0, double rz=1.0f) { set(x, y, z, v, b, rz);} MSGraph(RBound rb, T v=(T)0, T b=(T)0, double rz=1.0f) { set(rb, v, b, rz);} MSGraph(void) { init();} ~MSGraph(void) {} T& point(int x, int y=0, int z=0) { return gp[x+xs*y+xs*ys*z];} // 座標(x,y,z)の画素値の参照 T get_vPoint(double x, double y=0., double z=0., int mode=OFF); void set_vPoint(double x, double y=0., double z=0., T cc=(T)0, int mode=OFF); void put_vPoint(double x, double y=0., double z=0., T cc=(T)0, int mode=OFF); void set(RBound rb, T v=(T)0, T b=(T)0, double rz=1.0f); void set(int x, int y=1, int z=1, T v=(T)0, T b=(T)0, double rz=1.0f); void init(void); // グラフィックデータは解放しない bool isNull(void); // グラフィックデータを持っていないか? void fill(T v=(T)0); // 全空間を画素値 v にする void clear(T v); // 全空間を画素値 v にする void clear(void); // 全空間を画素値 zero にする void getm(int x, int y=1, int z=1, T v=(T)0); // グラフィックメモリを獲得する void free(void); // グラフィックデータを開放する void get_minmax(void); // min, max を獲得 void set_array(T* ary, int sz=0); // ary の内容を gpにコピー. template void mimicry(MSGraph s) { set(s.xs, s.ys, s.zs, (T)s.zero, (T)s.base, s.RZxy); rbound = s.rbound; color = s.color; state = s.state; max = s.zero; min = s.zero; norm = s.norm; }; // for viewport void setWindow(double x1, double y1, double x2, double y2); void wMove(double x, double y) {wNowX=x; wNowY=y;} void wMove_rel(double x, double y) {wNowX+=x; wNowY+=y;} MSGraph operator= (ExMSGraph& s); }; /** メンバ変数を初期化する.画像データの開放は行わない */ template void MSGraph::init(void) { xs = ys = zs = 0; gp = NULL; RZxy = 1.0; zero = (T)0; base = (T)0; min = (T)0; max = (T)0; norm = 1.0; color = GRAPH_COLOR_MONO; state = STATE_GRAPH_NOERR; rbound.init(); wRateX = wRateY = 1.0; wZeroX = wZeroY = 1.0; wNowX = wNowY = 0.0; return; } /** グラフィックデータを持いないか? */ template bool MSGraph::isNull() { if (gp==NULL) return true; #ifdef WIN32 if (gp==(T*)WIN32_NULL) return true; #endif return false; } // template void MSGraph::set(RBound rb, T v, T b, double rz) { set(rb.xmax-rb.xmin+1, rb.ymax-rb.ymin+1, rb.zmax-rb.zmin+1, v, b, rz); rbound = rb; return; } // template void MSGraph::set(int x, int y, int z, T v, T b, double rz) { if (z<=0) z = 1; getm(x, y, z, v); if (gp==NULL) return; base = b; if (rz<=0.0) RZxy = 1.0; else RZxy = rz; rbound.set(0, x-1, 0, y-1, 0, z-1); color = GRAPH_COLOR_MONO; norm = 1.0; state = STATE_GRAPH_NOERR; return; } /** template MSGraph::getm(int x, int y, int z, T v) 機能: typename T 型単純グラフィックデータ(MSGraph)のメモリ領域を確保する. グラフィックデータ部分は v (デフォルトは0)で初期化される. 引数: x -- 確保するグラフィックデータの x方向のサイズ. y -- 確保するグラフィックデータの y方向のサイズ. z -- 確保するグラフィックデータの z方向のサイズ. v -- グラフィックデータ部分の初期化値(デフォルトは0) 戻り値:なし. メモリ領域を獲得できなかった場合,メモリ領域へのポインタは NULLとなる. */ template void MSGraph::getm(int x, int y, int z, T v) { xs = x; ys = y; zs = z; gp = NULL; zero = max = min = v; if (xs>0 && ys>0 && zs>0) { gp = (T*)malloc(xs*ys*zs*sizeof(T)); if (gp==NULL) { init(); state = ERROR_GRAPH_MEMORY; return; } for (int i=0; i void MSGraph::get_minmax(void) { int i; min = max = gp[0]; for (i=1; i void MSGraph::set_array(T* ary, int sz) { int size = xs*ys*zs; if (sz>0) size = Min(size, sz); for (int i=0; i void MSGraph::fill(T v) { for (int i=0; i void MSGraph::clear(T v) { for (int i=0; i void MSGraph::clear(void) { for (int i=0; i void MSGraph::free(void) { if (gp!=NULL) ::free(gp); init(); return; } /** template T MSGraph::get_vPoint(double x, double y, double z, int mode); 機能: グラフィックデータ構造体 vpの任意の 1voxelの値(濃度)を返す. 座標の範囲チェックあり.Z軸の歪,境界補整あり. 引数: x, y, z -- 値を設定する xyz座標. mode -- モード:OFFなら最も近い点の濃度を返す.それ以外なら周囲の平均. 戻り値: (x,y,z)点の濃度(輝度値).(x,y,z)が座標の範囲外の場合は zeroを返す. */ template T MSGraph::get_vPoint(double x, double y, double z, int mode) { int ix, iy, iz; int xx, yy, zz; T ret; ret = zero; z = z*RZxy; if (mode==OFF) { ix = (int)(x+0.5) - rbound.xmin; iy = (int)(y+0.5) - rbound.ymin; iz = (int)(z+0.5) - rbound.zmin; if (ix>=0 && ix=0 && iy=0 && iz=0 && ix=0 && iy=0 && iz void MSGraph::set_vPoint(double x, double y, double z, T cc, int mode) 機能: グラフィックデータ構造体 gdの任意の 1voxelに値を設定する. 座標の範囲チェックあり.Z軸の歪,境界補整あり. 引数:x, y, z -- 値を設定する xyz座標. cc -- 点(x,y,z)に設定する点の値(濃度). mode -- OFFの場合、 (x,y,z)に一番近い点に ccを設定する.   ON の場合、(x,y,z)の周りの格子点全てに ccを設定する. */ template void MSGraph::set_vPoint(double x, double y, double z, T cc, int mode) { int ix, iy, iz; int xx, yy, zz; z = z*RZxy; if (mode==OFF) { ix = (int)(x+0.5) - rbound.xmin; iy = (int)(y+0.5) - rbound.ymin; iz = (int)(z+0.5) - rbound.zmin; if (ix>=0 && ix=0 && iy=0 && iz=0 && ix=0 && iy=0 && iz void MSGraph::put_vPoint(double x, double y, double z, T cc, int mode) 機能: グラフィックデータ構造体 gdの任意の 1voxelに値を設定する. 座標の範囲チェックあり.Z軸の歪,境界補整あり. ただし,set_vPoint()は強制的に値を設定するが,put_vPoint()は既に 値が設定されている場合(zeroでない場合)は,指定された値を設定しない. 引数:x, y, z -- 値を設定する xyz座標. cc -- 点(x,y,z)に設定する点の値(濃度). mode -- OFFの場合、 (x,y,z)に一番近い点に ccを設定する.   ON の場合、(x,y,z)の周りの格子点全てに ccを設定する. */ template void MSGraph::put_vPoint(double x, double y, double z, T cc, int mode) { int ix, iy, iz; int xx, yy, zz; z = z*RZxy; if (mode==OFF) { ix = (int)(x+0.5) - rbound.xmin; iy = (int)(y+0.5) - rbound.ymin; iz = (int)(z+0.5) - rbound.zmin; if (ix>=0 && ix=0 && iy=0 && iz=0 && ix=0 && iy=0 && iz void MSGraph::setWindow(double x1, double y1, double x2, double y2) { if (x1==x2 || y1==y2) return; wRateX = (double)xs/Xabs(x2-x1); wRateY = (double)ys/Xabs(y2-y1); wZeroX = Min(x1, x2); wZeroY = Max(y1, y2); } // // オペレータ // template MSGraph MSGraph::operator= (ExMSGraph& s) { xs = s.xs; ys = s.ys; zs = s.zs; gp = s.gp; zero = s.zero; base = s.base; max = s.max; min = s.min; rbound = s.rbound; RZxy = s.RZxy; norm = s.norm; color = s.color; state = s.state; wRateX = s.wRateX; wRateY = s.wRateY; wZeroX = s.wZeroX; wZeroY = s.wZeroY; wNowX = s.wNowX; wNowY = s.wNowY; return *this; } //////////////////////////////////////////////////////////////////////////////////////////// // 簡易表示インターフェイス // template class MSGraphDisp : public CVDisplay { public: public: MSGraphDisp() {} ~MSGraphDisp() {} virtual void displayNew (MSGraph vp) {} virtual void displayNext(MSGraph vp) {} }; //////////////////////////////////////////////////////////////////////////////////////////////// // データ変換 // // ビット和を執れるように設定する. #define CH2MG_NORMAL 0 // ノーマルコピー #define CH2MG_NOPARM 1 // パラメータ処理(Z軸の歪, rboundの処理)をしない. #define MG2CH_NORMAL 0 // ノーマルコピー #define MG2CH_NOPARM 1 // パラメータ処理(Z軸の歪, rboundの処理)をしない. #define MG2CH_CONTRAST 2 // コントラスト調整を行う #define MG2CH_OCTET 4 // 8bitへ変換 //template MSGraph copyCmnHead2MSGraph(CmnHead hd, unsigned int mode=CH2MG_NORMAL); //template CmnHead copyMSGraph2CmnHead(MSGraph mgr, unsigned int mode=MG2CH_NORMAL); /** template MSGraph copyCmnHead2MSGraph(CmnHead hd, unsigned int mode=CH2MG_NORMAL, bool cnt=false) CmnHead から MSGraphのデータを作り出す. MSGraph.gp のメモリ領域は別に作られる. グローバルカウンタが使用可能. 引数: mode CH2MG_NORMAL 0 // ノーマルコピー(デフォルト) CH2MG_NORZXY 1 // Z軸の歪を処理しない. cnt カウンタを使用するか(デフォルト:使用しない false) エラー:state ERROR_GRAPH_HEADER: ヘッダエラー ERROR_GRAPH_MEMORY: メモリ確保エラー ERROR_GRAPH_CANCEL: 中断 */ template MSGraph copyCmnHead2MSGraph(CmnHead hd, unsigned int mode=CH2MG_NORMAL, bool cnt=false) { MSGraph vp; int kind = hd.kind & 0x00ff; vp.init(); // vp.color = GRAPH_COLOR_MONO; if (kind==UN_KNOWN_DATA || hd.kind==HEADER_ERROR) { vp.state = ERROR_GRAPH_HEADER; return vp; } vp.set(hd.xsize, hd.ysize, hd.zsize); if (vp.gp==NULL) { vp.state = ERROR_GRAPH_MEMORY; return vp;} // カラータイプ if (kind==JPEG_RGB_DATA || kind==JPEG_MONO_DATA) { if (hd.zsize==3) vp.color = GRAPH_COLOR_RGB; } else if (hd.depth==16) { vp.color = GRAPH_COLOR_MONO16; } // カウンタ.ここでは,delete禁止 CVCounter* counter = NULL; if (vp.zs>=10 && cnt) { counter = GetUsableGlobalCounter(); if (counter!=NULL) counter->SetMax(vp.zs/10); } int ks, js, ln; ln = vp.xs*vp.ys; if (hd.depth==16){ sWord* bp = (sWord*)hd.grptr; vp.max = vp.min = bp[0]; for (int k=0; kStepIt(); if (counter->isCanceled()) { // キャンセル vp.free(); vp.state = ERROR_GRAPH_CANCEL; return vp; } } } } else if (hd.depth<16){ // ==8 //int uint = (unsigned char)hd.grptr[0]; vp.max = vp.min = (T)((unsigned char)hd.grptr[0]); for (int k=0; kStepIt(); if (counter->isCanceled()) { // キャンセル vp.free(); vp.state = ERROR_GRAPH_CANCEL; return vp; } } } } else { vp.max = vp.min = (T)((uByte)hd.grptr[0]>>(hd.depth-15)); for (int k=0; k>(hd.depth-15)); vp.max = Max(vp.max, vp.gp[js]); vp.min = Min(vp.min, vp.gp[js]); } if (counter!=NULL && k%10==0) { counter->StepIt(); if (counter->isCanceled()) { // キャンセル vp.free(); vp.state = ERROR_GRAPH_CANCEL; return vp; } } } } // もし存在するなら,ヘッダ部分から Z方向の歪率, rboundを取り出す. if (!checkBit(mode, CH2MG_NOPARM)) { if (hd.bsize>0 && (kind==CT_DATA || kind==CT_3DM || kind==CT_3D_VOL)) { sWord* rz = (sWord*)hd.buf; if (rz[9]==RZXY_RATE || checkBit(hd.kind, HAS_RZXY)) { double rzm = (double)(rz[8])/rz[9]; if (rzm<5.0 && rzm>0.) vp.RZxy = rzm; } if (rz[10]!=0 && checkBit(hd.kind, HAS_BASE)) { vp.base = (T)rz[10]; } if (checkBit(hd.kind, HAS_RBOUND)) { vp.rbound.xmin = rz[6]; vp.rbound.xmax = rz[7]; vp.rbound.ymin = rz[4]; vp.rbound.ymax = rz[5]; vp.rbound.zmin = rz[2]; vp.rbound.zmax = rz[3]; } } } if (counter!=NULL) counter->PutFill(); return vp; } /** template CmnHead copyMSGraph2CmnHead(MSGraph& vp, unsigned int mode=MG2CH_NORMAL, bool cnt=false) MSGraph から CmnHeadのデータを作り出す. CmnHead.grptr のメモリ領域は別に作られる. vpに関しては vp.max, vp.minが設定される. グローバルカウンタが使用可能. 引数: mode MG2CH_NORMAL 0 // ノーマルコピー(デフォルト) MG2CH_NORZXY 1 // Z軸の歪を処理しない. MG2CH_CONTRAST 2 // コントラスト調整 MG2CH_OCTET 4 // 8bitへ変換 cnt カウンタを使用するか(デフォルト:使用しない false) エラー: cmnHead.kind HEADER_ERROR cmnHead.xsize ERROR_GRAPH_HEADER: ヘッダエラー ERROR_GRAPH_MEMORY: メモリ確保エラー ERROR_GRAPH_CANCEL: 中断 */ template CmnHead copyMSGraph2CmnHead(MSGraph& vp, unsigned int mode=MG2CH_NORMAL, bool cnt=false) { CmnHead hd; CTHead ct; memset(&ct, 0, sizeof(CTHead)); memset(&hd, 0, sizeof(CmnHead)); if (vp.gp==NULL) { hd.xsize = ERROR_GRAPH_HEADER; hd.kind = HEADER_ERROR; return hd; } // hd.kind = 0; // MSGraphからのコピー時には,ヘッダ情報は既に消失している. hd.xsize = ct.xsize = ct.cutright= vp.xs; hd.ysize = ct.ysize = ct.cutdown = vp.ys; hd.zsize = vp.zs; if (checkBit(mode, MG2CH_OCTET)) hd.depth = 8; else hd.depth = sizeof(T)*8; hd.lsize = hd.xsize*hd.ysize*hd.zsize*(hd.depth/8); hd.bsize = sizeof(CTHead); hd.grptr = (uByte*)malloc(hd.lsize*sizeof(uByte)); if (hd.grptr==NULL) { hd.xsize = ERROR_GRAPH_MEMORY; hd.kind = HEADER_ERROR; return hd; } hd.buf = (uByte*)malloc(hd.bsize*sizeof(uByte)); if (hd.buf==NULL) { free_CmnHead(&hd); hd.xsize = ERROR_GRAPH_MEMORY; return hd; } // カウンタ.ここでは,delete禁止 CVCounter* counter = NULL; if (hd.zsize>=5 && cnt) { counter = GetUsableGlobalCounter(); if (counter!=NULL) counter->SetMax(hd.zsize*2/10); } // 最大値,最小値を求める int j, k, ks, js, ln; T max, min; max = min = vp.gp[0]; ln = vp.xs*vp.ys; for (k=0; kStepIt(); if (counter->isCanceled()) { // キャンセル free_CmnHead(&hd); hd.xsize = ERROR_GRAPH_CANCEL; return hd; } } } vp.max = max; vp.min = min; // ノーマルコピー if (mode==MG2CH_NORMAL) { memcpy(hd.grptr, vp.gp, hd.lsize); } // 8bitへ変換 else if (checkBit(mode, MG2CH_OCTET)) { // 255以下はコントラスト調整しない if (!checkBit(mode, MG2CH_CONTRAST) && vp.max<=255 && vp.min>=0) { max = 255; min = 0; } for (k=0; kStepIt(); if (counter->isCanceled()) { // キャンセル free_CmnHead(&hd); hd.xsize = ERROR_GRAPH_CANCEL; return hd; } } } } if (counter!=NULL) counter->PutFill(); memcpy(hd.buf, &ct, hd.bsize); // Z方向の歪率, rboundの設定. if (!checkBit(mode, MG2CH_NOPARM)) { sWord* rz = (sWord*)hd.buf; if (vp.RZxy!=1.0) { hd.kind = hd.kind | HAS_RZXY; rz[9] = (sWord)RZXY_RATE; rz[8] = (sWord)(vp.RZxy*RZXY_RATE); } if (vp.base!=0) { rz[10] = (sWord)vp.base; hd.kind |= HAS_BASE; } rz[2] = (sWord)vp.rbound.zmin; rz[3] = (sWord)vp.rbound.zmax; rz[4] = (sWord)vp.rbound.ymin; rz[5] = (sWord)vp.rbound.ymax; rz[6] = (sWord)vp.rbound.xmin; rz[7] = (sWord)vp.rbound.xmax; hd.kind |= HAS_RBOUND; } return hd; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Tools // inline unsigned int ARGB2Int(unsigned int a, unsigned int r, unsigned int g, unsigned int b) { if (isBigEndian) { a = (unsigned int)((a&0x000000ff)<<24); r = (unsigned int)((r&0x000000ff)<<16); g = (unsigned int)((g&0x000000ff)<<8); b = (unsigned int) (b&0x000000ff); } else { b = (unsigned int)((b&0x000000ff)<<24); g = (unsigned int)((g&0x000000ff)<<16); r = (unsigned int)((r&0x000000ff)<<8); a = (unsigned int) (a&0x000000ff); } unsigned int c = (unsigned int)(a + r + g + b); return c; } #define RGBA2Int(r, g, b, a) ARGB2Int((r), (g), (b), (a)) #define ABGR2Int(a, b, g, r) ARGB2Int((a), (b), (g), (r)) #define BGRA2Int(b, g, r, a) ARGB2Int((b), (g), (r), (a)) inline uWord ARGB2Word(uWord a, uWord r, uWord g, uWord b) { if (isBigEndian) { a = (int)(((a&0x00ff)>>4)<<12); r = (int)(((r&0x00ff)>>4)<<8); g = (int)(((g&0x00ff)>>4)<<4); b = (int) ((b&0x00ff)>>4); } else { g = (int)(((g&0x00ff)>>4)<<12); b = (int)(((b&0x00ff)>>4)<<8); a = (int)(((a&0x00ff)>>4)<<4); r = (int) ((r&0x00ff)>>4); } uWord c = (uWord)(a + r + g + b); return c; } #define RGBA2Word(r, g, b, a) ARGB2Word((r), (g), (b), (a)) #define ABGR2Word(a, b, g, r) ARGB2Word((a), (b), (g), (r)) #define BGRA2Word(b, g, r, a) ARGB2Word((b), (g), (r), (a)) inline uWord RGB2Word(uWord r, uWord g, uWord b) { r = (int)(((r&0x00ff)>>3)<<11); g = (int)(((g&0x00ff)>>2)<<5); b = (int) ((b&0x00ff)>>3); uWord c = (uWord)(r + g + b); if (isLittleEndian) swap_byte(&c, 2, 2); return c; } /** See Also for Dx9 in Dx9.h inline D3DCOLOR Dx9Word2RGBA(uWord pp); inline D3DCOLOR Dx9Word2ARGB(uWord pp); inline D3DCOLOR Dx9Word2RGB (uWord pp); */ } // namespace #endif