- 締切済み
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 の画像を半分に区切ってファイルに保存する方法は ないのでしょうか。また、任意の解像度でピクセル抜けが 発生しないようにしたいです。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- redfox63
- ベストアンサー率71% (1325/1856)
今回のように PropertyItemで解像度変更した場合 Dim destLeftG As Graphics = Graphics.FromImage(destLeft) Dim rect As New Rectangle(0, 0, 750, src.Height) destLeftG.DrawImage(src, rect, rect, GraphicsUnit.Pixel) といった具合で ソースの範囲と描画の範囲を設定してやれば縮小されないと思います これは描画する際には96dpiのまま描画し、保存後の画像が300dpiだと設定されているためなのかも ・・・ 0) ソースのJpgを読み込み 1) 96dpiのBitmapオブジェクトを作成 2) ソースのJpgファイルからPropertyItemを取得 3) 2)の内容を 300DPIに変更 4) 1)に3)を追加、Y軸も同様に追加 5) 4)よりGraphicsを生成 この時点では 5)も4) 96dpi 6) 5)に対して 0)の描画 96dpiのGraphicsに300dpiで描画するため縮小されてしまう なのではと考えられます 3)と4)の間で destLeftをSave/Loadをすれば destLeftG.DrawImage(src, rect, 0, 0, GraphicsUnit.Pixel) でも縮小されませんが、最後にもう一度描画後のイメージをSaveする際にGDI+汎用エラーが発生するようです ・・・
- redfox63
- ベストアンサー率71% (1325/1856)
24ビットイメージの処理の中でPropertyItemによってDPIの指定をした場合のイメージはご希望のものになるのでしょうか Dim destLeftG As Graphics = Graphics.FromImage(destLeft) の手前で dim prop as PropertyItem = src.PropertyItems(0) prop.Id = &h11a ' PropertyTagXResolution prop.Type = 5 prop.Len = 8 ' 300dot / 1Inch なので ' 300 mod 256 , 1, 0, 0 と 1, 0, 0, 0 のペアを登録 prop.Value = new Byte(){44,1,0,0,1,0,0,0} destLeft.SetPropertyItem( prop ) prop.Id = &h11b ' PropertyTagYResolution destLeft.SetPropertyItem( prop ) といった具合で DPIを変更してイメージが期待通りなのか確認してください
お礼
御回答有り難うございます。 ご教授いただいた通り、プロパティを設定して試してみたところ、 解像度 300 dpi の画像ファイルを作成することができました。 とても勉強になりました。有り難うございました。 ただ、今回は何がいけないのか、作成されたイメージが 小さくなってしまい、その周りは黒い隙間で埋められていました。 具体的には、 "scanfile.jpg" (解像度 300dpi / ビットの深さ 8 / 縦800 × 横1500 ピクセル) を読み込み、横幅 750 で区切った左側の画像を "scanfile-Left.jpg" として保存しました。 ご教授いただいたようにプロパティを設定できたお陰で "scanfile-Left.jpg" は、 (解像度 300dpi / ビットの深さ 24 / 縦800 × 横750 ピクセル) として作成できたのですが、そのイメージを開いてみたところ、 元の画像 "scanfile.jpg" の左半分が、小さくなって隅っこ (左上の位置)に描かれており、その右下の部分は黒で塗りつぶされた 状態になっておりました。 ご教授いただいた通り prop を作成し、 destLeft の X 方向の解像度/ Y 方向の解像度を元の画像 src と同じように設定した後、 Dim destLeftG As Graphics = Graphics.FromImage(destLeft) Dim rect As New Rectangle(0, 0, 750, src.Height) destLeftG.DrawImage(src, 0, 0, rect, GraphicsUnit.Pixel) として描いたところ、destLeft の左上隅に小さく src の左半分 が描かれている状態となってしまいました。 同じ解像度間で描き写しているのに、描かれるイメージの大きさが変わってしまうことってあるのでしょうか。
お礼
redfox63 様 ご教授いただき感謝致します。 ANo.1 の通り作成した Bitmap オブジェクトに解像度を指定し、 ANo.2 の通り、Bitmap オブジェクトへの描画の際に 描画するイメージの座標とサイズを指定したところ、 意図した通りの大きさ・解像度による描画及び ファイルへの書き込みができました。 描画先の新しい Bitmap オブジェクトに解像度を指定する方法、 また、解像度を指定した Bitmap オブジェクトに描画する際の スケーリングの指定方法について、とても勉強になりました。 有り難うございました。