Bitmapデータ型の画像幅の拡大

このQ&Aのポイント
  • Visual studio 2005のフォームアプリケーションで画像の幅を倍にする方法を教えてください。
  • 画像データの幅を倍にしようとするとエラーが発生し、実行できません。
  • BITMAPデータ型で読み込んだ画像の幅を倍にするための対処方法を教えてください。
回答を見る
  • ベストアンサー

Bitmapデータ型の画像幅の拡大

現在Visual studio 2005のフォームアプリケーションでプログラミグを行っている者です。以下のプログラムの中に画像の幅であるw,hという変数があるのですが、私の作ろうとしている画像処理の関係上、この画像データの幅を倍にしたいです(例:3*w,3*h)。しかし、変数宣言(例:int 3*w)やfor文の中で倍にしようとしても、ビルドはできるものの"アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました。・・・パラメータは正の値で、高さより小さい値指定しなければなりません。"とでて、実行できません。おそらく倍にしてあげたとこで、倍になった部分の画像データがわからないためこういったエラーが出てしまうのだと考えています。どうにかして、BITMAPデータ型で読み込んだ画像の幅を倍の数値を得たいのですが、エラーのでないようにするためにはどのようにしてあげればいいのでしょうか?わかる方がいたらよろしくお願いします。 プログラムは以下のとおりです。 #pragma once // 省略 // } #pragma endregion private:Bitmap^ pic; private:array< Bitmap^>^ bmp; // 原画像格納 // private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { bmp[0] = gcnew Bitmap("画像ファイル1",true); pictureBox1->Image = bmp[0]; pic = gcnew Bitmap("画像ファイル2",true); } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { int x,y,a,b; /* x,y: 画像の座標 a,b: 複合画像の座標 */ int w = pic->Width; //ここでpic->Width*3としてもエラー /* 複合画像の横幅 */ int h = pic->Height; /* 複合画像の縦幅 */ x = 0; y = 0; a = 0; b = 0; for(y = 0; y < h; y++){ //ここで3*hとしてもエラー for(x = 0; x < w; x+=3){ pic->SetPixel( x, y, bmp[1]->GetPixel( x, y ) ); } } pictureBox2->Image = pic; } }; }

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

復元処理のループの主体はどちらでしょう 個々の分割された画像なのか、復元された大画像なのか 個々の画像なら for ( y = 0; y < h; y++ ) {   for ( x = 0; x < w; x ++ ) {     for ( i = 0; i < 3; i ++ ) {       for ( j = 0; j < 3; j++ ) {         pic->SetPixel( x * 3 + j, y * 3 + i ,           bmp[j * 3 + i]->GetPixel( x, y ) );       }     }   } } 逆ならば for ( y = 0; y < h; y += 3 ) {   for ( x = 0; x < w; x += 3 ) {     for( i = 0; i < 3; i++ ) {       for( j = 0; j < 3; j++ ) {         pic->SetPixel( x + j, y + i ,           bmp[i * 3 + j]->GetPixel( x / 3, y / 3 ) );       }     }   } } といった具合でしょう ・・・

judas15
質問者

お礼

大画像の方なので下のプログラムになるかと思います。 自分でも以下のように作っておいてあります。どちらもビルドは通りますが、実行するとアプリケーションのコンポーネントで、"ハンドルされていない例外が発生しました。・・・パラメータは正の値で、幅より小さい値を指定しなければなりません。"とでてしまいます。画像の幅を変えるだけではなく何か別の設定を変える必要があるのでしょうか。 for(y = 0; y < h; y++){ for(x = 0; x < w; x+=3){ pic->SetPixel( a, b, bmp[0]->GetPixel( x, y ) ); pic->SetPixel( a+1, b, bmp[1]->GetPixel( x, y ) ); pic->SetPixel( a+2, b, bmp[2]->GetPixel( x, y ) ); pic->SetPixel( a+3, b, bmp[3]->GetPixel( x+1, y ) ); pic->SetPixel( a+4, b, bmp[4]->GetPixel( x+1, y ) ); pic->SetPixel( a+5, b, bmp[5]->GetPixel( x+1, y ) ); pic->SetPixel( a+6, b, bmp[6]->GetPixel( x+2, y ) ); pic->SetPixel( a+7, b, bmp[7]->GetPixel( x+2, y ) ); pic->SetPixel( a+8, b, bmp[8]->GetPixel( x+2, y ) );               ・               ・ ・ pic->SetPixel( a+3, b+2, bmp[0]->GetPixel( x+1, y ) ); pic->SetPixel( a+4, b+2, bmp[1]->GetPixel( x+1, y ) ); pic->SetPixel( a+5, b+2, bmp[2]->GetPixel( x+1, y ) ); pic->SetPixel( a+6, b+2, bmp[3]->GetPixel( x+2, y ) ); pic->SetPixel( a+7, b+2, bmp[4]->GetPixel( x+2, y ) ); pic->SetPixel( a+8, b+2, bmp[5]->GetPixel( x+2, y ) ); pic->SetPixel( a, b+2, bmp[6]->GetPixel( x, y ) ); pic->SetPixel( a+1, b+2, bmp[7]->GetPixel( x, y ) ); pic->SetPixel( a+2, b+2, bmp[8]->GetPixel( x, y ) ); a = a + 9; } b = b + 3; a = 0; }

