JPEGで保存する(前回の続きです)


のん  2005-07-20 18:08:32  No: 123585

お世話になります。
以前(2005/07/13)、『画像ファイル保存時にサイズを小さくするには?』で
一度解決とさせて頂いたのですが、完全に解決できていなかったので、
もう一度質問させてください。

前回、回答していただいた中で、魔界の仮面弁士さんにJPEG保存の方法を教えて頂きました。
その通りに保存を行い、そのJPEGファイルを確認したところ、
編集される前の画像が保存されていました。

Dim MyFile1 As String  '初期画像のフルパス
Dim MyFile2 As String  '画像編集後の保存先フルパス
Dim iCnt    As Integer '画像の番号

Private Sub Form_Load()
  ①Call PreviewFile(MyFile1)  'Imageコントロールに画像の縦横比を計算して表示させるための関数
  ②Picture1.Picture = LoadPicture(MyFile1)
End Sub

Private Sub Image1_MouseUp(Button As ......)
  ③'//ここでPictureBoxコントロールに描画の処理

  ④MyFile2 = App.Path & "\Temp\TempF" & iCnt & ".jpg"
  ⑤SavePicture Picture1.Image, App.Path & MyFile2
  ⑥DoEvents
  ⑦Call PreviewFile(MyFile2)  'ここでImageコントロールに編集後の画像の縦横比を計算して、再表示させている
End Sub
という処理を行っていたのを、
⑤のSavePictureのところで、JPEGの保存をするために、
Dim Status As GDIPlusStatusConstants
    Status = SavePictureJpeg(Picture1.Picture, MyFile2, 70)
と書き直し、保存の処理を行ってみました。
すると、保存されたのは③で編集したPicture1の画像ではなく、
②で読み込んだ状態の画像のまま保存されていました。

以前解決としたのは、この問題を解決するために、
⑦のあとに⑧として、Picture1.Picture = LoadPicture(MyFile2)と記述し、
別にボタンを追加し、
そのボタンクリックのイベント(Command1_Click)でJPEG保存の処理をしたら
問題なくできたので、解決としてしまいました。
ですが、これはサンプルプログラムで作ったもので、
(しかも保存先のファイル名は全く別のものを指定)
実際の流れでプログラムを組んでみると、25000KBのJPGファイルが生成されていました。

①〜⑧のコード
DoEvents
Dim Status As GDIPlusStatusConstants
⑨Status = SavePictureJpeg(Picture1.Picture, MyFile2, 70)
DoEvents

その他、色々試したところ、
⑨で保存先を別の名前(新規)で保存したら、
600KB〜1000KBのファイルが生成されているのが確認できました。
どうも、MyFile2と同じ名前で25000KBのファイル名が存在していると、駄目な様です。
(600KB〜1000KBのファイルが存在していて上書きするとOKでした。)

一番実現したいのは、⑤でSavePictureではなく、
⑨のSavePictureJpeg(Picture1.Picture, MyFile2, 70)を行うことです。
(Picture1に実際に表示されている画像をそのまま保存)
それが出来ないのであれば、⑨でJPEGファイル(600KB〜1000KB)で
上書きすることです。

長文、乱筆申し訳ありません。
宜しくお願いします。


通りすが隣人  2005-07-20 19:47:10  No: 123586

○文字付数字は、機種依存文字なので
使用は控えるように・・・。

メール等でも同様ですが、注意されたことありませんか?


のん  2005-07-20 20:03:11  No: 123587

通りすが隣人さん

すいません。
半角カタカナは、使用しない方が良いとは
聞いたことがあったのですが、
○文字は知りませんでした。

以後気をつけます。


名無し  2005-07-20 21:24:06  No: 123588

いまどきその程度の文字が使えないマシンって・・・
半角カナは文字コードの特性上cgiに支障が出ることもあるがね

  #っと質問に関係ない話のみの投稿は禁止でしたかな

保存しようとしているファイルが存在しているかチェックし、あったら削除してから保存してみたら如何ですかね?


のん  2005-07-21 19:23:49  No: 123589

名無しさん。ありがとうございます。

>保存しようとしているファイルが存在しているかチェックし、あったら削除してから保存してみたら如何ですかね?

5番で保存しているファイルは、仮ファイルとして保存しており、
これは、3番で編集する度に新しい仮ファイルを生成し、
「戻る」や「進む」といった機能をつける為にこのような事をしています。

表示されている画像の処理が終わって、次の画像の処理に進む時や、別の処理に進む時は、ここで生成された仮ファイルは全て削除します。
(「保存」ボタンで編集した画像をDBに登録することができます。)

