質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

604閲覧

Gdiplus::Bitmap::FromStream で、invalidparameterとなる

valval

総合スコア43

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2023/08/11 18:00

編集2023/08/12 00:52

実現したいこと

こちらの記事を参考にし、Gdiplus::Bitmap::FromStreamで、メモリ上に展開されたpngファイルを読みます

前提

復号化したpngファイルをメモリ内に保持し、IStream化後、Gdiplus::Bitmapにすることを想定しています。

発生している問題・エラーメッセージ

FromStreamでBitmapは生成されますが、その大きさが0✕0です。
このときのBitmapで、GetLastStatus()を行うと2(invalidParameter)
となります。

しかも、この事象は、同じ画像ファイルでも現れるときと現れないときが
ランダムに起きるため、困っています。

該当のソースコード

C++

1void CreateJpegTexture(const void* iData, uint32_t iDataSize) 2{ 3 // グローバルメモリを確保してロック 4 HGLOBAL aGlobalHandle = GlobalAlloc(GMEM_MOVEABLE, iDataSize); 5 if(aGlobalHandle) 6 { 7 void* aGlobalBuffer = GlobalLock(aGlobalHandle); 8 if(aGlobalBuffer) 9 { 10 // グローバルメモリにコピー 11 CopyMemory(aGlobalBuffer, iData, iDataSize); 12 13 // ストリーム作成 14 IStream* aIStream = NULL; 15 if(CreateStreamOnHGlobal(aGlobalHandle, FALSE, &aIStream) == S_OK) 16 { 17 // GDI+ビットマップ生成(グローバルメモリは解放) 18 Gdiplus::Bitmap* aBitmap = Gdiplus::Bitmap::FromStream(aIStream); 19 aIStream->Release(); 20 if(aBitmap && aBitmap->GetLastStatus() == Gdiplus::Ok) 21 { 22 // バッファにコピー 23 UINT aWidth = aBitmap->GetWidth(); 24 UINT aHeight = aBitmap->GetHeight(); 25 Gdiplus::Rect aRect(0, 0, aWidth, aHeight); 26 Gdiplus::BitmapData aBitmapData; 27 aBitmap->LockBits(&aRect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &aBitmapData); 28 const uint8_t* aPixels = reinterpret_cast<const uint8_t*>(aBitmapData.Scan0); 29 std::vector<uint32_t> aBuffer(aWidth * aHeight); 30 for(UINT aY = 0; aY != aHeight; ++aY) 31 { 32 for(UINT aX = 0; aX != aWidth; ++aX) 33 { 34 const uint8_t* aPixel = aPixels + aY * aBitmapData.Stride + aX * 4; 35 uint32_t aR = aPixel[2]; 36 uint32_t aG = aPixel[1]; 37 uint32_t aB = aPixel[0]; 38 uint32_t aA = aPixel[3]; 39 aR = aR * aA / 255; 40 aG = aG * aA / 255; 41 aB = aB * aA / 255; 42 aBuffer[aY * aWidth + aX] = (aA << 24) | (aB << 16) | (aG << 8) | aR; 43 } 44 } 45 aBitmap->UnlockBits(&aBitmapData); 46 47 // 解放 48 delete aBitmap; 49 50 // ~aBufferにピクセルデータが格納されている~ 51 } 52 } 53 54 // アンロック 55 GlobalUnlock(aGlobalHandle); 56 } 57 58 // 解放 59 GlobalFree(aGlobalHandle); 60 } 61}

上記20行目でaBitmap->GetLastStatus() == Gdiplus::Okにならないことがあります。

試したこと

ランダムに発生する事象なので、確保したが初期化されてないメモリが影響したと思い、10行目に

C++

1memset(aGlobalBuffer, 0, iDataSize);

で、確保されたメモリを0で埋めましたが、結果は変わっていません。

補足情報(FW/ツールのバージョンなど)

Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.4.4

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2023/08/12 04:28

データそのものは間違いないのでしょうか? あと、CreateStreamOnHGlobal の前に GlobalUnlock が必要な気がします。
valval

2023/08/12 04:31 編集

データそのものは、ストレージにpng形式で書き出すことが可能なので、間違いはありません。 GlobalUnlock ですね。調べてみます。
guest

回答1

0

自己解決

データそのものに破損が見つかりました。
お手数をおかけしました。

投稿2023/08/13 08:13

valval

総合スコア43

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問