2009-04-29 29 views
6

Tôi đang định lại kích thước một số hình ảnh với độ phân giải màn hình của người dùng; nếu tỷ lệ khung hình sai, hình ảnh sẽ bị cắt. Mã của tôi trông giống như sau:Thay đổi kích thước hình ảnh - đôi khi chất lượng rất kém?

protected void ConvertToBitmap(string filename) 
    { 
     var origImg = System.Drawing.Image.FromFile(filename); 
     var widthDivisor = (double)origImg.Width/(double)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width; 
     var heightDivisor = (double)origImg.Height/(double)System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height; 
     int newWidth, newHeight; 

     if (widthDivisor < heightDivisor) 
     { 
      newWidth = (int)((double)origImg.Width/widthDivisor); 
      newHeight = (int)((double)origImg.Height/widthDivisor); 
     } 
     else 
     { 
      newWidth = (int)((double)origImg.Width/heightDivisor); 
      newHeight = (int)((double)origImg.Height/heightDivisor); 
     } 

     var newImg = origImg.GetThumbnailImage(newWidth, newHeight, null, IntPtr.Zero); 
     newImg.Save(this.GetBitmapPath(filename), System.Drawing.Imaging.ImageFormat.Bmp); 
    } 

Trong hầu hết các trường hợp, tính năng này hoạt động tốt. Nhưng đối với một số hình ảnh, kết quả có chất lượng kém cực kỳ. Có vẻ như nó đã được thay đổi kích thước thành một cái gì đó rất nhỏ (kích thước hình thu nhỏ) và mở rộng một lần nữa .. Nhưng độ phân giải của hình ảnh là chính xác. Tôi có thể làm gì?

Ví dụ orig ảnh: alt text http://img523.imageshack.us/img523/1430/naturaerowoods.jpg

Ví dụ thay đổi kích cỡ hình ảnh: alt text http://img523.imageshack.us/img523/2531/naturaerowoods.png

Lưu ý: Tôi có một ứng dụng WPF nhưng tôi sử dụng WinForms chức năng cho thay đổi kích thước bởi vì nó dễ dàng hơn và vì tôi đã cần một tham chiếu đến System.Windows.Forms cho biểu tượng khay.

+0

Cám ơn hỏi này! Vấn đề này vẫn còn hiện nay ... – Andrew

Trả lời

7

Thay đổi hai dòng cuối cùng của phương pháp thành:

var newImg = new Bitmap(newWidth, newHeight); 
Graphics g = Graphics.FromImage(newImg); 
g.DrawImage(origImg, new Rectangle(0,0,newWidth,newHeight)); 
newImg.Save(this.GetBitmapPath(filename), System.Drawing.Imaging.ImageFormat.Bmp); 
g.Dispose(); 
+2

Bạn cần phải thiết lập các thiết lập chất lượng cũng - họ mặc định thấp. Xem http://nathanaeljones.com/163/20-image-resizing-pitfalls/ –

+0

Chúc mừng cho cả Chuyên gia ngôn ngữ Bfree và Máy tính, hiện đã giải quyết được sự cố của tôi ... –

+0

