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

[ 最新記事及び返信フォームをトピックトップへ ]

■35316 / inTopicNo.1)  PictureBoxの画像を連続保存
  
□投稿者/ ま〜 一般人(38回)-(2023/01/10(Tue) 19:41:27)
  • アイコン環境/言語:[VS2022 VB] 
    分類:[.NET] 

    こんばんわ
    また困った事がありましてお教え願います
    15個のPictureBoxの画像をグルグル回してファイルに落としたいのですが
    どうも上手くできないのです。
    ファイル保存の方は問題なく出来ると思うのですが
    PictureBoxからイメージを取ってきて受け渡しをどう考えれば宜しいでしょうか?
    宜しくお願いしまうす

マルチポストを報告
違反を報告
引用返信 削除キー/
■35317 / inTopicNo.2)  Re[1]: PictureBoxの画像を連続保存
□投稿者/ 魔界の仮面弁士 大御所(1512回)-(2023/01/10(Tue) 20:23:47)
  • アイコンNo35316に返信(ま〜さんの記事)
    > 15個のPictureBoxの画像をグルグル回してファイルに落としたいのですが
    画像を回転させるということですか?
    画像を切り替えるということですか?

    https://dobon.net/vb/dotnet/graphics/rotateflip.html
    https://dobon.net/vb/dotnet/graphics/pictureboximage.html
    https://dobon.net/vb/dotnet/graphics/selectactiveframe.html


    > どうも上手くできないのです。
    今はどういう方法を試していて、どういう結果になっているのでしょうか?


    > ファイル保存の方は問題なく出来ると思うのですが
    思うだけで、まだ保存はできていないという事でしょうか。


    > PictureBoxからイメージを取ってきて受け渡しをどう考えれば宜しいでしょうか?
    「取ってきて」という言葉が、具体的に何を指しているのか曖昧ですが、
    とりあえずこの辺りを読んでみるとか…。
    https://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html
違反を報告
引用返信 削除キー/
■35318 / inTopicNo.3)  Re[2]: PictureBoxの画像を連続保存
□投稿者/ ま〜 一般人(39回)-(2023/01/11(Wed) 13:59:21)
  • アイコンいつもありがとうございます。

    >>ファイル保存の方は問題なく出来ると思うのですが
    > 思うだけで、まだ保存はできていないという事でしょうか。


    すみません
    説明不足でした。15個の PictureBoxに作画してる内容(画像)を15個ファイルに保存したいが目的です


    2つのPictureBoxに作画した状態で
    直前に作画を実行したPictureBoxにしか保存できない。1歩手前に作画したPictureBoxはエラーとなってしまします
    2個とも作画済みが条件で
    下記のコードで PictureBox1を再作画した後でSaveをするとPictureBox1は保存できる。PictureBox2はエラーとなります
    PictureBox2を再作画した後だとPictureBox1を保存するとエラーとなります

    PictureBox1.Image.Save(PicturePath + "MojiGAZou1.Png", System.Drawing.Imaging.ImageFormat.Png)
    PictureBox2.Image.Save(PicturePath + "MojiGAZou2.Png", System.Drawing.Imaging.ImageFormat.Png)

    エラー内容は下記通りです

    System.ArgumentException
    HResult=0x80070057
    Message=使用されたパラメーターが有効ではありません。
    Source=System.Drawing
    スタック トレース:
    at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
    at System.Drawing.Image.Save(String filename, ImageFormat format)
    at 勉強.文字編集Form.Button10_Click(Object sender, EventArgs e) in C:\Users\userMM\OneDrive\ソフト\勉強\文字編集Form.vb:line 736
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    at 勉強.My.MyApplication.Main(String[] Args) in :line 83

    以上、宜しくお願いします


