DOBON.NET DOBON.NETプログラミング掲示板過去ログ

画像の縮小保存

環境/言語:[XP C#(VS7) .NetFramework1.0]
分類:[.NET]

はじめまして投稿質問致します。
サンプルを活用させていただき、HighQualityBicubicを用いて
縮小を行い指定画像拡張子で保存したいのです

Form上にdstPictureというPictureBoxを配置しています。
-----------------------------------------------------
dstPicture.Height = 100;
dstPicture.Width = 100;

Bitmap wkBmp = new Bitmap("読み込むファイル名");

Graphics g = dstPicture.CreateGraphics();

g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(wkBmp,0,0,dstPicture.Width,dstPicture.Height);

ここで
wkBmp.Save("出力ファイル名", "PNG");
としても セットした100x100のサイズで保存されずに最初のピクセルサイズで
保存されました。

Image stImg = wkBmp.GetThumbnailImage(dstPicture.Width,dstPicture.Height,null,IntPtr.Zero);
stImg.Save("出力ファイル名", "PNG");
wkBmp.Dispose();
g.Dispose();
stImg.Dispose();
とするとようやく100x100のサイズで保存されました。

--------------------------------------------------
補間方法を指定して画像を拡大、縮小表示する の中に
'画像を縮小表示
g.DrawImage(image, 0, 0, 150, 120)
と記載されているこの行を実行する事により
HighQualityBicubicで補間を取りながら縮小されるのだと
解していましたが、私の間違いなのでしょうか?
現にGetThumbnailImageを行わないと縮小できなかったですから。

ご指南宜しくお願いします。
  • 題名: Re[1]: 画像の縮小保存
  • 著者: ぱる
  • 日時: 2005/05/26 19:15:49
  • ID: 10963
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No10961に返信(いくみさんの記事)
> はじめまして投稿質問致します。
> サンプルを活用させていただき、HighQualityBicubicを用いて
> 縮小を行い指定画像拡張子で保存したいのです
>
> Form上にdstPictureというPictureBoxを配置しています。
> -----------------------------------------------------
> dstPicture.Height = 100;
> dstPicture.Width = 100;
>
> Bitmap wkBmp = new Bitmap("読み込むファイル名");
>
> Graphics g = dstPicture.CreateGraphics();
>
> g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
> g.DrawImage(wkBmp,0,0,dstPicture.Width,dstPicture.Height);
>
> ここで
> wkBmp.Save("出力ファイル名", "PNG");
> としても セットした100x100のサイズで保存されずに最初のピクセルサイズで
> 保存されました。
>
> Image stImg = wkBmp.GetThumbnailImage(dstPicture.Width,dstPicture.Height,null,IntPtr.Zero);
> stImg.Save("出力ファイル名", "PNG");
> wkBmp.Dispose();
> g.Dispose();
> stImg.Dispose();
> とするとようやく100x100のサイズで保存されました。
>
> --------------------------------------------------
> 補間方法を指定して画像を拡大、縮小表示する の中に
> '画像を縮小表示
> g.DrawImage(image, 0, 0, 150, 120)
> と記載されているこの行を実行する事により
> HighQualityBicubicで補間を取りながら縮小されるのだと
> 解していましたが、私の間違いなのでしょうか?
> 現にGetThumbnailImageを行わないと縮小できなかったですから。
>
> ご指南宜しくお願いします。
>


こんばんは。

この辺の記事が参考になるでしょうか。
http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html
2005/05/26(Thu) 19:38:34 編集(投稿者)

> HighQualityBicubicで補間を取りながら縮小されるのだと
> 解していましたが、私の間違いなのでしょうか?
> 現にGetThumbnailImageを行わないと縮小できなかったですから。

 何か誤解されているような‥‥(^_^;)


> Image stImg = wkBmp.GetThumbnailImage(dstPicture.Width,dstPicture.Height,null,IntPtr.Zero);
> stImg.Save("出力ファイル名", "PNG");

 こちらの処理ではサムネールとしてサイズ指定したイメージを stImg に取得し、それを保存しています。

> Graphics g = dstPicture.CreateGraphics();
> g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
> g.DrawImage(wkBmp,0,0,dstPicture.Width,dstPicture.Height);

 一方、こちらは wkBmp の内容を PictureBox にサイズ指定して描画しているコードです。 wkBmp の自体に変化はないのですから
> wkBmp.Save("出力ファイル名", "PNG");
しても縮小されたりはしないでしょう。


 Graphics オブジェクトの取得方法を見直してみては如何でしょうか? 以下の Tips など参考になるかと思います。

画像を動的に作成する
http://dobon.net/vb/dotnet/graphics/createimage.html



(追記)
#あ、なるほど。確かにそっちのほうかも。< No10963
レスありがとうございます。

PictureBoxのImageプロパティに関するよくある勘違い

まさにこの通りだというのは理解出来ました。

Graphic オブジェクトにHighQualityBicubicを設定して
drowした結果は Graphicオブジェクト上にしかないという
事は分かりましたが、この結果をファイルに保存するという
手法が分からなくて悩んでおります。

画像を動的に作成する/画像ファイルを表示する
のサンプルと併用して3時間ほど理解しようとしていますが
うまく出来ません。

私が目標としてることは
1.ファイルからjpgを読み込む
2.HighQualityBicubicを使用して任意のサイズに縮める
3.結果をpngで保存する
というテストプログラムを作成して理解を深めようとしています。

PictureBoxから生成したGraphics objectは別物だという事は
PictureBoxのImageプロパティに関するよくある勘違い
を読んで分かりました。

上記のことを実現するにはPictureBoxを使用しなくても
可能ではないのかと考えています。
ファイルからGraphic objectに対して読み込み
加工して保存すれば良いのだと考えています。

ご指南宜しくお願いします。
■No10973に返信(いくみさんの記事)
> Graphic オブジェクトにHighQualityBicubicを設定して
> drowした結果は Graphicオブジェクト上にしかないという
> 事は分かりましたが、この結果をファイルに保存するという
> 手法が分からなくて悩んでおります。
PictureBoxの Graphicで描いたものを保存しようとしているから
できないのです。


> 私が目標としてることは
> 1.ファイルからjpgを読み込む
> 2.HighQualityBicubicを使用して任意のサイズに縮める
> 3.結果をpngで保存する
> というテストプログラムを作成して理解を深めようとしています。
>
> 上記のことを実現するにはPictureBoxを使用しなくても
> 可能ではないのかと考えています。
> ファイルからGraphic objectに対して読み込み
> 加工して保存すれば良いのだと考えています。
その通りですね。
ヒントとして、PictureBoxではなくもう1つの Bitmapオブジェクトを
作成することで置き換えてみてください。
> ヒントとして、PictureBoxではなくもう1つの Bitmapオブジェクトを
> 作成することで置き換えてみてください。

Image srcImg = Image.FromFile("読み込みファイル");
Image dstImg = Image.FromFile("読み込みファイル");

Graphics dstg = Graphics.FromImage(dstImg);
dstg.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
dstg.DrawImage(srcImg,0,0,100,100);
dstImg.Save("保存ファイル",System.Drawing.Imaging.ImageFormat.Png);

もう一つ作ってみましたが、やはり失敗の様でした。
これですとdstgには描いているけれどもdsgImgには描いていないという
PictureBoxのImageプロパティに関するよくある勘違い
と同じ失敗なのではないかなと思っています。

Graphic.Saveでは拡張子の指定が出来ません。
Image.Saveでは拡張子の指定が出来ます。
だから Graphicに描画したものをImageに戻さなければ
ならないのか?と考えていますが筋違いなのでしょうか?

PictureBox.Imageから生成したGraphicObjectの描画が反映されない
というのはGraphicのhelpにあるデバイスコンテキストが別物である
という説明から納得したつもりなのですが、上記の様な
コードを書こうとしてる所から私は何を根本的に間違った解釈を
しているのかという箇所が分からない状態です。
宜しくお願いします。
>もう1つの Bitmapオブジェクトを
>作成することで置き換えてみてください。
とのアドバイスから Bitmapを2つ使ったら出来ました _oz

Bitmap srcBmp = new Bitmap("読み込みファイル");
Bitmap dstBmp = new Bitmap(100,100);
Graphics dstg = Graphics.FromImage(dstBmp);

dstg.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
dstg.DrawImage(srcBmp,0,0,100,100);
dstBmp.Save("保存ファイル", System.Drawing.Imaging.ImageFormat.Png );

前述の
Image srcImg = Image.FromFile("読み込みファイル");
としている Imageはイコール PictureBox.Imageに同じく
Imageクラスであり、Imageクラスを元にして生成したGraphicsに
対して描画しても保存(反映)はできませんよということでしょうか?

///////////////////////////////////////////////////////////
「PictureBoxのImageプロパティに関するよくある勘違い」
///////////////////////////////////////////////////////////
に書かれている
「Graphicsオブジェクトに何を描画しようが、それがPictureBoxのImageプロパティに反映されることはありません。この2つの方法は全く別の方法であり、基本的に併用すべきではありません」
という文章に繋がるのではないかと考えます。

なのにサンプルでは
---------------------------------------------------------
//300x300の大きさのイメージをImageプロパティに設定する
PictureBox1.Image = new Bitmap(300, 300);
---------------------------------------------------------
と書かれていたりしてる為(?_?)
多分目で見える状態にするのに必要だからかな。

かなり変な日本語になっているとは思いますが
私の解釈で正しいのでしょうか?
御指摘お願いします。
.NET TIPS
画像を高品質に拡大/縮小するには?

http://www.atmarkit.co.jp/fdotnet/dotnettips/023resize/resize.html

こちらの資料を参考にしました。  
■No10983に返信(いくみさんの記事)
> 前述の
> Image srcImg = Image.FromFile("読み込みファイル");
> としている Imageはイコール PictureBox.Imageに同じく
> Imageクラスであり、Imageクラスを元にして生成したGraphicsに
> 対して描画しても保存(反映)はできませんよということでしょうか?

違います。

> Graphics g = dstPicture.CreateGraphics();
> g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
> g.DrawImage(wkBmp,0,0,dstPicture.Width,dstPicture.Height);
この例では、PictureBoxの Graphicsに対して描画を行っています。
このままではファイルに保存できません。

> Bitmap dstBmp = new Bitmap(100,100);
> Graphics dstg = Graphics.FromImage(dstBmp);
> dstg.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
> dstg.DrawImage(srcBmp,0,0,100,100);
> dstBmp.Save("保存ファイル", System.Drawing.Imaging.ImageFormat.Png );
ここでは、Bitmapオブジェクトの Graphicsに対して描画を行っています。
ですからそのまま Save()メソッドが使えます。

Imageクラスを元にして生成したGraphicsに対して描画しても保存できない
ということではなくて、どのオブジェクトの Graphicsに対して描画したか
です。
> ここでは、Bitmapオブジェクトの Graphicsに対して描画を行っています。
> ですからそのまま Save()メソッドが使えます。

この2行が私の悩んでいた事でした。
PictureBox.Imageから生成したGraphicsでsaveにファイル名が指定できない。
Bipmapから生成したGraphicsではsaveでファイル名が指定できる。

という事で理解できました。

>> Imageクラスであり、Imageクラスを元にして生成したGraphicsに
>> 対して描画しても保存(反映)はできませんよということでしょうか?
>違います。
この件に関しましては srcとdstで同じファイルを読み込んでいました。
dstに縮小して出力しても元の絵に縮小絵を貼り付けても
元のサイズが残っていますから大きなサイズでファイルに保存されている
のを勘違いしていました。

◆まとめ◆

× PictureBox.Image
○ Bipmap
○ Image

各々を元にそたGraphicsでsaveする時
PictureBox.Imageを元にした場合は
描画(加工)した結果をファイルに保存できない。

これで解決できたと思っております。
御指摘ありましたらお願いします。
■No10988に返信(いくみさんの記事)
> PictureBox.Imageから生成したGraphicsでsaveにファイル名が指定できない。
> Bipmapから生成したGraphicsではsaveでファイル名が指定できる。
> という事で理解できました。

どうも、Graphics オブジェクトと Image/Bitmap オブジェクトとの混同があ
るみたいですし、途中から PictureBox と PictureBox.Image がすりかわって
いますよね。

Graphics オブジェクトは「画家」です。Image/Bitmap/PictureBox オブジェ
クトは「キャンバス」です。画家は与えられたキャンバスに向かって絵を描き
ます。キャンバスには、Image/Bitmap オブジェクトのように自身に描かれて
いる内容をファイルに保存できるものもありますし、PictureBox オブジェク
トのように保存できないものもあります。

Graphics.Save メソッドは、画家の状態を保存するものです。キャンバスとは
関係ありません。画家の状態というのは、例えば、「全てのモノを時計まわり
に 90 度傾けて描く」といったものです。90 度傾ける、線を描く、Save、さ
らに 10 度傾ける、線を描く、Restore (= 90 度の傾きに戻す)、線を描く、
というように使います。

PictureBox と PictureBox.Image の意味するものの違いは、いいですよね。
おはようございます。
御指摘ありがとうございます。

>途中から PictureBox と PictureBox.Image がすりかわっていますよね。
すみません、あちらこちらと書き方が不味かった様です。
ImageとPictureBox.Imageは置き換えた例として(別物として)
載せてしまいましたがPictureBoxとPictureBox.Imageのすり替えと
指摘されてる部分が思い当たりません。

Image/Bitmap オブジェクトのように自身に描かれて
> いる内容をファイルに保存できるものもありますし、PictureBox オブジェク
> トのように保存できないものもあります。
はい、この点で行き詰まっていました。
この部分は明快になりました。

画家とキャンパスの関係は現在の認識と違いがなかったので
大丈夫だと思います。

> Graphics.Save メソッドは、画家の状態を保存するものです。キャンバスとは
> 関係ありません。画家の状態というのは、例えば、「全てのモノを時計まわり
> に 90 度傾けて描く」といったものです。90 度傾ける、線を描く、Save、さ
> らに 10 度傾ける、線を描く、Restore (= 90 度の傾きに戻す)、線を描く、
> というように使います。
詳細な例で理解出来ました。ありがとうございます。

> PictureBox と PictureBox.Image の意味するものの違いは、いいですよね。
PictureBoxは簡易に画像を表示する為のクラスで
PictureBox.Imageはそのプロパティであり、PictureBoxを元にして
Graphicsで描画してもPictureBox.Imageプロパティには反映されない。
反映されない理由までは分かっておりません。

認識違い等ありましたら、御指摘お願いします。
  • 題名: Re[10]: 画像の縮小保存
  • 著者: いくみ
  • 日時: 2005/05/31 0:12:51
  • ID: 11020
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
皆さん、親切に教えてくださり有難うございました。
解決済み!
■No11005に返信(いくみさんの記事)
> ImageとPictureBox.Imageは置き換えた例として(別物として)
> 載せてしまいましたがPictureBoxとPictureBox.Imageのすり替えと
> 指摘されてる部分が思い当たりません。

言葉の選択がよくなかったかもしれません。書き間違えていますよね? くらい
の意味です。直接的には No10988 のまとめを指しています。表や後段の記述
にある PictureBox.Image を PictureBox に読み替えると何となく正しい記述
になるからです。

裏を返すと、No10988 のまとめはおかしいんです。PictureBox.Image を元に
した Graphics オブジェクトとは、Image オブジェクトの Graphics オブジェ
クトです。ですから、描画した結果をファイルに保存できますよね。
解決済み!
  • 題名: Re[11]: 画像の縮小保存
  • 著者: いくみ
  • 日時: 2005/05/31 14:20:17
  • ID: 11035
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
> PictureBox.Image を元にした Graphics オブジェクトとは
>Image オブジェクトの Graphics オブジェクトです。
>ですから、描画した結果をファイルに保存できますよね。

御指摘の通り PictureBox.Imageでも Imageでも ImageObjectである
事には変わりありませんから ファイルに保存できます。
御指摘ありがとうございます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板