その他の回答 (5)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.6

> これは( b * 3 + a + x ) > 10 の場合であってますよね? ん? bmpのインデックスって0-8ですよね ( b * 3 + a + x )がいくつでも % 9 で剰余を計算すると 0-9になりますよ ・・・ 正の整数なら 1-9がほしいいなら( ( b * 3 + a + x ) % 9 ) + 1 とすれば良いでしょう

judas15
質問者

お礼

すみません、私が勘違いしていました。確かになりますね。 合成画像もなんとか作れました。ありがとうございました。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

わたしの#3のコードですと #2のお礼のような並びにはならないと思います 0,1,2 3,4,5 6,7,8 の並びが繰り返されていますので … bmp[b * 3 + a] は bmp[ ( b * 3 + a + x ) % 9 ] にすればいいのではないかと思います

judas15
質問者

お礼

なるほど!%9を使うのは思いつきませんでした。 これは( b * 3 + a + x ) > 10 の場合であってますよね? たしか1%10などは0になってしまうはずなので、(間違ってるかもです・・。) ( b * 3 + a + x ) < 10 の場合は bmp[ b * 3 + a + x ] にしてあげると合いますね。 for(y = 0; y < h; y++){ for(x = 0; x < w; x+=3){ pic->SetPixel( x, y, bmp[1]->GetPixel( x, y ) ); } } だと普通に動いてくれるので、やはりa,bの演算結果の値がおかしいか、w,hの幅領域を広げてしまったのが原因のようですね。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

GetPixelとSetPixelを分けてみてはいかがでしょう 多分 a,bの演算結果範囲が 画像の範囲をはみ出してしまっているように思います

judas15
質問者

お礼

返答が遅くて申し訳ないです>< GetPixelとSetPixelを分けるとはどういうことでしょうか? はみ出さない様に合成画像であるpicの幅領域をh*3,w*3とせず、元々の画像の大きさを3倍以上にしてh,wとしても同じエラーが発生してしまいます。毎回"xのパラメータは正の値で、高さより小さい値指定しなければなりません”と言われるので、xとyに問題があるのでしょうか? 計算してみて気づいたんですけど、redfox63の考えていた以下のプログラムで9回目までのループは正しいのですが、10回目のループが pic->SetPixel( 3, 0, bmp[0]->GetPixel( 1, 0 ) ); とならないでしょうか? ここはホントなら pic->SetPixel( 3, 0, bmp[4]->GetPixel( 1, 0 ) ); となってほしいところなのです。間違っていたらすみません。 for ( y = 0; y < h; y += 3 ) {  for ( x = 0; x < w; x += 3 ) {   for( b = 0; b < 3; b++ ) {    for( a = 0; a < 3; a++ ) {      pic->SetPixel( x + a, y + b , bmp[b * 3 + a]->GetPixel( x / 3, y / 3 ) );    }   }  } }

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

