2011-01-21 3 views
7

画像の解像度を変更するために呼び出される関数に従っています。私はこれをやりたいので、たとえば300dpiのアップロードされた画像は72dpi(ウェブ用)に変更されます。この質問は、ここでは私が取り組んでいるところでanother questionに関連しています。アップロードされた画像のC#変更dpi

私は、この機能を新しいファイルをアップロードするときだけでなく、アプリケーション内の他の場所でも使用できる拡張メソッドを作成しています。 (上記の質問を参照してください)

上記の拡張メソッドは、以下のような関数で呼び出されています。

if (newSize.Width > originalImage.Width && newSize.Height > originalImage.Height) 
{ 
    newSize.Width = originalImage.Width; 
    newSize.Height = originalImage.Height; 

    uploadedFileBuffer = uploadedFileBuffer.SetDpiTo72(uploadedFile.ContentType, newSize); 

    return CreateFile(newSize, uploadedFile, uploadedFileBuffer); 
} 

bytearrayは、bytearrayとしてファイルされています。既にサイズは正しいですが、解像度を72dpiに変更したいのですが。ただし、画像を保存して保存した後、解像度は元の解像度(300dpi)になります。これどうやってするの?いくつもの答えAFTER

UPDATE:

public static byte[] SetDpiTo72(this byte[] imageToFit, string mimeType, Size newSize) 
     { 
      using (MemoryStream memoryStream = new MemoryStream(), newMemoryStream = new MemoryStream()) 
      { 
       memoryStream.Write(imageToFit, 0, imageToFit.Length); 
       var originalImage = new Bitmap(memoryStream); 

       using (var canvas = Graphics.FromImage(originalImage)) 
       { 
        canvas.SmoothingMode = SmoothingMode.AntiAlias; 
        canvas.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        canvas.PixelOffsetMode = PixelOffsetMode.HighQuality; 
        canvas.DrawImage((Image)originalImage,0,0, newSize.Width, newSize.Height); 

        originalImage.SetResolution(72, 72); 

        var epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75); 
        var epParameters = new EncoderParameters(1); 
        epParameters.Param[0] = epQuality; 

        Image newimg = Image.FromStream(memoryStream); 

        //Getting an GDI+ exception after the execution of this line. 
        newimg.Save("C:\\test1234.jpg", ImageFunctions.GetEncoderInfo(mimeType), epParameters); 

        originalImage.Save("test.jpg", ImageFormat.Jpeg); 

        //This line give me an Argumentexception - Parameter is not valid. 
        //originalImage.Save(newMemoryStream, ImageFunctions.GetEncoderInfo(mimeType), epParameters); 
        //newMemoryStream.Close(); 
       } 
       return newMemoryStream.ToArray(); 
      } 
     } 

例外が付属していますstackstraceは私に次のように語っています。

at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) 
    at Extensions.ByteArrayExtensions.SetDpiTo72(Byte[] imageToFit, String mimeType, Size newSize) in C:\Website\Project\Extensions\ByteArrayExtensions.cs:line 356 
    at CMS.Presentation.FileFunctions.CreateFullsizeImage(HttpPostedFileBase uploadedFile, Size newSize, Byte[] uploadedFileBuffer) in C:\Website\Project\CMS.Presentation\FileFunctions.cs:line 197 
    at CMS.Presentation.FileFunctions.CreateFile(HttpPostedFileBase uploadedFile, INodeService nodeservice, Guid userId, Node parentNode) in C:\Website\Project\CMS.Presentation\FileFunctions.cs:line 53 

私はまた、ビットマップのサイズを変更する別の機能(下記参照)を開発しました。そして、これは正しく動作するようです。私は現在の実装でこの関数を使用することはできませんが、Bitmapだけを返すためです。または、ビットマップを使用するためにすべてを変更する必要がありますか?

+1

あなたは素晴らしい環状コードを知っていますか? newBitmap = originalImageはコピーではありません。同じImageへの参照のみ。その面白い方法はまだ動作することができます。 – Euphoric

+0

ハハハッハッハ!変更されました;-) – Rob

+0

Wait ..あなたの問題を実際に解決しましたか? – Euphoric

答えて

3

私はしばらくの間、問題を発見しました。 私が使用したResizeImage関数に問題がありました。具体的には、 'GetThumbnailImage'にあります。 GetThumbnailImageは、作成されたThumbNailを目的のサイズに伸ばしてしまうため、説明できなかったぼやけた画像で別の問題が発生しました。サムネイルの解像度は決して変わりません。私はそれをレンダリングする前に新しいイメージを再描画するGraphics.drawImageをを使用して問題を解決することができたの下に機能するために、上記の機能を変更することにより

private static Bitmap ResizeImage(Image image, int width, int height) 
     { 
      var frameCount = image.GetFrameCount(new FrameDimension(image.FrameDimensionsList[0])); 
      var newDimensions = ImageFunctions.GenerateImageDimensions(image.Width, image.Height, width, height); 
      Bitmap resizedImage; 

      if (frameCount > 1) 
      { 
       //we have a animated GIF 
       resizedImage = ResizeAnimatedGifImage(image, width, height); 
      } 
      else 
      { 
       resizedImage = (Bitmap)image.GetThumbnailImage(newDimensions.Width, newDimensions.Height, null, IntPtr.Zero); 
      } 

      resizedImage.SetResolution(72,72); 

      return resizedImage; 
     } 

。また、GenerateImageDimensionsもわずかに修正されました。これをまとめると、問題は解決されました。

