9246


簡単な計算ができません。  
画像が複数枚あります。それぞれ1MBを超えるランダムのサイズです。  
それを全てダウンロードまではできたんですが、指定したファイルサイズに圧縮できません。よろしく居お願いします。  
計算部分はこれです。fi.Lengthは元のファイルサイズです。

[code]

    long imgsize = (20L/fi.Length);
    
[/code]

また、できればへんてこなソースコードを改良していただきたいです。

[code]

    ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
    EncoderParameters myEncoderParameters = new EncoderParameters(1);
    
    
    WebClient wc = new WebClient();
    try
    {
        for (int i = 0; i < lines.Length; i++)
        {
            wc.DownloadFile(lines[i], dirName + "\\" + (i + 1) + ".jpg");
    
            Bitmap bmp1 = new Bitmap(@"C:\download\"+now+"\\"+(i+1)+".jpg");
            System.IO.FileInfo fi=new System.IO.FileInfo(@"C:\download\" + now + "\\" + (i + 1) + ".jpg");
            long imgsize = (20L/fi.Length);
            EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, imgsize);
            myEncoderParameters.Param[0] = myEncoderParameter;
            bmp1.Save(@"C:\download\"+now+"\\resized\\"+(i+1)+"s.jpg", jgpEncoder, myEncoderParameters);
    
        }
        balloon = lines.Length + "枚の画像を保存しました";
    }
    catch (WebException exc)
    {
        Console.WriteLine(exc.Message + "\r\n");
        balloon = "エラーが発生しました";
    }
    
[/code]


CC BY-SA 3.0
2015-04-17T02:03:18.103
9242
2015-04-17T09:16:19.387
9184
question
c#
C#でWEB上の画像をダウンロードし20kbまで圧縮させたいです。


> 指定したファイルサイズに圧縮できません。

まず一般論として、JPEGによる静止画像圧縮では、目標出力サイズを指定して圧縮するのは困難です。

JPEG圧縮の原理的には、映像品質を決める一つの値(Q値)しか制御するパラメータが存在しません。このパラメータを用いて、サイズが小さいが映像が汚い／サイズが大きいが映像は綺麗のトレードオフから選択します。

`EncoderParameter`に指定する[`Encoder.Quality`フィールド](https://msdn.microsoft.com/ja-
jp/library/system.drawing.imaging.encoder.quality.aspx)では、「出力品質」を値0～100で指定できるだけで、それ以上の細かい制御はできません。

一つの解法として、出力ファイルサイズが目標サイズを下回るまで、`Encoder.Quality`フィールドの値を下げながら（画質を下げながら）何度もエンコードしてみるという手はあります。

* * *

`Encoder.Quality`フィールドの説明は上記のとおりですから、質問にある実装コードは論理的に誤っています。`20L/fi.Length`で算出される値に妥当性がありません。

[code]

    System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
    long imgsize = (20L/fi.Length);
    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, imgsize);
    
[/code]

**追記**  
`Quality`の指定は値0-100ですが、これは百分率(%)のような直観的なパラメータではありません。残念ながら、指定値を半分にしたからサイズが半分になり品質が半分になる、というものではありません。

`Quality`値と出力サイズの関係は、下記サイトの情報が参考になるかと思います。ただし、対象とする画像の種類で結構かわりますから、あくまで目安としてみて下さい。  
<http://www.ipentec.com/document/document.aspx?page=csharp-save-image-to-jpeg>


CC BY-SA 3.0
2015-04-17T03:22:08.743
9246
2015-04-17T08:57:42.747
2015-04-17T08:57:42.747
49
49
9242
answer


自己解決しました。yohjpさんの言うとおり、ループにしなければできませんでした。  
無理やりループで完成しました。

[code]

    long ex = 80L;
    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, ex);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmpSrcHalf.Save(@"C:\OKADA\download\" + now + "\\resized\\" + (i + 1) + "ss.jpg", jgpEncoder, myEncoderParameters);
    
    System.IO.FileInfo fic = new System.IO.FileInfo(@"C:\OKADA\download\" + now + "\\resized\\" + (i + 1) + "ss.jpg");
    
    while (fic.Length > 160000)
    {
        myEncoderParameter = new EncoderParameter(myEncoder, (ex=ex-3));
        myEncoderParameters.Param[0] = myEncoderParameter;
        bmpSrcHalf.Save(@"C:\OKADA\download\" + now + "\\resized\\" + (i + 1) + "ss.jpg", jgpEncoder, myEncoderParameters);
        fic = new System.IO.FileInfo(@"C:\OKADA\download\" + now + "\\resized\\" + (i + 1) + "ss.jpg");
    }
    
[/code]


CC BY-SA 3.0
2015-04-17T07:48:20.080
9258
2015-04-17T09:16:19.387
2015-04-17T09:16:19.387
9184
9184
9242
answer