
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 の画像を半分に区切ってファイルに保存する方法は
ないのでしょうか。また、任意の解像度でピクセル抜けが
発生しないようにしたいです。
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+汎用エラーが発生するようです ・・・
redfox63 様
ご教授いただき感謝致します。
ANo.1 の通り作成した Bitmap オブジェクトに解像度を指定し、
ANo.2 の通り、Bitmap オブジェクトへの描画の際に
描画するイメージの座標とサイズを指定したところ、
意図した通りの大きさ・解像度による描画及び
ファイルへの書き込みができました。
描画先の新しい Bitmap オブジェクトに解像度を指定する方法、
また、解像度を指定した Bitmap オブジェクトに描画する際の
スケーリングの指定方法について、とても勉強になりました。
有り難うございました。
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を変更してイメージが期待通りなのか確認してください
御回答有り難うございます。
ご教授いただいた通り、プロパティを設定して試してみたところ、
解像度 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が見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- Excel(エクセル) EXCELのグラフを画像(JPG形式)で保存、通常実行がうまく行かない。ステップインはうまく行く 3 2022/08/30 12:06
- Excel(エクセル) エクセル VBA For Next 繰り返しの書き方を教えてください 6 2022/09/01 14:11
- Visual Basic(VBA) 【VBA】写真の縦横比を変えずに貼り付ける 5 2023/06/13 11:42
- Visual Basic(VBA) VBAが止まります。 2 2022/09/02 14:02
- HTML・CSS CSSが効かずどのように指定すれば良いか分からないのでアドバイスお願い致します 2 2023/06/07 12:25
- HTML・CSS 【HTML】【CSS】【Swiper】 元の画像は横1200×縦600なのですが、実際のサイト上に反 5 2022/07/16 13:57
- Excel(エクセル) 【マクロ】スクショ印刷がうまく動かない件 5 2022/12/06 17:37
- JavaScript clear機能を失わずにファイルアップロード機能を作成したい 3 2023/06/10 16:12
- HTML・CSS ブロックエディターで作りつつ、画像を挿入しつつ、画像にスタイルシートのコードを付ける方法はありますか 1 2022/08/23 18:46
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
始めに読み込む画像を固定して...
-
ロールオーバーをどのように実...
-
小さなウィンドウ
-
bxsliderにて読み込み後に内容...
-
jQuery版のlightbox.jsについて...
-
文字列をクリックすると文字の...
-
VB2005 でビットの深さ8の画像...
-
Ajax LightBoxを使用したサムネ...
-
ヘアスタイルをサイト内で絞り...
-
複数の画像を先に読み込ませ表...
-
Ajaxから画像ファイルへのリク...
-
jQueryスライドショー画像への...
-
javascriptで画像移動時に表示...
-
1枚の画像をクリックすると複数...
-
画像を切り替えランダム表示
-
javaを使ってマウスオンでの画...
-
代替文字が表示されなくなった...
-
今日の日付のみ表示して1つの画...
-
javascriptで画像の切り替え
-
マウスオーバー
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
1枚の画像をクリックすると複数...
-
画像の重なりの順序を代える方...
-
textareaに画像を表示したい
-
Gifアニメ、最後のコマに行った...
-
透過pngの透明部分以外をクリッ...
-
1枚の画像をクリックして複数の...
-
ステータスバーについて
-
JavaScript スライドの画像にリ...
-
マウス追従スクリプトについて
-
画面の表示位置を指定させて表...
-
Javascriptで指定した日付と時...
-
プルダウンの位置がwin/macでず...
-
jQueryで特定のURLの時のみ表示
-
オンマウスで、画像切り替え+...
-
バナー広告のように表示させた...
-
ランダム表示に加えwidthをブラ...
-
JavaScriptとチェックボックス...
-
ホォルダの読む込み
-
jQuery bxSlider 画像に変更
-
画像にロールオーバーするとメ...
おすすめ情報