• 締切済み

画像のビット数を変更する方法

http://okwave.jp/qa/q8880161.html このページなどで画像の取扱に関して詳しく教えていただきました。 大体、思ったことはできるようになったのですが まだ疑問点が残っております。 例えば、24bit画像をGDI+で読み込んで、 アルファチャンネルに情報を書き加えた後、 そのまま画像を出力します。 するとirfanviewなどで読み込んだ際に アルファチャンネルに情報をもっているにも拘わらず 24bit画像をとして認識されてしまいます。 アルファチャンネルをもっているかいないかではなく 画像のインデックスのところに24か32bitかを識別するものが含まれているようです。 読み込んだ24bit画像を32bit画像に変換したいのですが どのようにすれば良いでしょうか? GdipCreateBitmapFromScan0(lngWidth, lngHeight, 0, PixelFormat32bppARGB, ByVal 0&, hBmp2) を使えば、32bit画像を生成できますが 新たにbitmapオブジェクトを生成せずに 読み込んだオブジェクトのbit数を変更する方法を教えてください。

みんなの回答

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.1

mitarashiです。シリーズで回答させていただきながら、当方も勉強してきましたが、そろそろ追い越されそうな雰囲気ですね。お望みの事は分かりかねます。検索して見つかるのは、32bitカラーのGraphicsを質問文中にもあるGdipCreateBitmapFromScan0で作成した32bitのbitmapから作成する方法です。 myumyu1234さんが行われているのは、個々のPixelの透明度の変更の様なので、GdipBitmapLockBitsをお使いなのでしょうか。 回答にはなっておりませんが、前回のhttp://okwave.jp/qa/q8880161.htmlへの回答のコードがどうも分かり難いと思っていましたが、どうやら冗長らしいので、その部分を修正し、24->32bitへの変更も盛り込んだコードを投稿させていただきます。 なお、32bitをサポートしているPNGでの保存に変更しています。 構造体、API宣言は、下記が追加になります。 Public Const CLSID_PNG As String = "{557CF406-1A04-11D3-9A73-0000F81EF32E}" Public Declare Function GdipGraphicsClear Lib "gdiplus" (ByVal graphics As Long, ByVal lColor As Long) As Long Sub test() Dim IID_IDispatch As GUID Dim udtInput As GdiplusStartupInput Dim lngToken As Long, lngStatus As Long Dim pGraphics As Long Dim pSrcBmp As Long, pDstBmp As Long Dim lngWidth As Long, lngHeight As Long Dim srcPath As String, dstPath As String Const myDpi As Long = 300 srcPath = GetDesktopPath & "\sample1.jpg" dstPath = GetDesktopPath & "\sample2.png" ' 初期化 udtInput.GdiplusVersion = 1 If GdiplusStartup(lngToken, udtInput, ByVal 0&) <> 0 Then Exit Sub End If ' 画像の読みこみ If GdipCreateBitmapFromFile(ByVal StrPtr(srcPath), pSrcBmp) <> 0 Then GdiplusShutdown lngToken Exit Sub End If ' 元画像サイズの取得 GdipGetImageWidth pSrcBmp, lngWidth GdipGetImageHeight pSrcBmp, lngHeight ' コピー先Bitmap作成 lngStatus = GdipCreateBitmapFromScan0(lngWidth, lngHeight, 0, PixelFormat32bppARGB, ByVal 0&, pDstBmp) 'dpiの指定 lngStatus = GdipBitmapSetResolution(pDstBmp, myDpi, myDpi) If lngStatus = 0 Then ' コピー用Graphics作成 If GdipGetImageGraphicsContext(pDstBmp, pGraphics) = 0 Then '白で初期化(検索してみつかったコードは大抵含んでいたので追加) GdipGraphicsClear pGraphics, &HFFFFFFFF ' イメージのコピー GdipDrawImageRectI pGraphics, pSrcBmp, 0, 0, lngWidth, lngHeight 'Graphicsの始末 GdipDeleteGraphics pGraphics 'PNGで保存 Call GdipSaveImageToFile(pDstBmp, StrPtr(dstPath), ConvCLSID(CLSID_PNG), ByVal 0&) End If GdipDisposeImage pDstBmp End If GdipDisposeImage pSrcBmp GdiplusShutdown lngToken End Sub

