• 締切済み

画像読み込み時のOutOfMemory

VC++2010ExpressのWindows Applicationで画像のサムネールを作るプログラムを作っています。 概略、つぎの様なコーディングです(細部は気にしないで下さい)。 for filePath in dlg->Files{ try{ String^ FileName = Path::GetFileName(filePath); Image^ img = Image::FromFiles(filePath); Bitmap^ bmp = gcnew Bitmap(Image, 48, 48); bmp->Save(FolderPath + "\\Thumbnails\\" + FileName); } chactch(System::Exception^ err){ Debug::Print("{0}", err->Massages); } } 問題は、数万件の画像を処理したときに、数千件までは順調に処理が進むのに、そのあと「OutofMemory」とか「メモリー不足」とか「GDI+で汎用エラー」といった例外が続発してしまうことです。マネージコードなのでリソースは自動的に解放されると思うのですが、それでも間に合わないのでしょうか?何か対処方法があれば、ご教示ください。

みんなの回答

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.2

>リソースは自動的に解放されると思うのですが この文章に引っかかりました。 Cでは確保したメモリーは自動開放はしないと記憶しています。 bmpを開放してみてください。

softwarelearner
質問者

お礼

有難うございます。 自己解決しました。 画像を一枚処理するごとに、下のPumpMesage()を実行したら、例外が発生しなくなりました。 やはり、リソース開放がOSに伝わるのに時間が掛っていたのが原因かと思っています。 なお、マネージコードなのでbmpの解放を明示的に行うことはできないのではないでしょうか。 #pragma comment(lib, "User32.lib") void PumpMessage() { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } }

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

マニュアルより http://msdn.microsoft.com/ja-jp/library/stf701f5%28v=vs.110%29.aspx > 例外 > OutOfMemoryException > ファイルのイメージ形式が有効ではありません。 > または > GDI+ はファイルのピクセル形式をサポートしません。 > 解説 > ファイルのイメージ形式が有効でない場合、または、そのファイルのピクセル形式が GDI+ でサポートされていない場合、このメソッドは OutOfMemoryException 例外をスローします。 これに該当していませんか?

softwarelearner
質問者

お礼

早速のアドバイス有難うございます。 私もそう考え、例外を起こす画像のみを集めて処理したところ、件数が少なければ例外が発生しませんでした。どうも数万件を処理した場合に、特に後半で例外が続発するので、何かリソースに関係しているのではないかと思い、今回の質問をしました。 それに、ひとつよく分からないのが、ご指摘の「形式がサポートされてない」とOutOfMemoryという言葉の関係です。形式がサポートされていならTypeNotSupportedとかを使えば良いのにと思いますが。