private static Bitmap ResizeImage(Image image, int width, int height) 
     { 
      var frameCount = image.GetFrameCount(new FrameDimension(image.FrameDimensionsList[0])); 
      var newDimensions = ImageFunctions.GenerateImageDimensions(image.Width, image.Height, width, height); 

      var resizedImage = new Bitmap(newDimensions.Width, newDimensions.Height); 
      if (frameCount > 1) 
      { 
       //we have a animated GIF 
       resizedImage = ResizeAnimatedGifImage(image, width, height); 
      } 
      else 
      { 

       //we have a normal image 
       using (var gfx = Graphics.FromImage(resizedImage)) 
       { 
        gfx.SmoothingMode = SmoothingMode.HighQuality; 
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; 
        gfx.PixelOffsetMode = PixelOffsetMode.HighQuality; 

        var targRectangle = new Rectangle(0, 0, newDimensions.Width, newDimensions.Height); 
        var srcRectangle = new Rectangle(0, 0, image.Width, image.Height); 

        gfx.DrawImage(image, targRectangle, srcRectangle, GraphicsUnit.Pixel); 
       } 
      } 

      return resizedImage; 
     } 
1

「解像度を変更する」とは、イメージのピクセル数を72/300に減らしたいということですか?私。 4000x3000の画像を960x720に変更しますか?

もしそうなら、私はあなたのコードが実際にそれをしているのか分かりません。 overload of DrawImage() you're usingはこれを行います。

指定されたイメージを、元の物理サイズを使用して、座標ペアで指定された位置に描画します。

これはまさに起きていることです。

one of the other overloadsなどthis oneとして試してみてください。

が指定した位置に、指定したサイズで指定されたイメージを描画します。例えば

// Create image. 
Image newImage = Image.FromFile("SampImag.jpg"); 

// Create coordinates for upper-left corner of image and for size of image. 
int x = 0; 
int y = 0; 
int width = 450; 
int height = 150; 

// Draw image to screen. 
e.Graphics.DrawImage(newImage, x, y, width, height); 

EDIT:コメントあたり、私はOPは画素数を低下させることなく、ファイルサイズを小さくしたい理解しています。したがって、ファイルを再圧縮する必要があります。

私はhereからいくつかのサンプルコードを借りてきました:

ImageCodecInfo iciJpegCodec = null; 

// This will specify the image quality to the encoder. Change the value of 75 from 0 to 100, where 100 is best quality, but highest file size. 
EncoderParameter epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75); 

// Get all image codecs that are available 
ImageCodecInfo[] iciCodecs = ImageCodecInfo.GetImageEncoders(); 

// Store the quality parameter in the list of encoder parameters 
EncoderParameters epParameters = new EncoderParameters(1); 
epParameters.Param[0] = epQuality; 

// Loop through all the image codecs 
for (int i = 0; i < iciCodecs.Length; i++) 
{ 
    // Until the one that we are interested in is found, which is image/jpeg 
    if (iciCodecs[i].MimeType == "image/jpeg") 
    { 
     iciJpegCodec = iciCodecs[i]; 
     break; 
    } 
} 

// Create a new Image object from the current file 
Image newImage = Image.FromFile(strFile); 

// Get the file information again, this time we want to find out the extension 
FileInfo fiPicture = new FileInfo(strFile); 

// Save the new file at the selected path with the specified encoder parameters, and reuse the same file name 
newImage.Save(outputPath + "\\" + fiPicture.Name, iciJpegCodec, epParameters); 
+0

私は確かに画像の1インチあたりのピクセル数を減らしたいと思います。たとえば、300dpiで1181 x 1181のサイズの画像をアップロードした場合、元のサイズの代わりに721piの1181 x 1181 buthの元のサイズで保存したい – Rob

+0

私はちょうど私が必要な画像を与えていないのを見たdrawimage関数を呼び出すときのサイズ。これを修正しようとします。 – Rob

+0

ああ、イメージの実際の総ピクセル数ではなく、ファイルのDPI値を減らしています。申し訳ありませんが、本当に問題が何であるかはわかりません。画像ファイルに保存された「解像度」の値は、画像がデジタル形式で保存されているときには意味がありません。実際に画像を再生したときにのみ表示されます。実際に行う必要がありますか? – tomfanning

0

ロブ、私はあなたのコードでその問題は、画像を保存であると考えている - 実際のデジタル画像データは、ドット/ピクセル、すなわち特定の数になります(mxn)とビットマップで解像度を設定しても、ドット数(したがってイメージの物理バイトサイズ)は変更しないでください。解像度情報が画像ヘッダ(/編集画像を印刷しながら、プログラムで使用される)に格納される - から上記ファイルの新しいビットマップを格納する場合に何が起こるかMEMストリームの代わりにファイルに

newBitmap.Save("c:\test.png", ImageFormat.Png); 

チェックDPIファイル - >プロパティ - >概要(上級)。 72 dpiにする必要があります。

+0

それをファイルシステムに保存する噂を試してみましょう。しかし、これは最終的な解決策ではありません。私はアプリケーション開発のために最後にデータベースに保存する必要があります – Rob

+0

私はあなたの提案を試みましたが、私はGDI +例外を取得しています。私は質問を更新しました – Rob

2

[OK]を、私はハードドライブ上のファイルで試してみましたが、それはあまりにもストリームで動作するはずです。

 Bitmap bitmap = new Bitmap(loadFrom); 
     Bitmap newBitmap = new Bitmap(bitmap); 
     newBitmap.SetResolution(72, 72); 
     newBitmap.Save(saveTo); 
関連する問題