今回、質問させて頂いたのは、仮ファイルが大きすぎる為、
「戻る」や「進む」で画像を切り替える度に、少し時間がかかるのを何とかしたいのと、
できれば、大きなファイルを生成したり、削除したりというのをしたくないというのが理由です。

ですので、質問には「出来ないのであれば上書き」と書きましたが、
できれば先に大きなファイルで保存するというのを
回避する方法はないでしょうか。

ちなみに、先に削除するというのを確認してみましたが、
一応普通に操作すればできたのですが、
連続で早く操作すると、2つ目くらいまでは小さくできたのですが、
それ以降のものは大きなファイルで生成されてしまいました。
(Killで削除する前後にDoEventsを入れましたが駄目でした)

宜しくお願いします。


魔界の仮面弁士  2005-07-21 19:43:36  No: 123590

まずは、PictureプロパティとImageプロパティの意味の違いを理解しましょう。


のん  2005-07-22 00:12:48  No: 123591

魔界の仮面弁士さん。ありがとうございます。

HELP(ライブラリ)でみると、Pictureプロパティには
>デザイン時に Picture プロパティを使ってフォームにグラフィックスをロードした場合、そのグラフィックスはフォームと共に保管、ロードされます。

Imageプロパティには
>Image プロパティの値を、Picture プロパティに割り当てることができます。また、Image プロパティの値を、Windows API を呼び出すときに渡すこともできます
>AutoRedraw プロパティの設定によっては、グラフィックスのハンドルである Image プロパティが変更される場合があります。つまり、AutoRedraw プロパティが真 (True) のとき、オブジェクトの hDC プロパティは Image プロパティのグラフィックスを含むデバイス コンテキストへのハンドルになります。

とありました。
はっきりと理解できたわけではありませんが、
この部分を見て漠然としたイメージで
Status = SavePictureJpeg(Picture1.Picture, MyFile2, 70)

Status = SavePictureJpeg(Picture1.Image, MyFile2, 70)
と変更したら、僕の希望どおり、最初からJPEGファイルで保存できました。
魔界の仮面弁士さんの仰ったことはこうゆう事でよかったのでしょうか?

これで解決としたかったのですが、やはり連続して早く操作を行うと、
操作が重なってしまうことがあります。
例えば、本来であれば2本線を引いたら1本ずつ線を引くたびに保存するのですが
連続して早く線を引くと、途中から、2本の線が描画されて保存されたりします。

これを回避するために、DoEventsと入れてたのですが、これではだめでした。
できれば、一つの処理が終わるまで操作(MouseUpイベント)不可にするという処理は避けたいのですが、
連続で操作をしても、全ての処理を確実に行っていく方法はないのでしょうか?

続けての質問で申し訳ありません。
宜しくお願い致します。


特攻隊長まるるう  2005-07-25 21:13:46  No: 123592

>連続して早く線を引くと、途中から、2本の線が描画されて保存されたりします。
>これを回避するために、DoEventsと入れてたのですが、これではだめでした。
ここは DoEvents すると寧ろ不具合となる場所のように思いますが、どういう
考えで入れていたのでしょうか?。…適当に入れてたのなら話になりません。
>途中から
という事は処理がぶつかって不整合が起こっているようですが、通常の処理では
   Status = SavePictureJpeg(Picture1.Image, MyFile2, 70)
の戻り値が得られるまで次の処理は行われないのでは?…だとすればマルチスレッド
を使っているという事でしょうか?…説明されてないので分かりませんが。
マルチスレッドであれば処理の不整合への対策は必須で、それはプログラムに
応じて考えるものですから、マニュアル的な回答はありません。強いて言うなら
『不整合が起こらないようにして下さい』です。

1つ参考になるかもしれない概念として
[キュー (queue)]
http://www.atmarkit.co.jp/icd/root/43/67542643.html

変数などに処理を一時格納しておいて、順に取り出すような仕組みを
考えられれば進展するかもしれません。ただし、無限に時間のズレが発生
し続ける処理は良くないでしょう。どこかで整合を取るような結果になる
と思います。…となると
>できれば、一つの処理が終わるまで操作(MouseUpイベント)不可にするという処理は避けたいのですが、
これも1つの方法。実力と相談する事も必要です。


通ってみた  2005-07-26 04:01:41  No: 123593

ファイルがどうこう以前の問題であれなんですが・・・機能的にUndoを実装させたいのだと思うんだけど、それならファイルに保存させるのは如何なものかと
PictureBox(もしくはImage)に退避させておく方が処理も断然はやいと思うのだがどう?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加