0 1 2 3 4 5 6 7 8 といった具合にBitmapを並べたいってことでしょうか? それとも個々のビットマップ1は (0,0), (w,0), (2w,0) などと 元の大きな画像の飛び飛びの画素を集めた画像なのでしょうか どうも後者のような気がしますが ・・・ このあたりをきちんと説明しないとトンチンカンな回答になってしまいます 仮に個々の画像が3x3で 復元先を9x9とした場合の画素はどのように並ぶのでしょう ------------------------------------------------------------- [0-0,0][1-0,0][2-0,0]|[0-1,0][1-1,0][2-1,0]|[0-2,0][1-2,0][2-2,0] [0-0,1][1-0,1][2-0,1]|[0-1,1][1-1,1][2-1,1]|[0-2,1][1-2,1][2-2,1] [0-0,2][1-0,2][2-0,2]|[0-1,2][1-1,2][2-1,2]|[0-2,2][1-2,2][2-2,2] ------------------+-----------------+------------------------ [3-0,0][4-0,0][5-0,0]|[3-1,0][4-1,0][5-1,0]|[3-2,0][4-2,0][5-2,0] [3-0,1][4-0,1][5-0,1]|[3-1,1][4-1,1][5-1,1]|[3-2,1][4-2,1][5-2,1] [3-0,2][4-0,2][5-0,2]|[3-1,2][4-1,2][5-1,2]|[3-2,2][4-2,2][5-2,2] ------------------+-----------------+------------------------ [6-0,0][7-0,0][8-0,0]|[6-1,0][7-1,0][8-1,0]|[6-2,0][7-2,0][8-2,0] [6-0,1][7-0,1][8-0,1]|[6-1,1][7-1,1][8-1,1]|[6-2,1][7-2,1][8-2,1] [6-0,2][7-0,2][8-0,2]|[0-1,2][7-1,2][8-1,2]|[6-2,2][7-2,2][8-2,2] といった具合の並びなのでしょうか [図番号-X,Y]といった表記です

judas15
質問者

お礼

返答ありがとうございます。 お察しのとおり後者の飛び飛びの画素を集めた画像にするつもりです。 並び方は、 [0-0,0][1-0,0][2-0,0]|[3-1,0][4-1,0][5-1,0]|[6-2,0][7-2,0][8-2,0] [3-0,0][4-0,0][5-0,0]|[6-1,0][7-1,0][8-1,0]|[0-2,0][1-2,0][2-2,0] [6-0,0][7-0,0][8-0,0]|[0-1,0][1-1,0][2-1,0]|[3-2,0][4-2,0][5-2,0] -----------------+-----------------+------------------------ [0-0,1][1-0,1][2-0,1]|[3-1,1][4-1,1][5-1,1]|[6-2,1][7-2,1][8-2,1] [3-0,1][4-0,1][5-0,1]|[6-1,1][7-1,1][8-1,1]|[0-2,1][1-2,1][2-2,1] [6-0,1][7-0,1][8-0,1]|[0-1,1][1-1,1][2-1,1]|[3-2,1][4-2,1][5-2,1] -----------------+-----------------+------------------------ [0-0,2][1-0,2][2-0,2]|[3-1,2][4-1,2][5-1,2]|[6-2,2][7-2,2][8-2,2] [3-0,2][4-0,2][5-0,2]|[6-1,2][7-1,2][8-1,2]|[0-2,2][1-2,2][2-2,2] [6-0,2][7-0,2][8-0,2]|[0-1,2][1-1,2][2-1,2]|[3-2,2][4-2,2][5-2,2] とするつもりです。 (1)|(2)|(3) --+--+-- (4)|(5)|(6) --+--+-- (7)|(8)|(9) とすると(1)が1~9枚の画像の(0,0)の画素、(2)が(0,1)、・・・、(4)が(1.0)、・・・、(9)が(2,2)の画素となっております。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

画像ファイル1の大きさが300x200で画像ファイル2の大きさが900x600といった具合になっているのでしょうか こうなっているのであれば int w = pic->Width; でいいのでは … pic->Width * 3 としてしまうと 2100になってしまいますよ for( y = 0; y < h; y++ ) {   for( x = 0; x < w; x++ ) {     pic->SetPixel( x, y, bmp[1]->GetPixel( x / 3, y / 3 ) );   } } pictureBox2->Image = pic; といった具合でしょう …

judas15
質問者

お礼

今回もありがとうございます。そして返事が遅れてしまって申し訳ありません。 私の説明がたぶんわかりにくかったです、すみません。私が作りたいのは9枚の画像(bmp[0]~bmp[8])の全画素を1つに組合わせた画像で、9枚の画像の大きさは全て同じものです。なので特殊な画像処理で合成された画像(pic)は1枚分(bmp[0]~bmp[8]の大きさは同じなので、どれでもよいが、ここではpicにはbmp[0]の画像を入れるようにしている)の横*3、縦*3の画像となります。そのためにどうしても元の画像の横縦3倍の幅領域(pic->Width*3、pic->Heigh*3)が必要になってきます。