関連するQ&A

  • 8bitインデックス画像の入出力方法

    http://okwave.jp/qa/q8852322.html http://okwave.jp/qa/q8856128.html このページで画像の配列への入出力の仕方を教えていただきました。 配列の読み書きの方法が分かればできるかと思ったのですが やり方がわかりませんでしたので質問いたします。 24あるいは32bitの場合には教えていただいた方法で問題ないのですが 8bitの画像(インデックスカラー画像)の場合にはどうしたら良いでしょうか? 8bit画像を GdipCreateBitmapFromFile(ByVal StrPtr(strInName), pSrcBitmap) で取得し、そのまま GdipSaveImageToFile pSrcBitmap, StrPtr(strOutName), encTIFF, VarPtr(udtEncParam) を使って、別の画像形式に再圧縮して出力しても 8bit画像として出力されるので、 pSrcBitmapにはインデックスカラーに関する情報と 256階調(8bit)での画像情報も含まれているようです。 しかしながら、 GdipBitmapGetPixel pSrcBitmap, x, y, myARGB で画像情報を抽出すると 8bit画像を読み込んだとしても 32bitカラー情報として抽出されてしまいます。 http://www.vbforums.com/showthread.php?718163-GDI-GdipGetImagePixelFormat-(untrusted) このサイトにPixelFormatの設定の仕方が書かれてあって、 PixelFormat24bppRGB = &H21808 を用いると24bit画像として出力できることが分かりました。 PixelFormat8bppIndexed = &H30803 を指定してみたのですが、 一応、8bit画像として出力することは確認できたのですが 出力にものすごく時間がかかってしまうのですが。 恐らくインデックスを生成するのに時間がかかっているのだと思うのですが 既にインデックスがでている場合にどのように指定すれば良いか、 8bit画像からインデックスを抽出するのかが分からないのですが。 どのようにすれば インデックスカラーと256階調(8bit)での画像情報を 配列に読み込み、および配列から画像への書き出しを行えますでしょうか?

  • GDI+を使ったビット数とDPIの扱い

    http://okwave.jp/qa/q8858627.html このページでVBAのGDI+を使った8bitや24bitの画像の取扱方にについて教えていただきました。 追加の質問なのですが 画像を読み込んで画像のビット数を調べるにはどうしたら良いですか? 8bitなのか24bitなのか? それと読み込んだ画像のdpiを取得する方法および dpiを設定して画像を保存するにはどうしたら良いですか? 検索して調べてみましたが見つかりませんでしたので ご助言いただけないでしょうか?  

  • GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。

    GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。 環境は、VC++のWin32プロジェクトです。 WindowのデバイスコンテキストからGraphicsオブジェクトを生成し、DrawStringとすると滑らかに描画されます。 しかし、BitmapオブジェクトからGraphicsオブジェクトを生成し、DrawStringを行うとビットマップフォントのようです。 Graphics g(hdc); g.DrawString(......); -> この場合はなめらか(画像の下の方) しかし、 Bitmap bmp(w, h, PixelFormat32bppARGB); Graphics g (&bmp); g.SetSmootingMode(SmoothingModeHighQuality); g.DrawString(...); -> ジャギが目立つ。(画像の上の方) ビットマップ(メモリ)にスムーズなテキストを描画することはできないのでしょうか? ちなみにフォントはメイリオです。

  • IrfanViewのポータブル版64bitについて

    画像ソフトの、IrfanViewのPortable版の64bitを探しているのですが、 こちらのサイトでしたポータブル版はダウンロードできず、 64bitか32bitか選択できる項目も存在せず、ダウンロードしたら32bitでした https://portableapps.com/apps/graphics_pictures/irfanview_portable IrfanViewでPortable版の64bitは何処でダウンロードできますでしょうか?

  • 画像表示について

    画像を表示させたいのですがうまくいきません。 途中まで打ってみたのでご意見お願いします。 (リソースから読み込んで表示させる方法) 環境:MicrosoftVisualC++ SDK ******省略********* case WM_PAINT:   hdc = BeginPaint(hWnd,&ps);   //ビットマップリソースハンドルの取得   hBmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1));   if(hBmp == NULL){     MessageBox(hWnd,"ファイルの読み込みに失敗しました。","エラー",MB_ICONWARNING | MB_OK);     exit(1);   }   //ビットマップの大きさの情報取得   GetObject(hBmp,(int)sizeof(BITMAP),&bmp_info);   w = bmp_info.bmWidth;   h = bmp_info.bmHeight;   hdc_mem = CreateCompatibleDC(hdc);   SelectObject(hdc_mem,hBmp);   BitBlt(hdc,0,0,w,h,hdc_mem,0,0,SRCCOPY);   DeleteDC(hdc_mem);   DeleteObject(hBmp);   EndPaint(hWnd,&ps);   break; ******リソース(img.rc)****** // // Bitmap // IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" #ifdef APSTUDIO_INVOKED

  • 24bit画像の画像編集での劣化について

    色空間のウィキペディアの説明に 24bitでは画像編集の過程で劣化が無視できないため、48bit(各色16bit)などより多ビットで扱うことがある という表記があります。 http://ja.wikipedia.org/wiki/%E8%89%B2%E7%A9%BA%E9%96%93 これを読んで、画像編集の過程とはどんな作業を言うのかという疑問が起こり以下のような質問をしました。 http://qa.itmedia.co.jp/qa7896553.html 得た回答は ソフトに画像を貼り付けトリミングや、画像の貼り付けを行っただけでも、 jpegは周辺情報を元に画像を構成するため、周辺情報が変化すれば編集部分以外も変化シ劣化するということでした。 ここでは、JPEGについての回答は得ましたが、24bitPNGや24bitTiffでの場合はどうなるのでしょうか

  • アクセス(2003)のVBAでビット演算方法

    エクセルのマクロではビット演算ができましたが、アクセスではどのような方法があるのでしょうか? where in 文で値の自動生成も考えられますが、VBやVCでアドインも可能でしょうか教えてください。 '*********** Excel VBA Bit 演算 ************ Private Sub Boln() Dim MyBln As Boolean Dim Object1 As Range Dim Object2 As Range Set Object1 = Range("B11") Set Object2 = Range("B12") MyBln = Object1 And Object2 MsgBox MyBln End Sub '*********** Excel VBA Bit 演算 ************ 以上、宜しくお願いします。

  • bitmapクラスをiconクラスに変換する方法

    bitmapクラスをiconクラスに変換する方法 bitmapクラスをiconクラスに変換する方法 今、画像変換ソフトをVisual Basic 2010 Express Editionで作っているのですがbitmapクラスをiconクラスに変換する方法が分かりません。 GetHiconを使って変換する方法を試してみたのですがアイコンが16色になってしまい画像が変わってしまいます。 変換ソフトで使用するBitmapをIconに変換する関数を作ったのですが変換するところで止まっています。 Public Function convert_to_ico(ByVal image As Bitmap) As Icon Dim loadimage As Bitmap = New Bitmap(16, 16, PixelFormat.Format24bppRgb) Dim draw As Graphics = Graphics.FromImage(loadimage) draw.DrawImage(image, 0, 0) Dim returnico As Icon Return returnico End Function 申し訳ありませんが、宜しくお願いします。

  • VB2005 でビットの深さ8の画像を処理したい。

    VB2005を使って簡単な画像処理のツールを制作しています。 処理内容は、画像ファイル(jpg)を読み込み、画像を縦に区切って 左側と右側を別のファイルに保存する、という処理です。 縦に区切る位置(x 座標)は、自由に指定できます。 上記のような処理を「任意の解像度(0~300 dpi)、ビットの深さ 8 」 の画像で行うには、どのようにしたらよいのでしょうか。 (ビットの深さ 8 の image からは Graphics オブジェクトを  作ることができず、そのため、読み込んだ画像の解像度を  保てませんでした。) ビットの深さが 24 の画像は、以下のようにして問題なく動きました。 "scanfile01.jpg" は、 解像度 300dpi / ビットの深さ 24 / 縦1500 × 横1200 ピクセル の画像ファイルです。 --------------- private sub splitImage()  '画像(src)の読み込み  Dim fs As New IO.FileStream("scanfile01.jpg", _     IO.FileMode.Open)  Dim src As Image = Image.FromStream(fs, False, False)  Dim srcG As Graphics = Graphics.FromImage(src) '解像度の取得用  'src を分割する位置(x座標)  '(横幅1500 の scanfile01.jpg を左右半分に分ける)  Dim cutx As Integer = 750   'src の左側を格納する Bitmap を新規作成  '(src の解像度を引き継ぐ)  Dim destLeft As Image = New Bitmap(cutx, src.Height, srcG)  Dim rect As New Rectangle(0, 0, cutx, src.Height)  Dim destLeftG As Graphics = Graphics.FromImage(destLeft)  Dim rect As New Rectangle(0, 0, cutx, src.Height)  destLeftG.DrawImage(src, 0, 0, rect, GraphicsUnit.Pixel)  'src の左側をファイルに保存  destLeft.Save("scanfile01-left.jpg" _         , System.Drawing.Imaging.ImageFormat.Jpeg)  destLeft.Dispose()  destLeftG.Dispose()  'src の右側を格納する Bitmap を新規作成  ~省略~  srcG.Dispose()  src.Dispose()  fs.Dispose() End Sub ---------------- ビットの深さ 8 の画像を読み込むと、実行時に  Dim srcG As Graphics = Graphics.FromImage(src) '解像度の取得用 の部分で「インデックス付きのピクセルから Graphics オブジェクトを作成できません」というエラーが発生します。 そこで、解像度は引き継がずに、以下のように変更してみました。 ・srcG の定義文を削除 ・destLeft の定義時に解像度は指定せず、以下のように変更   Dim destLeft As Image = New Bitmap(cutx, src.Height) すると、エラーは発生せずファイルが作成されましたが、 解像度が引き継がれずに元の画像よりずっと小さな画像になって 作成されていました。 (作成されたファイルを開くと、イメージが小さくなった分、  黒い隙間ができていました。) 300 dpi の画像を読み込んだので、VB2005 で作成される?Bitmap のデフォルトの解像度 96 dpi に変換される際にピクセル抜けが 発生して画像が小さくなったのだと思います。 ビットの深さ 8 の画像を半分に区切ってファイルに保存する方法は ないのでしょうか。また、任意の解像度でピクセル抜けが 発生しないようにしたいです。

  • 8bit(256色)グレースケール画像の保存

    32bitのRGB画像ではなく、8bitのグレースケール画像を保存したいと考えています。 保存形式は、tiffとbmpのどちらでも構いません。 ですが、以下のような方法では、 アルファチャンネルを含んだ32bitのRGB画像が保存されてしまいます。 (作成中のプログラムの一例)    Dim img As Bitmap    Dim x As Integer    Dim y As Integer    img = New Bitmap(256, 50)    For x = 0 To 255       For y = 0 To 49          img.SetPixel(x, y, Color.FromArgb(x, x, x))       Next    Next    img.Save("gradation.tif", System.Drawing.Imaging.ImageFormat.Tiff) なお、一例として単純なグラデーション画像を保存していますが、 あくまでも一例であり、グラデーション画像を作成することが目的ではありません。 最終的には、VisualBasicのBitmapクラスで作成したbitmap画像を Photoshopで、8bitのグレースケール画像として開けることが理想です。 どうか、アドバイスをよろしくお願い致しますm(__)m

専門家に質問してみよう