違反を報告
引用返信 削除キー/
■35319 / inTopicNo.4)  Re[3]: PictureBoxの画像を連続保存
□投稿者/ 魔界の仮面弁士 大御所(1514回)-(2023/01/11(Wed) 14:06:02)
  • アイコン2023/01/11(Wed) 14:08:40 編集(投稿者)

    No35318に返信(ま〜さんの記事)
    > PictureBox1.Image.Save(PicturePath + "MojiGAZou1.Png", System.Drawing.Imaging.ImageFormat.Png)
    > PictureBox2.Image.Save(PicturePath + "MojiGAZou2.Png", System.Drawing.Imaging.ImageFormat.Png)

    画像未設定の場合、Image プロパティは Nothing を返します。
    また、表示した画像が Png 保存できる形式でない場合も失敗しますし、
    保存先のファイルパスに出力できない場合もエラーとなるでしょう。


    > System.ArgumentException
    > HResult=0x80070057
    > Message=使用されたパラメーターが有効ではありません。
    > Source=System.Drawing

    Image が Nothing というわけでは無かったものの、
    ImageFormat.Png で保存できない画像形式だったようですね。
    (実際に試してはいないので、想像で答えていますが)


    現在の画像の RawFormat は何になっていますか?
    https://dobon.net/vb/dotnet/graphics/imagerawformat.html

    あとは、割り当てた画像が Dispose() されてしまっていないか、とか…。
違反を報告
引用返信 削除キー/
■35320 / inTopicNo.5)  Re[4]: PictureBoxの画像を連続保存
□投稿者/ ま〜 一般人(40回)-(2023/01/11(Wed) 16:06:00)
  • アイコンありがとうございます。
    画像は
    https://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=one&namber=35282&type=35270&space=120&no=0
    で生成した画像です

    色々やってる中でPngで試したのを書いてしまいましたが画像形式はbmpです
    bmpに戻しましたが結果は同じで最後に作画した画像なら問題なく保存できます

    > あとは、割り当てた画像が Dispose() されてしまっていないか、とか…。


    多分原因はこれですね。本当にすごい方ですね
    ただ。PictureBox1も2も.Disposeはしておらず

    探した所先のURLの
    If PictureBox1.Image IsNot Nothing Then
    PictureBox1.Image.Dispose()
    End If

    実際は上記を参考に下記の様に書き開けてます
    Dim Rbox() As Global.System.Windows.Forms.RichTextBox =
    {RichTextBox1, RichTextBox2, RichTextBox3, RichTextBox4, RichTextBox5}
    Dim bmp = CreateBitmapFromControl(Rbox(PageNo))
    If PictureBox16.Image IsNot Nothing Then
    ' PictureBox16.Image.Dispose()
    End If
    PictureBox16.Image = bmp
    'ピクチャ1−15へ各個転送
    Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, ・・・・・PictureBox15}
    Picture(PageNo).Image = PictureBox16.Image

    しか無く上記を消した所問題は解消されたのですがメモリの消費が何かアクションをするたび少し増えていきます

    甘え序に何故こなるのか理解したいのですが教えて頂けないでしょうか?

    以上





違反を報告
引用返信 削除キー/
■35321 / inTopicNo.6)  Re[5]: PictureBoxの画像を連続保存
□投稿者/ ま〜 一般人(41回)-(2023/01/11(Wed) 16:49:17)
  • アイコン追加報告

    FormLOADに下記を記述して画像ファイルを読み込んおいて
    確認してみました所、トラブルが再燃しました。全く同じ現象でした。

    For i As Byte = 0 To 4
      Picture(i).Size = New Size(Picture(i).Size.Width, 320)
      Picture(i).Size = New Size(Picture(i).Size.Height, 160)
      Picture(i).SizeMode = PictureBoxSizeMode.Zoom
      Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" + CStr(i + 1) + ".bmp")
      Picture(i).Dispose()
    Next