関連するQ&A

  • フォーム間のデータ受け渡し

    現在VIsual Studio 2005のフォームアプリケーションを使ってプログラミングしています。ボタンを押すことで新たな子フォームを作成し、親フォームから子フォームへグローバル関数で宣言しているbmp[],picture[],red[]などのデータを渡したいのですがどうすればいいのかわからず困っております。子フォームから親フォームへテキストボックスなどの値を渡す方法などはわかったのですが、それをどう応用していいのかもわからない状況です。最終的には親フォームのbmp[0]におけるred[0]が1(画像処理されている)なら子フォームでbmp[0]を表示させたいと思っています。わかる方がいましたらどうかご教授ください。よろしくお願いします。以下がプログラムとなっております。 *** 親フォーム *** #pragma once #include "pic2.h" namespace pic { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::IO; // 省略 // public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // bmp = nullptr; Array::Resize( bmp, 20 ); Array::Resize( picture, 20 ); Array::Resize( bmpr, 20 ); this->red = gcnew array<int>(20); } // 省略 // private: System::Windows::Forms::PictureBox^ pictureBox1; private:array< Bitmap^>^ bmp; // 原画像格納 // private:array< Bitmap^>^ bmpr; // 処理画像格納 // private:array< PictureBox^>^ picture; private:array< int>^ red; // 処理:1 不処理:0 // // 省略 // #pragma endregion private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { bmp[0] = gcnew Bitmap("ファイル名",true); } private: System::Void button1_Click_1(System::Object^ sender, System::EventArgs^ e) { pic2 ^p2 = gcnew pic2(); p2->ShowDialog();     /* ボタンを押すことで新たなフォーム作成 */ } private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) { int x,y; int w = bmpr[0]->Width; int h = bmpr[0]->Height; if(red[0] == 1){ bmp[0] = gcnew Bitmap("ファイル名",true); pictureBox1->Image = bmp[0]; red[0] = 0; return; } if(red[0] == 0){ // 画像処理 // pictureBox1->Image = bmpr[0]; red[0] = 1; } } }; *** 子フォーム *** #pragma once //#include "Form1.h" #include "pic3.h" using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace pic { /// <summary> /// pic2 の概要 /// public ref class pic2 : public System::Windows::Forms::Form { public: pic2(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // } // 省略 // } #pragma endregion private: System::Void pic2_Load(System::Object^ sender, System::EventArgs^ e) { if(親フォームのred[0]==1ならば){ pictureBox1->Image = bmp[0] } } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {   // 新たな子フォームpic3作成 // } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { this->Close(); } }; }

  • 配列を使ったビットマップクラス

    VC++を使ったフォームアプリケーションでビットマップなどの画像を表示させ、ピクセル処理を施せるプログラムを作りました。このプログラム上ではピクチャボックスを1つ用意していますが、今後もっと多くのピクチャボックスが必要になってきます。以下のプログラムではBitmapクラスのbmpをピクチャボックス1の画像に入れています。単純にBitmapクラスのbmpを増やせば(例:bmp1)、ピクチャボックスが増えても平気ですが、処理の関係上配列を使いたいと思っています。なので下に書いてあるプログラムのbmp->という部分をbmp[0]->というふうに変えたいと考えています。自分なりに調べて(1)、(2)の部分を変えればいいと思うのですがどうもうまくいきません。わかる方がいたらご教授ください、おねがいします。 #pragma once namespace bmp { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Text; using namespace System::Collections::Generic; /// <summary> /// Form1 の概要 /// /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを /// 変更する必要があります。この変更を行わないと、 /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 /// 正しく相互に利用できなくなります。 /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // bmp = nullptr; ……… (1) //Bitmap^ bmp[300]; }      //省略// #pragma endregion //private: array<Bitmap^>^ bmp = gcnew array<Bitmap^>(300); ……… (2) private: Bitmap^ bmp; private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { bmp = gcnew Bitmap("C:/Documents and Settings/Owner/デスクトップ/lena.bmp",true); pictureBox1->Image = bmp; } private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) { /*bmp = gcnew Bitmap("C:/Documents and Settings/Owner/デスクトップ/lena.bmp",true);*/ int x,y; int w = bmp->Width; int h = bmp->Height; for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ if(x < (w * 0.05) || y < (h * 0.05) || (y > (h - (h*0.05)))&&(y < h) || (x > (w - (w*0.05)))&&(x < w)){ Color pixelColor = bmp->GetPixel( x, y ); Color newColor = Color::FromArgb( 255, 0, 0 ); bmp->SetPixel( x, y, newColor ); } } } pictureBox1->Image = bmp; } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { } }; }

  • 二つの画像を並べて表示

    ひとりで独学でVC++2005を勉強してるのですが、pictureBoxでつまずいます。初心者ですがわかりやすく教えて頂けたらと思います。 やりたい事はタイトル通り、画像を単純に並べて表示したいだけなのですが、WEB場で検索しても的を得た答えが見つかりませんでした。 二つの画像を読み込んで、新しいBitmapデータに書き込めばいいのかと思ったのですが、どうやっていいのか見当が付きません。 Bitmap^ bmpA = gcnew Bitmap("testAA.bmp"); Bitmap^ bmpB = gcnew Bitmap("testAB.bmp"); int w = bmpA->Width + bmpB->Width; int h = bmpA->Height + bmpB->Height; Bitmap^ bmp = gcnew Bitmap(w,h); //ここで何やっていいかわかりません。 pictureBox1->Image = bmp; 最終的にはタイル的にどんどん並べて行きたいと考えています。 助言の方よろしくお願いします。

  • C#でBitmapの画像を比較

    C#でBitmapの画像を比較するときに、 bmp.GetPixel(W, H); でひとつひとつ比較していけば出来るのですが、 全く同じBitmapかどうかの比較をするのに、 Bitmap情報の数値化などで、 簡単な方法はあるのでしょうか? 画像比較速度を上げたいので。 よろしくお願い致します。

  • 複数枚画像の合成

    こんにちわ、Visual Studio 2005のフォームアプリケーションでプログラミングしているものです。複数枚の画像を一つの画像にしたいのですが、どうもあっているのかどうかわかりません。 たとえば、画像が9枚あって1枚目の一番左上の画素を[0-0,0]とすると、 [0-0,0][1-0,0][2-0,0]|[3-1,0][4-1,0][5-1,0]|[6-2,0][7-2,0][8-2,0] [0-0,0][1-0,0][2-0,0]|[3-1,0][4-1,0][5-1,0]|[6-2,0][7-2,0][8-2,0] [3-0,0][4-0,0][5-0,0]|[6-1,0][7-1,0][8-1,0]|[0-2,0][1-2,0][2-2,0] [3-0,0][4-0,0][5-0,0]|[6-1,0][7-1,0][8-1,0]|[0-2,0][1-2,0][2-2,0] [6-0,0][7-0,0][8-0,0]|[0-1,0][1-1,0][2-1,0]|[3-2,0][4-2,0][5-2,0] [6-0,0][7-0,0][8-0,0]|[0-1,0][1-1,0][2-1,0]|[3-2,0][4-2,0][5-2,0] -----------------+-----------------+------------------------ [0-0,1][1-0,1][2-0,1]|[3-1,1][4-1,1][5-1,1]|[6-2,1][7-2,1][8-2,1] [0-0,1][1-0,1][2-0,1]|[3-1,1][4-1,1][5-1,1]|[6-2,1][7-2,1][8-2,1] [3-0,1][4-0,1][5-0,1]|[6-1,1][7-1,1][8-1,1]|[0-2,1][1-2,1][2-2,1] [3-0,1][4-0,1][5-0,1]|[6-1,1][7-1,1][8-1,1]|[0-2,1][1-2,1][2-2,1] [6-0,1][7-0,1][8-0,1]|[0-1,1][1-1,1][2-1,1]|[3-2,1][4-2,1][5-2,1] [6-0,1][7-0,1][8-0,1]|[0-1,1][1-1,1][2-1,1]|[3-2,1][4-2,1][5-2,1] -----------------+-----------------+------------------------ [0-0,2][1-0,2][2-0,2]|[3-1,2][4-1,2][5-1,2]|[6-2,2][7-2,2][8-2,2] [0-0,2][1-0,2][2-0,2]|[3-1,2][4-1,2][5-1,2]|[6-2,2][7-2,2][8-2,2] [3-0,2][4-0,2][5-0,2]|[6-1,2][7-1,2][8-1,2]|[0-2,2][1-2,2][2-2,2] [3-0,2][4-0,2][5-0,2]|[6-1,2][7-1,2][8-1,2]|[0-2,2][1-2,2][2-2,2] [6-0,2][7-0,2][8-0,2]|[0-1,2][1-1,2][2-1,2]|[3-2,2][4-2,2][5-2,2] [6-0,2][7-0,2][8-0,2]|[0-1,2][1-1,2][2-1,2]|[3-2,2][4-2,2][5-2,2] といった感じにしようと思っています。 画像には配列を使っていてbmp[0]~[8]が9枚の画像を表し、picはbmp[0]~[8]の画像一枚に対してサイズが横3倍縦6倍の画像になるはずです。 自分でプログラムしたのですが、できた画像を拡大しても細かすぎてよくわからない状況です。 for ( y = 0; y < h; y += 6 ) {  for ( x = 0; x < w; x += 3 ) {   for( b = 0; b < 3; b++ ) {    for( a = 0; a < 3; a++ ) {      pic->SetPixel( x + a, y + (2 * b) , bmp[((2 * b) * 3 + a + x) % 9]->GetPixel( x / 3, y / 6 ) );      pic->SetPixel( x + a, y + (2 * b) , bmp[(((2 * b) + 1) * 3 + a + x) % 9]->GetPixel( x / 3, y / 6 ) );    }   }  } } 以前に、同じような配置法なのですが横3倍縦3倍の合成画像として、 [0-0,0][1-0,0][2-0,0]|[3-1,0][4-1,0][5-1,0]|[6-2,0][7-2,0][8-2,0] [3-0,0][4-0,0][5-0,0]|[6-1,0][7-1,0][8-1,0]|[0-2,0][1-2,0][2-2,0] [6-0,0][7-0,0][8-0,0]|[0-1,0][1-1,0][2-1,0]|[3-2,0][4-2,0][5-2,0] -----------------+-----------------+------------------------ [0-0,1][1-0,1][2-0,1]|[3-1,1][4-1,1][5-1,1]|[6-2,1][7-2,1][8-2,1] [3-0,1][4-0,1][5-0,1]|[6-1,1][7-1,1][8-1,1]|[0-2,1][1-2,1][2-2,1] [6-0,1][7-0,1][8-0,1]|[0-1,1][1-1,1][2-1,1]|[3-2,1][4-2,1][5-2,1] -----------------+-----------------+------------------------ [0-0,2][1-0,2][2-0,2]|[3-1,2][4-1,2][5-1,2]|[6-2,2][7-2,2][8-2,2] [3-0,2][4-0,2][5-0,2]|[6-1,2][7-1,2][8-1,2]|[0-2,2][1-2,2][2-2,2] [6-0,2][7-0,2][8-0,2]|[0-1,2][1-1,2][2-1,2]|[3-2,2][4-2,2][5-2,2] の配置プログラムとして、 for ( y = 0; y < h; y += 3 ) {  for ( x = 0; x < w; x += 3 ) {   for( b = 0; b < 3; b++ ) {    for( a = 0; a < 3; a++ ) {      pic->SetPixel( x + a, y + b , bmp[(b * 3 + a + x) % 9]->GetPixel( x / 3, y / 3 ) );    }   }  } } との回答をいただいたので、これを参考に作ってみたのですが・・・。 説明が下手でわかりにくいかもしれませんが、お分かりの方がいましたらご教授お願いします。

  • bitmap画像の保存がうまくいきません。

    VC++のMFC、ダイアログベースで画像処理のソフトを作っています。 処理した画像を保存したいのですが、「描画できませんでした」というメッセージのでるファイルになってしまい、うまく保存できません。 プログラムは以下のようになっていてピクチャーコントロールの変数をm_pict8にしています。また、画像は24ビットで240×320のものを保存します。 static LONG CalcScanLineByte(const LONG w, const WORD bpp) { return (((bpp * w) + 31) / 32) * 4; } //----------------------------------------------------------- void Cstart2Dlg::OnBnClickedButton10() //保存ボタン { CFileDialog myDLG(FALSE,"BMP","*.BMP",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"画像(*.BMP)|*.BMP||"); if(myDLG.DoModal() == IDOK){ CStdioFile fout(myDLG.GetPathName(),CFile::modeCreate | CFile::modeWrite|CFile::typeBinary); //ピクチャボックスからビットマップを取り出す HBITMAP hBitmap = m_pict8.GetBitmap(); //無いので処理できない if(hBitmap == NULL)return; //ビットマップの情報を取る BITMAP bitmap = {0}; ::GetObject(hBitmap, sizeof(bitmap), &bitmap); //4バイト調整したスキャンラインのサイズ const int iScanLineByte = ::CalcScanLineByte(240, bitmap.bmBitsPixel); //const int iScanLineByte = ::CalcScanLineByte(bitmap.bmWidth, bitmap.bmBitsPixel); //ファイルヘッダとビットマップヘッダ BITMAPFILEHEADER bmfh = {sizeof(bmfh)}; BITMAPINFOHEADER bmif = {sizeof(bmif)}; //ビットマップである事を示す名称 bmfh.bfType = ('M' << 8) | 'B'; //イメージデータへのオフセットはファイルヘッダ+ビットマップヘッダ bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmif); //見ての通り bmif.biBitCount = 24; //24ビットの時はBI_RGBで固定 bmif.biCompression = BI_RGB; //常に1で固定 bmif.biPlanes = 1; //見ての通り bmif.biWidth = 240; bmif.biHeight= 320; //bmif.biWidth = bitmap.bmWidth; //bmif.biHeight= bitmap.bmHeight; //4バイト調整も含めた正確な合計バイトサイズが必要 bmif.biSizeImage = iScanLineByte * bmif.biHeight; //ファイルヘッダ→ビットマップヘッダの順番に書き出す fout.Write(&bmfh, sizeof(bmfh)); fout.Write(&bmif, sizeof(bmif)); //イメージデータをセーブする HDC hMemDC = ::CreateCompatibleDC(NULL); ::SelectObject(hMemDC, hBitmap); //yを縦幅-1から回転させないと上下逆転してしまう for(int y = bmif.biHeight - 1; y >= 0; --y) { //3バイトずつステップする for(int x = 0; x < iScanLineByte; x += 3) { const COLORREF cref = ::GetPixel(hMemDC, x / 3, y); //色素の位置関係をBGRにしないと赤と青の関係が逆転してしまう const BYTE arrBy[3] = {GetBValue(cref), GetGValue(cref), GetRValue(cref)}; //1ピクセル分(3バイト)書き出す fout.Write(arrBy, sizeof(arrBy)); } } ::DeleteDC(hMemDC); } どこか改善点などありましたら、よろしくお願いいたします。

  • ビットマップを直接編集して背景画像を波打たせる

    質問(1) pixelsは一次元配列で1ラインのx方向の要素を左方向や右方向にシフト量sだけ離れた所へコピーすることにより1ラインの画像のピクセルデータをシフト量sだけずらして波打たせる効果を持たせていることは想像つきますが、これではy方向を考慮した全てのラインをずらすことにはなっていない様な感じがします。y方向はどうなっているのですか? 質問(2) int line = y*bmpdata.Stride/4;で4で割っているのは何故ですか? 質問(3) if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } でこのif文の中の条件式x+s>=0はint x=-s;→int x+s=0;…;x++により明らかに常に真ではないですか?もし、そうだとしたらこのif文は必要ないのではないですか? 質問(4) } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } でこのif文の中の条件式x+s<BITMAP_Wの意味が良く分かりません。 質問(5)(6)(7) for(int y=0; y<BITMAP_H; y++){ … int line = y*bmpdata.Stride/4;の意味が良く分かりません。質問(5) … pixels[line+x+s] = pixels[line+x];でlineを加えているのは何故ですか?質問(6) … pixels[line+x] = pixels[line+x-s];でlineを加えているのは何故ですか?質問(7) C言語、C++言語初心者なので分かりやすく教えて下さい。 宜しくお願いします。 プログラムコード(animation.cpp) //ウェーブエフェクト UINT g_wavecount; const int BITMAP_H = 480; const int BITMAP_W = 320; float g_wavelines[BITMAP_H]; //ウェーブエフェクト初期化 void ResetWave(){ g_wavecount = 0; float r=0, rdelta=3.14f/12;//波の数 float waveh = 3;//波の高さ for(int i=0; i<BITMAP_H; i++){ g_wavelines[i] = sinf(r) * waveh; r += rdelta; } } //ウェーブエフェクト描画 void RenderWave(Gdiplus::Bitmap *bmp){ g_wavecount++; int topline = g_wavecount % BITMAP_H; //ビットマップのロック Gdiplus::BitmapData bmpdata; Gdiplus::Status status = bmp->LockBits( &Gdiplus::Rect(0,0,320,480), Gdiplus::ImageLockModeWrite, bmp->GetPixelFormat(), &bmpdata); if(status != Gdiplus::Ok) return; UINT* pixels = (UINT*)bmpdata.Scan0; //←この行から下のコードが全部分からない。 //ビットマップを加工する for(int y=0; y<BITMAP_H; y++){ //シフト量を取得 int s = (int)g_wavelines[(topline+y)%BITMAP_H]; int line = y*bmpdata.Stride/4; //ピクセルコピー if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } bmp->UnlockBits(&bmpdata); }

  • フォーム間のデータ受け渡し2

    Visual Studio 2005のフォームアプリケーションでプログラミングを行っているものです。前回と似たような質問になるのですが、微妙に状況が違っていてどうしてよいのかわかりません。まず、メインフォーム(Form1.h)でサブフォーム(pic0.h)を呼び出しているのですが、プログラムを見てお分かりのように起動時に呼び出ししているので最初に子フォームのpic0.hが現れます。この子フォームを消すことでメインフォームが現れるといった感じになっています。私がしたいことは、まずメインフォームの上でサブフォームを表示させ(メインフォームが表示された後にサブフォームが表示されてほしい)、さらにpic0.hでテキストボックスによる入力や出力で取得されたint型やdouble型のデータをForm1.hに引き渡すことです。以下がプログラムなのですが、どのようにプログラムしていいのかお分かりの方がいましたら御教授お願いします。 /*** メインフォーム(Form1.h) ***/ #pragma once #include "pic2.h" #include "pic0.h" // 省略 // #pragma endregion private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { pic0 ^p0 = gcnew pic0(); //起動時呼び出し p0->ShowDialog(this); } /*** サブフォーム(pic0.h) ***/ #pragma once // 省略 // #pragma endregion praivate int a,double b; a = double::Parse(textBox1->Text); //例1 b = double::Parse(textBox2->Text); //例2 // 省略 // /*** pic0.cpp ***/ #include "StdAfx.h" #include "pic0.h" #include "Form1.h" using namespace pic;

  • ビットマップ画像表示

    いつもお世話になっております。 VS2005でC++を用いてWindowsアプリケーションの作成をしています。 子ウィンドウにビットマップ画像(ファイル名:HELP.bmp)を 表示させようとプログラムを組んだのですが、 子ウィンドウを出してもビットマップ画像が表示されません。 以下のようなプログラムを追加しました。 --------------------------------- ///リソーススクリプト/////////////////////////////////  IDB_BITMAP1  BITMAP DISCARDABLE  "HELP.bmp" ///ヘッダースクリプト/////////////////////////////////  #define IDB_BITMAP1   3000 ///ソーススクリプト/////////////////////////////////// void ShowMyBMP(HWND hWnd, HDC hdc){   HDC hmdc;   HBITMAP hBitmap;   BITMAP bmp;   HINSTANCE hInst;   int BMP_W, BMP_H;   hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);   hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));  //インスタンスハンドル取得   GetObject(hBitmap, sizeof(BITMAP), &bmp);  //ビットマップの情報を得る   BMP_W = (int)bmp.bmWidth;  //画像の幅   BMP_H = (int)bmp.bmHeight;  //画像の高さ   hmdc = CreateCompatibleDC(hdc);  //メモリデバイスコンテキストハンドルを取得   SelectObject(hmdc, hBitmap);   BitBlt(hdc, 0, 0, BMP_W, BMP_H, hmdc, 0, 0, SRCCOPY);   StretchBlt(hdc, 0, BMP_H, BMP_W / 2, BMP_H / 2, hmdc, 0, 0, BMP_W, BMP_H, SRCCOPY);   DeleteDC(hmdc); //デバイスコンテキストハンドルを開放   DeleteObject(hBitmap);   return; } --------------------------------- ShowMyBMP関数は子ウィンドウを表示するときに実行されます。 全て載せられないので追加した部分のみプログラムを載せましたが、 この部分だけでも、プログラムの間違い等はありませんでしょうか。 ご教授お願いいたします。

  • GDIによるメモリ上からの画像データ読み込みに関して

    開発環境はVC++/CLIです。 アンマネージ型のCOMオブジェクトの扱いで困っております。 JPEGやPNGなどの画像データを保存したunsigned char型配列から、Gdiplus::Bitmap型を作ろうとしています。 unsigned int imagesize; // 画像のバイト数が格納されている array<unsigned char>^ image = gcnew array<unsigned char>(imagesize); //画像のデータが格納されている 事前にこのようなデータを用意し、以下のように記述しました。 HGLOBAL hResourceBuffer = GlobalAlloc(GMEM_MOVEABLE , imagesize); void* pResourceBuffer = GlobalLock(hResourceBuffer); CopyMemory(pResourceBuffer, &image, imagesize); IStream* pIStream = NULL; CreateStreamOnHGlobal(hResourceBuffer, TRUE, &pIStream) data->bmp = new Gdiplus::Bitmap(pIStream); pIStream->Release(); GlobalUnlock(hResourceBuffer); GlobalFree(hResourceBuffer); しかしながら、上記のコードだと、CopyMemory時に「保護されたメモリに書き込もうとした」といったエラーが発生します。 Webで色々検索しましたが、全て似たような記述で動作していました。 何が問題なのでしょうか? 尚、上記と同様の画像データ配列を使って、System::Drawing::Bitmap型に格納したとき、画像が正常に表示されることを確認しております。 画像のバイト数に於いても取得したデータに間違いはなく、やはりメモリ関連の問題だと思うのですが…。 MemoryStream^ memst = gcnew MemoryStream(image); Bitmap^ bmp = gcnew Bitmap(memst); memst->Close(); Graphics^ im = pictureBox1->CreateGraphics(); im->DrawImage(bmp, 0, 0, 100, 100); delete bmp;

専門家に質問してみよう