• 締切済み

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 の画像を半分に区切ってファイルに保存する方法は ないのでしょうか。また、任意の解像度でピクセル抜けが 発生しないようにしたいです。

  • Xingb
  • お礼率66% (2/3)

みんなの回答

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

今回のように 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+汎用エラーが発生するようです ・・・

Xingb
質問者

お礼

redfox63 様 ご教授いただき感謝致します。 ANo.1 の通り作成した Bitmap オブジェクトに解像度を指定し、 ANo.2 の通り、Bitmap オブジェクトへの描画の際に 描画するイメージの座標とサイズを指定したところ、 意図した通りの大きさ・解像度による描画及び ファイルへの書き込みができました。 描画先の新しい Bitmap オブジェクトに解像度を指定する方法、 また、解像度を指定した Bitmap オブジェクトに描画する際の スケーリングの指定方法について、とても勉強になりました。 有り難うございました。

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

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を変更してイメージが期待通りなのか確認してください

Xingb
質問者

お礼

御回答有り難うございます。 ご教授いただいた通り、プロパティを設定して試してみたところ、 解像度 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 の左半分 が描かれている状態となってしまいました。 同じ解像度間で描き写しているのに、描かれるイメージの大きさが変わってしまうことってあるのでしょうか。

関連するQ&A

  • 動的に画像を作成し保存するには?

    Visual Basic 2012を使用しています。 下記プログラムを実行するとエラーが表示されてしまいます。 Dim img As New Bitmap(200, 100) Dim g As Graphics = Graphics.FromImage(img) g.FillRectangle(Brushes.Black, g.VisibleClipBounds) g.Dispose() PictureBox1.Image = img img.Save("E:\EPUB_test\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg) img.Dispose() 表示されるエラーは下記です。 型 'System.ArgumentException' のハンドルされていない例外が System.Drawing.dll で発生しました どこが間違っているのでしょうか? 正しく動作させるにはどこを修正すべきかをお教え下さい。

  • (VB.net)画像の一部を切り取って,拡大・縮小したい

    内容を見ていただき,ありがとうございます。 タイトルのままですが,PictureBoxに画像を出して,その一部を切り取ったうえで拡大・縮小させるプログラムを作成しています。 今のところ,画像の一部を切り出すことはできたのですが,これを拡大・縮小させる方法をご存じないでしょうか。画像の一部を切り出すソースは以下のとおりです。 まず,フォームにピクチャボックス(PictureBox1)とコマンドボタン(Button1)を配置し,ソリューションを置いているフォルダ内のbinフォルダにWinter.jpg(WinXPのマイピクチャに入っているものです)を入れておきます。次に,Button1のコードとして,以下のものを打ち込みました。 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'Bitmapオブジェクトの作成(切り取り元画像の指定) Dim bmap = New Bitmap("winter.jpg") '切り取る範囲をRectanleで指定 Dim rect As New Rectangle(10, 20, 100, 200) 'PictureBox1のGraphicsオブジェクトの作成 Dim g As Graphics = PictureBox1.CreateGraphics() '元の画像の指定部分を切り取ってPictureboxの左上隅(x,y = 0,0)に表示する.単位はピクセル. g.DrawImage(bmap, 0, 0, rect, GraphicsUnit.Pixel) 'Graphicsオブジェクトを破棄 g.Dispose() End Sub 以上です。 おそらく,DrawImageの部分を変えればいけるのではないかと思われるのですが,いかがでしょうか。ご助言よろしくお願いいたします。

  • 画像に関する知識がなさ過ぎて困っています!!

    おはようございます(;O;) 今ある画像が解像度300かどうか確認したいのですが、 どうやったらわかるか教えてください。 画像のプロパティのイメージのところを見ると、 大きさ 3000×4000 幅 3000ピクセル 高さ 4000ピクセル 水平方向の解像度 180dpi 垂直方向の解像度 180dpi ビットの深さ 24 解像度の単位 2 などと書いてあります。 これは解像度は180の画像だと判断してもいいのでしょうか??? だとしたら、解像度300の画像に変えるにはどうしたらいいのでしょうか?? 初心者なので なるべく簡単な言葉で回答よろしくお願いします(:_;) それと、とても急いでいるので、勝手ですがなるべく早く回答していただけたら嬉しいです! どうかよろしくお願いします!!!

  • VB2005での画像処理

    各ピクセルの色情報を取得し,そのままコピーするプログラムです. 同じ大きさのPictureBox1とPictureBox2,それとButton1があります. エラーや警告は出ませんが,Button1をクリックしてもまったく動きません. 最終的にはPictureBox1を画像処理してPictureBox2に結果を表示させたいのですが,そのままコピーも出来ないため原因を探しています. A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) ではだめなのでしょうか.ご教授ください. -----以下プログラム------ Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim i As Integer Dim j As Integer Dim A As Integer Dim picture1 As New Bitmap(PictureBox1.Image) Dim picture2 As New Bitmap(PictureBox2.Image) For j = 0 To PictureBox1.Width - 1 For i = 0 To PictureBox1.Height - 1 A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) Next Next End Sub

  • VB.NETのグラフィック描画で困っています

    VB.NETでのグラフィックの記述方法ですが 何かをクリックすると描画させるのではなく 単にあるsubプロシージャ内でグラフィックを描画させる記述する方法として pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) を教えていただきました。そこで private sub xy_keisan() '座標を計算させるプロシージャ disp_x() 'x座標に目盛りを表示させるプロシージャ disp_Y() 'xの目盛り数によってY座標の位置を変えて表示させるプロシージャ end sub private sub disp_x() pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) g.DrawLine(****** end sub private sub disp_y() pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) g.DrawLine(****** end sub のような記述(引数とか細かい所は端折っています)ですとdisp_yは描画されていますが,disp_xは消えてしまいます。 pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) が消えてしまう原因だとおもって宣言場所を変えてみましたが同じです 逆にこれが無いと描画させることが出来なくなります。 これの意味も今ひとつ判りません よろしくお願い致します

  • VB.netでのPictuerBoxに描写した内容の保存について。

    VB.netでのPictuerBoxに描写した内容の保存について。 PictureBoxに描写した内容を保存してみると、描写した項目事態は正しく保存されているのですが、背景が真っ黒になってしまいますこれは、なぜなのでしょうか? ソースは以下の様な感じです。 Dim bmp As Bitmap Dim g As Graphics bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height) PictureBox1.Image = bmp g = Graphics.FromImage(PictureBox1.Image) g.DrawLine(Pens.AliceBlue, 0, 10, 20, 10) PictureBox1.Refresh() PictureBox1.Image.Save("test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg) どなたかわかる方よろしくお願いいたします。

  • ■解像度の低い画像(72dpi-180dpi)をカラー印刷したい

    ■解像度の低い画像(72dpi-180dpi)をカラー印刷したい お世話になります。 主にWeb用に撮影されたjpg画像を使って 紙用カタログを作ることになりました。 印刷屋さんには画像解像度は300dpiあることが好ましいと言われたのですが、 果たして72dpiの画像(ピクセル数も少ない)を敢えて300dpiに保存し直すことに意味はあるのでしょうか。 ネットで調べても、意味はない派と、photoshopが足りないピクセルを足してくれるのでやはり解像度は上げた方がよい派に意見が分かれているようです。 ピクセル数が十分にある画像なら解像度を上げる意味もある気はするのですが、 ピクセル数が足りない(例:本来300dpiで3x4cmの仕上がりにしたいのに、 72dpiで3x4cm分の大きさしかない、またはそれにすら満たない) 場合に意味があるのでしょうか。 それから、使うjpg画像はRGBになっているのですが、これもやはりIndesignに貼る前に Photoshop上でCMYKに変えた方がよいでしょうか。 作業環境は Mac OS10.6, CS4 印刷はオフセットではなく、デジタル印刷です。 ご意見お待ちしております。

  • 画像サイズ(プリント)、ファイルサイズで分からないことがあります

    どうしても、理解できないことがあったので書き込みさせていただきました。 http://www.tokachimicro.co.jp/graphics-3.html の「解像度と画像サイズ」の蘭についてを参考にさせていただいたのですが、理解ができません。Macなら72dpi、winなら96dpiと画面上のピクセル数が固定されているなら、ピクセルの一つあたりの大きさは変化はせず、画像サイズを大きくするのだったらより鮮明な画像になるのではないのでしょうか?なぜ、画像が大きくなると劣化するのでしょうか。また、72と固定されている解像度は変えられないのでは? 全く理解ができません。どなたか分かりやすく説明していただけますか?? また、同じHPの「解像度とファイルサイズ」ついても理解ができません… 知識を貸してください

  • 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 申し訳ありませんが、宜しくお願いします。

  • 手持ちの画像が荒れずに印刷出来るか心配です。

    A6サイズの紙に、手持ちの画像を印刷したいと思っています。 印刷はオンラインの印刷会社に入稿する予定です。 画像データはjpgで、500 x 500pixel(72dpi)です。 指輪の画像なので、なるべく綺麗に印刷したいのですが 元の大きさがA6サイズに対して伸ばさなくても足りているのか心配です。 500 x 500pixel(72dpi)はミリ単位に直すと→176.39mm×176.39mm(72dpi)になると思うのですが A6サイズは105mm×148mmなので大きさは足りているので、画像を引き伸ばす必要は無いと思うのですが 考え方としてはあっていますか? オンラインの印刷会社(プリント○ック等)では画像解像度は350dpi(dpi=dots / inch)以上を推奨しているとあるので 解像度に関しては画像を一旦フォトショップで、解像度を72dpi→350dpiぐらいにあげれば問題ないのでしょうか? 印刷について初心者なため、よろしくお願い致します。

専門家に質問してみよう