Nếu bạn đang thực hiện việc này trên máy chủ, chẳng hạn như trong một ứng dụng ASP.NET, tốt nhất bạn nên sử dụng [một trình bao bọc] (http://imageresizing.net) để sửa các bản ghi nhớ System.Drawing. –

7

Tôi không thể nhìn trộm vào nguồn .NET vào lúc này, nhưng rất có thể sự cố nằm trong phương thức Image.GetThumbnailImage. Ngay cả MSDN nói rằng "nó hoạt động tốt khi hình ảnh thu nhỏ được yêu cầu có kích thước khoảng 120 x 120 pixel, nhưng bạn yêu cầu một hình thu nhỏ lớn (ví dụ: 300 x 300) từ Hình ảnh có hình thu nhỏ được nhúng, có thể là một sự mất mát đáng chú ý về chất lượng trong hình thu nhỏ ". Để thay đổi kích thước thực (nghĩa là không thu nhỏ), bạn nên sử dụng phương thức Graphics.DrawImage. Bạn cũng có thể cần phải chơi với Graphics.InterpolationMode để có chất lượng tốt hơn nếu cần.

2

Như được nêu trên MSDN, GetThumbnailImage() không được thiết kế để thực hiện chia tỷ lệ hình ảnh tùy ý. Bất cứ điều gì trên 120x120 nên được thu nhỏ theo cách thủ công. Hãy thử điều này thay vì:

using(var newImg = new Bitmap(origImg, newWidth, newHeight)) 
{ 
    newImg.Save(this.GetBitmapPath(filename), System.Drawing.Imaging.ImageFormat.Bmp); 
} 

Sửa

Là một điểm làm rõ, tình trạng quá tải này của các nhà xây dựng Bitmap gọi Graphics.DrawImage, mặc dù bạn không có bất kỳ kiểm soát nội suy.

0

Ví dụ: hình ảnh gốc là JPG và hình ảnh được đổi kích thước là PNG. Bạn có đang chuyển đổi giữa các định dạng với mục đích không? Chuyển đổi giữa các chương trình nén lossey khác nhau có thể gây ra tổn thất chất lượng.

+0

Tôi muốn sử dụng hình ảnh làm hình nền, và cho mục đích đó tôi phải chuyển đổi nó thành BMP vì Win XP không chấp nhận bất kỳ định dạng nào khác cho hình nền. – eWolf

3

Nếu bạn không tạo ra một hình ảnh thu nhỏ, sử dụng một phương pháp gọi là GetThumbnailImage lẽ không phải là một ý tưởng tốt ...

Đối với lựa chọn khác, có một cái nhìn tại this CodeProject article. Đặc biệt, nó tạo ra một hình ảnh mới, tạo ra một Graphics cho nó và đặt chế độ nội suy thành HighQualityBicubic và vẽ hình ảnh gốc lên đồ họa. Giá trị một thử, ít nhất.

+3

Downvoters: xin vui lòng cho lý do ... –

+0

họ chỉ ghen tị với kiến ​​thức sử thi của bạn jon bỏ qua chúng –

-1

Điều này sẽ rất khác nhau dựa trên các yếu tố sau:

  1. Làm thế nào chặt chẽ việc giải quyết điểm đến phù hợp với quy mô "tự nhiên" của độ phân giải gốc
  2. Độ sâu nguồn màu sắc hình ảnh
  3. Hình ảnh loại (s) - một số bị mất nhiều hơn số khác
0

Bạn có đang tăng hoặc giảm kích thước của hình ảnh khi bạn đổi kích thước hình ảnh không? Nếu bạn đang tạo ra một hình ảnh lớn hơn từ một hình nhỏ hơn, loại suy thoái này sẽ được mong đợi.

+0

Hai hình ảnh của ông dường như chỉ ra rằng bản gốc lớn hơn. –

0

Hình ảnh chắc chắn sẽ bị giảm nếu bạn phóng to chúng.

0

Một số máy ảnh đặt hình thu nhỏ đã được định lại kích cỡ vào chính tệp có lẽ cho mục đích xem trước trên chính thiết bị.

Phương pháp GetThumbnail thực sự nhận được hình ảnh thu nhỏ này được nhúng trong tệp hình ảnh thay vì nhận phương thức res cao hơn.

Giải pháp dễ dàng là lừa .Net đưa vào thông tin thu nhỏ trước khi thực hiện thay đổi kích thước hoặc hoạt động khác. như vậy ....

img.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX); 
//removes thumbnails from digital camera shots 
img.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX); 

Nếu bạn đang cố gắng để thay đổi kích thước tỷ lệ kìm hãm tôi đã viết một phương pháp khuyến nông trên System.Drawing.Image mà bạn có thể tìm thấy tiện dụng.

/// <summary> 
/// 
/// </summary> 
/// <param name="img"></param> 
/// <param name="size">Size of the constraining proportion</param> 
/// <param name="constrainOnWidth"></param> 
/// <returns></returns> 
public static System.Drawing.Image ResizeConstrainProportions(this System.Drawing.Image img, 
    int size, bool constrainOnWidth, bool dontResizeIfSmaller) 
{ 
    if (dontResizeIfSmaller && (img.Width < size)) 
     return img; 
    img.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX); 
    img.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX); 
    float ratio = 0; 
    ratio = (float)img.Width/(float)img.Height; 

    int height, width = 0; 
    if (constrainOnWidth) 
    { 
     height = (int)(size/ratio); 
     width = size; 
    } 
    else 
    { 
     width = (int)(size * ratio); 
     height = size; 
    } 
    return img.GetThumbnailImage(width, height, null, (new System.IntPtr(0))); 
} 
2

thay vì mã này:

newImg.Save(this.GetBitmapPath(filename), System.Drawing.Imaging.ImageFormat.Bmp); 

sử dụng này một:

System.Drawing.Imaging.ImageCodecInfo[] info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders(); 
System.Drawing.Imaging.EncoderParameters param = new System.Drawing.Imaging.EncoderParameters(1); 
param.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L); 
newImg.Save(dest_img, info[1], param); 
Các vấn đề liên quan