関連するQ&A

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

    ひとりで独学で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; 最終的にはタイル的にどんどん並べて行きたいと考えています。 助言の方よろしくお願いします。

  • VC++2005で高解像度画像の取り扱い。

    いつも質問ばかりで申し訳ないのですが、独学で勉強していて聞ける人がいないので協力して頂けたらと思います。 VC++2005のOS Windows32bit環境で高解像度(10240pixel × 10240pixel以上)の画像を取り扱うにはどうしたら良いのでしょうか? Bitmap^ bmp = gcnew Bitmap( 10240, 10240 ); ~省略 pictureBox1->Image = bmp ; のような書き方をして、エラーが出てる場所は Bitmap^ bmp = gcnew Bitmap( 10240, 10240 ); の部分です。 Bitmap^ bmp = gcnew Bitmap( 5120, 5120 ); だと平気です。 メモリーが不足しています。と警告が出てるのですが、はやり32bit環境では限界なのでしょうか? PCには8GB(うち5GB、RAMディスク)のメモリーを積んでますが、そう言う問題でもないですよね。 PhotoShopやAftterEffectとかはかなりの高解像度でも表示出来てるので不可能では無いとは思うのですが、初心者レベルでは無謀なのでしょうか? 何か打開策があれば教えて頂けたら助かります。 よろしくお願いします。

  • プログラムで、bmpをjpgに替えたらエラーして困ってます・・・。

    マネージ形式でbmpの画像の情報をlabel1などで表示できたんですけど、ファイル名の形式をjpgにしたら、情報が表示できずにエラーしました。 どこがまちがってるか、教えてください。 エラーした、プログラムをのせるんでアドバイスお願いします。 private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) {   Bitmap^image2; image2 = gcnew Bitmap( "画像名.jpg");   pictureBox1->Image = image2;        label3->Text = String::Format("幅(width) 高さ(height): {0}", image2->Size); } この、プログラムで、bmgの時は、image2 = gcnew Bitmap( "画像名.bmp");で、組んでエラーはなっかたんですけど、jpgの時は、image2 = gcnew Bitmap( "画像名.jpg");でしたら、エラーします。 MSDNで探してもわからず、色々試したんですがエラーしかでません。 ネットで検索してもあまりいい例が見つかりませんでした。適切なアドバイスお願いします。

  • 画像の連続取り込み

    Visual Studio 2005のC++を使ってプログラムしている者です。 C#で画像の連続した取り込みができるプログラムを見つけて、C++でもできないかと思い、とりあえず"000.bmp"という画像を読み込めるプログラムを組んで見たのですがどうもうまくいきません。 Visual Studio の検索で以下のようにできましたが"'System::Object::ToString' : 関数に 1 個の引数を指定できません。"といったエラーがでてしまいます。ある程度近いところまでいっているとは思うのですが・・・どこが間違っているのかわかる方おりましたらよろしくお願いします。 Object^ o = gcnew Object; o = (Object^)0; System::String^ filename = "C:/Documents and Settings/Owner/デスクトップ/"; //画像の場所ではなくファイルの場所(例:デスクトップ) filename += o->ToString("000") + ".bmp"; //ファイルの中の画像を指定 g = gcnew Bitmap(filename,true);

  • ビットマップ画像の色取得のご相談

    ビットマップ画像の色取得のご相談 WinXPでVC++2008ExpressEditionを使用してWinアプリケーションで画像処理をしようとしています.そこで,現在ビットマップのカラー画像を二値化(閾値判別分析法)するために,各色の抽出してグレースケール化を試みているのですが,色々試したのですがエラーがとれないので,もし間違い等ありましたら,ご助言いただけたらなと思います.何卒よろしくお願いいたします. 【エラー内容】 'System.ArgumentOutOfRangeException' のハンドルされていない例外が System.Drawing.dll で発生しました。追加情報: パラメータは正の値で、高さより小さい値指定しなければなりません。 【流れ】(ボタンを押したら以下三つを実行) 1.ファイルの読み込みピクチャーボックスに表示 2. ビットマップ画像の色の抽出 3. グレースケール化 /*ここから*/ OpenFileDialog^ OpenDlg = gcnew OpenFileDialog; //ファイルを開くダイアログ OpenDlg->Filter ="画像ファイル(*.bmp,*.jpg,*.jpeg,*.png,*.tif,*.tiff,*.ico)|*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.ico"; OpenDlg->ShowDialog(); //ダイアログの表示 if (OpenDlg->FileName == "") { //ファイル名が指定されなかった場合 return; } Bitmap^ bmp; bmp = gcnew Bitmap(OpenDlg->FileName); //Bitmapをファイルより作成 pictureBox1->Image = bmp; //ピクチャボックスへ画像の表示 Bitmap^ bmp1 = gcnew Bitmap(pictureBox1->Image); unsigned char Image_in[480][640][3]; //Image_in[Y][X][3] unsigned char (*Gray)[640] = new unsigned char[480][640]; //(*Gray)[X] = new unsigned char[Y][X] double Y; int i, j; //iがY方向,jがX方向 Color color1; unsigned char R,G,B; // 赤,緑,青成分の抽出 for( i = 1; i < 480; i++) //Y方向 { for( j = 1; j < 640; j++) //X方向 { ////////////////////////////////////////////// /*この辺がエラーの原因だと思うのですが・・・*/ color1 = bmp->GetPixel(i,j); R = color1.R; G = color1.G; B = color1.B; Image_in[i][j][0] = R; Image_in[i][j][1] = G; Image_in[i][j][2] = B; } } //RGB to Gray カラー画像をグレースケール化 for( i = 0; i < 480; i++) //Y方向 { for( j = 0; j < 640; j++) //X方向 { Y = 0.299*Image_in[i][j][0] + 0.587*Image_in[i][j][1] + 0.114*Image_in[i][j][2]; Gray[i][j] = Y; } }

  • 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;

  • Visual Studio 2005でWindowsフォームのプログラミングについて

    「Visual Studio 2005」のC++でWindowsフォームのプログラミングをしているのですが、画像保存ができなくて困ってます。 「開く」はどうにか参考書を見ながらできましたが、「保存」ができません。以下がプログラムとなっております。 private: System::Void 開くOToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {  OpenFileDialog^ myDLG = gcnew OpenFileDialog();  myDLG->AddExtension = true;  myDLG->DefaultExt = "bmp";  myDLG->FileName = "*.bmp";  myDLG->ShowReadOnly = false;  myDLG->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg";  if(myDLG->ShowDialog()==System::Windows::Forms::DialogResult::OK){    this->Text = myDLG->FileName;    pictureBox1->Image = gcnew Bitmap(myDLG->FileName);    Invalidate();  } } private: System::Void 保存SToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {  SaveFileDialog^ dlg = gcnew SaveFileDialog();  dlg->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg | すべてのファイル(*.*) | *.*";  if(dlg->ShowDialog() != System::Windows::Forms::DialogResult::OK){    return;  } /*** ここからわかりません。 ***/ } 知ってる方がいましたら教えてください。よろしくお願いします。

  • C#にて、イメージ画像の分割

    C#言語にて現在パズルゲームを作成しようと考えています。 パズルに使用するピースですが、ユーザが任意に選択した画像をプログラミングで規定の画像サイズに切り出し、それをパズルピースとして使用する仕様を考えています。 ファイルを開くボタン押下で、OpenFileDialogを表示し、ユーザに任意のイメージ画像を選択させます。その選択された画像を58pixcelx58pixcelのサイズの画像を9x6の54枚(パズルピース)に分割します。 以下がその仕様を考えたソースコードです。 private void selectButton_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); if (openFileDialog.ShowDialog() == DialogResult.OK) imageShow(openFileDialog.FileName); } private void imageShow(string filePath) { Bitmap _bmp = new Bitmap(58, 58); Image originalImage = Image.FromFile(filePath); Graphics g = Graphics.FromImage(_bmp); Rectangle rect; int x = 0; int y = 0; string title = "C:\\Image"; int index = 0; for (x = 0; x < 9; x++) { for (y = 0; y < 6; y++) { index++; rect = new Rectangle((x * 58) , (58 * y), 58, 58); g.DrawImage(originalImage, 0, 0, rect, GraphicsUnit.Pixel); _bmp.Save(title + index.ToString()+ ".jpg",System.Drawing.Imaging.ImageFormat.Jpeg); Thread.Sleep(50); } y = 0; } } パズルピースとして使用する予定のサイズ58x58のBitmapを作成します。そのBitmapからGraphicsを作成し、Graphicsに対してDrawImageでオリジナル画像(ユーザが選択した画像)を58Pixcelごとに分割し、分割されて作成されたImageをSave()にてファイル保存しています。 この仕様で一応ファイルは分割されて作成されるのですが、どうも画像の位置が合わないのです。画質も悪いですし。手動で同じオリジナルファイルを58Pixcelごとに切り出したものと比較しますと顕著にちがいます。 何か足りない処理や、他の対応策がございましたらご教授のほどよろしくお願いいたします。今回の仕様で、切り出したファイルをローカルマシンに保存する、と言うのは必須事項になっております。 どうか皆様よろしくお願いいたします。

  • VC++フォームアプリケーション でのビットマップ処理

    私は今Visual Studio 2005(C++)のフォームアプリケーションでプログラムを組んでいるのですが、ビットマップ処理ができません。以下のプログラムにどのような変更を加えればできるようになるのでしょうか? ご存知の方がいたら教えてください。 #pragma once ~フォームのデザイン部分のプログラム(自動)なので省略いたします~ #pragma endregion private: Bitmap^ bmp; private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { } private: System::Void 開くOToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { OpenFileDialog^ myDLG = gcnew OpenFileDialog(); myDLG->AddExtension = true; myDLG->DefaultExt = "bmp"; myDLG->FileName = "*.bmp"; myDLG->ShowReadOnly = false; myDLG->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg"; if(myDLG->ShowDialog() == System::Windows::Forms::DialogResult::OK){ this->Text = myDLG->FileName; pictureBox1->Image = gcnew Bitmap(myDLG->FileName); Invalidate(); } } private: System::Void 保存SToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { SaveFileDialog^ myDLG = gcnew SaveFileDialog(); myDLG->AddExtension = true; myDLG->DefaultExt = "bmp"; myDLG->FileName = "*.bmp"; myDLG->Filter = "ビットマップ(*.bmp) | *.bmp | jpeg(*.jpg;*.jpeg) | *.jpg;*.jpeg | すべてのファイル(*.*) | *.*"; if(myDLG->ShowDialog() != System::Windows::Forms::DialogResult::OK){ return; } pictureBox1->Image->Save(myDLG->FileName); Invalidate(); } private: System::Void 閉じるCToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { if(MessageBox::Show("アプリケーションを終了しますか?","画像描画",MessageBoxButtons::OKCancel,MessageBoxIcon::Question) == System::Windows::Forms::DialogResult::OK){ this->Close(); } } private: System::Void 編集ToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { } private: System::Void 回転180ToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { } } よろしくお願いします。

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

    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) { } }; }