違反を報告
引用返信 削除キー/
■35322 / inTopicNo.7)  Re[6]: PictureBoxの画像を連続保存
□投稿者/ 魔界の仮面弁士 大御所(1515回)-(2023/01/11(Wed) 17:36:00)
  • アイコン2023/01/11(Wed) 18:08:21 編集(投稿者)

    No35321に返信(ま〜さんの記事)
    > For i As Byte = 0 To 4
    >   Picture(i).Size = New Size(Picture(i).Size.Width, 320)
    >   Picture(i).Size = New Size(Picture(i).Size.Height, 160)
    >   Picture(i).SizeMode = PictureBoxSizeMode.Zoom
    >   Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" + CStr(i + 1) + ".bmp")
    >   Picture(i).Dispose()
    > Next

    変数 Picture の宣言が見当たりませんが、
    これは No35320 にある PictureBox 型の一次元配列でしょうか。

    最後に Dispose しているのは何故ですか?


    > Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" + CStr(i + 1) + ".bmp")

    VB で文字列連結する場合には、 + 演算子ではなく & 演算子を使う癖をつけた方が良いですよ。

    あるいは上記の処理を、補間文字列構文を使って書くこともできます。
     Picture(i).Image = Image.FromFile($"{PicturePath}MojiGAZou{i + 1}.bmp")
    こちらは、たとえば "MojiGAZou001.bmp" のように 3 桁数字にするために
     Picture(i).Image = Image.FromFile($"{PicturePath}MojiGAZou{i + 1:000}.bmp")
    などと書式指定にも使えるので便利かと。


    なお、画像の読み込みに Image.FromFile を使っておられますが、
    このメソッドは、画像ファイルをロックし続けることになりますのでご注意を。
    状況によっては FromStream を使った方が良いかもしれません。
    https://dobon.net/vb/dotnet/graphics/drawpicture2.html


    No35320に返信(ま〜さんの記事)
    > ただ。PictureBox1も2も.Disposeはしておらず

    流石に、Form 上に貼ってある PictureBox コントロールそのものを
    Dispose したりするとは思っていないのですが、心配していたのは
    「PictureBox の Image プロパティから参照されている最中の画像」を
    誤って Dispose しているのではないか…という点です。

    要は『誰かが使っている最中のオブジェクトを勝手に処分してはいけません』、と。


    > 探した所先のURLの
    > If PictureBox1.Image IsNot Nothing Then
    > PictureBox1.Image.Dispose()
    > End If

    いやいや。元の URL には、その直後に
     「PictureBox1.Image = bmp」
    と書いてあったはずですよ?


    プロパティから参照されているオブジェクトを
    勝手に Dispose するのはとてもマズイことです。

    たとえば下記は、表示中の画像を Dispose する実験コードです。

    Public Class Form1
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      PictureBox1.Image = Me.Icon.ToBitmap()
     End Sub

     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
      PictureBox1.Image.Dispose()
     End Sub
    End Class


    ボタンを押しただけでは PictureBox1 の見た目は変わりません。
    しかし、そのあとでフォームを最小化して復元するなどして、
    画像の再描画処理が発生すると、Disposed 状態のオブジェクトにアクセスされることになり、
     『System.ArgumentException: '使用されたパラメーターが有効ではありません。'』
    の例外を誘発する結果になってしまいます。


    割り当てた画像を解放したいのであれば、上記の Button1 の処理を
     Dim oldImage = PictureBox1.Image
     PictureBox1.Image = Nothing
     oldImage?.Dispose()
    もしくは
     Using PictureBox1.Image
      PictureBox1.Image = Nothing
     End Using
    のようにします。これならば、ArgumentException の問題は発生しません。

    あるいはせめて、処分した直後にただちに参照を差し替えるようにして
    Disposed 状態のオブジェクトが参照され続けないようにします。
    No35282 の KOZ さんの実装パターンに相当しますね。

     PictureBox1.Image?.Dispose() '処分
     PictureBox1.Image = Nothing '解放


    なお、この手の Dispose 処理を組み込むにあたっては、
     PictureBox16.Image = bmp
     PictureBox1.Image = bmp
    のような処理が行われていないことが大前提です。
    (同一の画像インスタンスが、複数の PictureBox から参照されているかどうか、ということ)

    上記の場合は、一つの画像が複数の PictureBox から参照されている状態です。
    もしもこの状態で、「bmp.Dispose()」あるいは「PictureBox16.Image.Dispose()」が呼ばれると、
    PictureBox1.Image も当然 Disposed 状態となり、ArgumentException 問題を引き起こします。

    もちろん、
     PictureBox16.Image = otherImage
     PictureBox1.Image = PictureBox1.ErrorImage
     bmp.Dispose()
    などのように、元々参照されていたインスタンスが
    どの PictureBox からも参照されていない状態に差し替えた後ならば、
    Dispose しても安全です。

    もしくは、同一の画像インタンスを共有するのではなく、
     PictureBox1.Image = DirectCast(bmp.Clone(), Image)
    のように、同じ画像の別インスタンスを代入するということもできます。
    これならば、それぞれの PictureBox ごとに、個別に Dipose できます。

    ただし Clone した分だけ、リソース消費が増えてしまう点がデメリットです。

    いずれにせよ、Dispose を呼び出す場合には、そのインスタンスが
    「どこからも使われない状態」を保証してから行うべきである、と言えます。


    > 実際は上記を参考に下記の様に書き開けてます
    > Dim Rbox() As Global.System.Windows.Forms.RichTextBox =
    > {RichTextBox1, RichTextBox2, RichTextBox3, RichTextBox4, RichTextBox5}
    繰り返し使うのであれば、フィールド変数にしておいた方が良いかも。

    Public Class Form1
     Private Rbox As RichTextBox()
     Private Picture As PictureBox ()
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      Rbox = {RichTextBox1, RichTextBox2, RichTextBox3, RichTextBox4, RichTextBox5}
      Picture = {PictureBox1, PictureBox2, PictureBox3, …, PictureBox15}
     End Sub
    End Class
違反を報告
引用返信 削除キー/
■35323 / inTopicNo.8)  Re[7]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(42回)-(2023/01/12(Thu) 14:13:11)
  • アイコンいつもありがとうございます
    フィールド変数の件は棚ぼたです。出来ないと思ってました。助かります。

    本題ですが先のコードでわDisposeした方が良いのか程度で書いてました
    Form LoadでDisposeしてますがボタンクリックでTextBoxから画像を生成して各PictureBoxに書いてますので問題ないと解釈していました
    今二つの問題に当たっています。スレッドを分けなかったのは同じ要因かなと思ってです。

    流れ RichTextBoxへ文字入力 ⇒生成⇒ PictureBox16 ⇒サイズを変えてコピー⇒ 各PictureBox ⇒ すべてのPictureBoxの画像をファイル保存


    ――――――――ボタン@――――――――ー
    Dim bmp = CreateBitmapFromControl(Rbox(PageNo))
    If PictureBox16.Image IsNot Nothing Then
      PictureBox16.Image.Dispose()
    End If

    ‘P PageNo←どのPictureBoxを操作するか
    PictureBox16.Image = bmp ← 自動生成されたイメージが入っている
    ‘ピクチャ1−15へ各個転送
    Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, ・・・・・PictureBox15} 
    Picture(PageNo).Image = PictureBox16.Image

    これは同じ画像を各PictureBoxへ書いたと同じ扱いになりますか?一旦PictureBox16経由で各PictureBoxへ作画されています
    これがやっては駄目な事でしょうか?

    最後の書いたPictureBoxをBで保存する事は出来ました。
    それ以外のPictureBox以外でBのコードを実行するエラーとなる

    ―――――――Bエラーになる箇所――――――――――
    Picture(PageNo).Image.Save(PicturePath"MojiGAZou1.bmp",System.Drawing.Imaging.ImageFormat.Bmp)


    Imageは使わない方がよいのでしょうか?

    ―――――――――ボタンA――――――――――――
    試してみました

    Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5}
    For i As Byte = 0 To 4
    Picture(i).Size = New Size(Picture(i).Size.Width, 320)
    Picture(i).Size = New Size(Picture(i).Size.Height, 160)
    Picture(i).SizeMode = PictureBoxSizeMode.Zoom
    Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" & CStr(i + 1) & ".bmp")
    Next

    Me.PictureBox1.Image.Save(PicturePath + "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox2.Image.Save(PicturePath + "MojiGAZou2.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox3.Image.Save(PicturePath + "MojiGAZou3.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox4.Image.Save(PicturePath + "MojiGAZou4.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    Me.PictureBox5.Image.Save(PicturePath + "MojiGAZou5.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    これもPictureBox1.のSaveの所でエラーとなります。こんな事は出来ない?

    以下はエラーの内容です

    System.Runtime.InteropServices.ExternalException
    HResult=0x80004005
    Message=GDI+ で汎用エラーが発生しました。
    Source=System.Drawing
    スタック トレース:
    at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
    at System.Drawing.Image.Save(String filename, ImageFormat format)
    at Test.文字編集Form.Button18_Click(Object sender, EventArgs e) in C:\Users\userMM\OneDrive\Test\文字編集Form.vb:line 232
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    at Test.My.MyApplication.Main(String[] Args) in :line 83


    Disposeする必要は無いので何か良い方法はありますか?

    あと

    >No35282 の KOZ さんの実装パターンに相当しますね。
    >
    > PictureBox1.Image?.Dispose() '処分
    > PictureBox1.Image = Nothing '解放

    とありますがこれはどの様な意味ですか?

    以上、長々とすみません

違反を報告
引用返信 削除キー/
■35324 / inTopicNo.9)  Re[8]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ 魔界の仮面弁士 大御所(1516回)-(2023/01/12(Thu) 16:00:58)
  • アイコンNo35323に返信(ま〜さんの記事)
    > 本題ですが先のコードでわDisposeした方が良いのか程度で書いてました
    でわ→では


    > If PictureBox16.Image IsNot Nothing Then
    >   PictureBox16.Image.Dispose()
    > End If
    上記は『PictureBox16.Image?.Dispose()』の一行で書けます。
    https://learn.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/null-conditional-operators

    そして、Disposed 状態のオブジェクトを参照し続けた状態にするのは問題があるため、
    PictureBox16.Image には直ちに、Nothing (あるいは別の画像)を代入しなおさねばなりません。

    ただし本来は、別の画像(あるいはNothing)を割り当ててから元の画像を Dispose した方が望ましいです。


    > PictureBox16.Image = bmp ← 自動生成されたイメージが入っている
    > Picture(PageNo).Image = PictureBox16.Image
    > これは同じ画像を各PictureBoxへ書いたと同じ扱いになりますか?

    一つの画像を複数の PictureBox から参照している状態になりますね。


    つまり、一枚の絵画を複数人で同時に鑑賞している状態に相当します。
    ということは、その絵画を破損させれば、他の閲覧者も破損した絵画を見ることになってしまいます。
    もしも閲覧者A が、自身が見ている絵画を破棄したとすれば、
    それは閲覧者B や C が見ている絵画も捨てられたことを意味します。

    Picture(0).Image を Dispose() した場合、
    Picture(1).Image も破棄されるので、ArgumentException 等になってしまう所以です。


    しかしあらかじめ、一枚の元絵を人数分複製しておき、それを閲覧させるようにすれば、
    元絵を破損させたとしても、各閲覧者の見ている画像が見えなくなることはありません。

    これはすなわち、
     Picture(PageNo).Image = DirectCast(PictureBox16.Image?.Clone(), Image)
    のようにしておく、ということです。それぞれの画像は元絵の複製にすぎないわけですから、
    Picture(0).Image を Dispose() したとしても、
    Picture(1).Image や PictureBox16.Image には影響がありません。


    > 一旦PictureBox16経由で各PictureBoxへ作画されています
    > これがやっては駄目な事でしょうか?
    何を経由させても構いません。
    変数であろうと PictureBox16.Image であろうと大丈夫です。

    問題になっているのは、PictureBox16 を経由させたことではなく、
    「使用中のオブジェクトを Dispose したこと」です。


    Picture(0) がその画像を使わなくなったとしても、他の PictureBox が
    同じインスタンスを使用しているのなら、Dispose してはいけません。
    捨てるなら、「誰も使わなくなってから」にしましょう。



    > ―――――――Bエラーになる箇所――――――――――
    > Picture(PageNo).Image.Save(PicturePath"MojiGAZou1.bmp",System.Drawing.Imaging.ImageFormat.Bmp)
    そもそも文法違反になるでしょうね。(^_^;)


    > Imageは使わない方がよいのでしょうか?
    いいえ。「誰かが使用している最中の Image を勝手に Dispose してはいけない」というだけです。

    「使い終わった Image は Dispose しなければならない」ルールであるのは確かですが、
    「私が使い終わったので、他の人が使っていたとしても勝手に捨ててしまおう」はルール違反です。


    > Dim Picture() As PictureBox = {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5}
    > For i As Byte = 0 To 4
    配列のインデックスは常に Integer 型です。Byte 型ではありません。

    Byte/SByte/Short/UShort は Integer 型への暗黙変換が可能なのでエラーにはなりませんが、
    わざわざ Byte 型を経由させると、無駄な変換処理が増えることになってしまいます。

    そのため普通は As Byte とはせず、「For i = 0 To 4」もしくは「For i As Integer = 0 To 4」と書きます。


    > Picture(i).Size = New Size(Picture(i).Size.Width, 320)
    > Picture(i).Size = New Size(Picture(i).Size.Height, 160)

    これって、
     Picture(i).Width = Picture(i).Size.Width
     Picture(i).Height = 320
     Picture(i).Width = Picture(i).Size.Height
     Picture(i).Height = 160
    に相当する処理ですよね。何故こんなことを…?

    幅と高さを指定するだけならば、
     Picture(i).Size = New Size(320, 160)
    では駄目なのでしょうか。SizeMode 指定のために必要だったとか?

    > Picture(i).Image = Image.FromFile(PicturePath + "MojiGAZou" & CStr(i + 1) & ".bmp")
    前 1 つが「+ 演算子」で、
    後 2 つが「& 演算子」なのは何故ですか?


    > Me.PictureBox1.Image.Save(PicturePath + "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox2.Image.Save(PicturePath + "MojiGAZou2.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox3.Image.Save(PicturePath + "MojiGAZou3.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox4.Image.Save(PicturePath + "MojiGAZou4.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > Me.PictureBox5.Image.Save(PicturePath + "MojiGAZou5.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
    > これもPictureBox1.のSaveの所でエラーとなります。こんな事は出来ない?

    「Image が Dispose されていない」かつ「指定のパスに書き込みが可能」な状態にしておけば
    上記のコードでもエラーにはならないと思いますよ。

    仮に Dispose していなかったとしても、その画像が Image.FromFile で読み込まれていて、
    かつ、そのインスタンスがまだ破棄されていなかったとしたら、ファイルがロックされたままになるので
    また別のエラーを誘発する可能性がありますね。


    >> PictureBox1.Image?.Dispose() '処分
    >> PictureBox1.Image = Nothing '解放
    > とありますがこれはどの様な意味ですか?

    If PictureBox1.Image IsNot Nothing Then
     PictureBox1.Image.Dispose() '処分
    End If
    PictureBox1.Image = Nothing '解放

    という意味です。

    KOZ さんの書かれた No35282 の場合は、
     Dim bmp = CreateBitmapFromControl(RichTextBox1)
     If PictureBox1.Image IsNot Nothing Then
       PictureBox1.Image.Dispose()
     End If
     PictureBox1.Image = bmp
    ですね。

    いずれも、「bmp (または Nothing)を参照させる前に、以前の画像があれば Dispose する」という処理です。
    以前の画像を「処分してから解放」の順序になっているので、本当は「解放してから処分」の方が良いのですが。

    上記 No35282 のコードを「解放してから処分」にするのであれば
     Using PictureBox1.Image
      PictureBox1.Image = CreateBitmapFromControl(RichTextBox1)
     End Using
    または
     Dim oldImage = PictureBox1.Image
     PictureBox1.Image = CreateBitmapFromControl(RichTextBox1)
     oldImage?.Dispose()
    と書きます。自分は後者の方が好みですが、 No35282 のままでも問題はありません。
違反を報告
引用返信 削除キー/
■35330 / inTopicNo.10)  Re[9]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(44回)-(2023/01/16(Mon) 14:20:51)
  • アイコンいつもありがとうございます
    貴重なお時間割いて頂きご指導ありがとうございます
    今回も知らない事が多く大変勉強になりました
    最終目標はテキストから生成した画像を保存なので道のり長いですが宜しくお願いします

    テスト的にやって見た所。下記の2行目でエラーとなります。まさに沼です

      Me.PictureBox1.Image = Image.FromFile(PicturePath & "MojiGAZou1.bmp")
      Me.PictureBox1.Image.Save(PicturePath & "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    2行目をコメントアウトして確認した所、表示はされてるのでファイルとかの問題ではなさそうです。。
    何か基本的なのが抜けてる気がしてきました。読み込んだだけでは保存出来ないのでしょうか?


    ーーーーーーーーーエラーの内容-----
    System.Runtime.InteropServices.ExternalException
    HResult=0x80004005
    Message=GDI+ で汎用エラーが発生しました。
    Source=System.Drawing

    余談ですが「は」「わ」の件ですが私も違和感あったのですが最近の若者からのメールが
    「わ」使う子が多くいつの間にか私も影響受けてるみたいです。(笑)

    あと+と&は修正途中でした。。意味はありません
違反を報告
引用返信 削除キー/
■35331 / inTopicNo.11)  Re[10]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ 魔界の仮面弁士 大御所(1519回)-(2023/01/16(Mon) 16:14:25)
  • アイコン2023/01/16(Mon) 16:30:46 編集(投稿者)

    No35330に返信(ま〜さんの記事)
    > テスト的にやって見た所。下記の2行目でエラーとなります。まさに沼です
    >   Me.PictureBox1.Image = Image.FromFile(PicturePath & "MojiGAZou1.bmp")
    >   Me.PictureBox1.Image.Save(PicturePath & "MojiGAZou1.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

    先の No35322 で紹介した通り、 Image.FromFile がファイルをロックしているためです。


    '駄目な例1
    PictureBox1.Image = Image.FromFile(bmpFile)
    'System.Runtime.InteropServices.ExternalException: 'GDI+ で汎用エラーが発生しました。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な例2
    PictureBox1.Image = Image.FromFile(bmpFile)
    PictureBox1.Image.Dipose()
    'System.ArgumentException: '使用されたパラメーターが有効ではありません。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '★修正例★
    PictureBox1.Image = Image.FromStream(New MemoryStream(File.ReadAllBytes(bmpFile)))
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例1
    PictureBox1.Image = Image.FromStream(New MemoryStream(File.ReadAllBytes(bmpFile)))
    PictureBox1.Image.Dipose()
    'System.ArgumentException: '使用されたパラメーターが有効ではありません。'
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例2
    Using stm As New FileStream(bmpFile, FileMode.Open, FileAccess.Read)
     PictureBox1.Image = Image.FromStream(stm)
    End Using
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)


    '駄目な修正例3
    Using stm As New MemoryStream(File.ReadAllBytes(bmpFile))
     PictureBox1.Image = Image.FromStream(stm)
    End Using
    PictureBox1.Image.Save(bmpFile, System.Drawing.Imaging.ImageFormat.Bmp)



    追記:こういう手もあるかな。

    Using img = Image.FromFile(pngFile)
     PictureBox1.Image = New Bitmap(img)
    End Using
    PictureBox1.Image.Save(pngFile, System.Drawing.Imaging.ImageFormat.Bmp)

    上記は、 No8405 のスレッドの "中 博俊" さん( No8447 )の案です。
    >>> New Bitmap(bmp)
    >>> で、新しいBitmapにコピーされますよ。
    >>>
    >>> ただし全てがコピーされるわけじゃなくってDPIが保持されないとか、現在のページだけ(マルチページな画像の場合)とかやや違いはありますが。
違反を報告
引用返信 削除キー/
■35340 / inTopicNo.12)  Re[11]: 複数のPictureBox画像を複数のファイルへ保存したい
□投稿者/ ま〜 一般人(46回)-(2023/01/20(Fri) 12:55:32)
  • アイコン沢山のアドバイスありがとうございます
    またまた、勉強になりました。

    少しハマりながらもなんとか目的の事が出来ました。

    重ねてありがとうございます

    クローズします。

解決み!
違反を報告
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

Mode/  Pass/


- Child Tree -