2008-08-27 4 views
24

투명 이미지 (주로 GIF)의 크기를 조정하는 비밀 수식이 있습니까 없이 모든 품질 손실 - 그 어느 때까지?C#을 사용하여 투명 이미지 크기 조정

나는 많은 것을 시도해 보았다. 가장 가까운 것은 충분하지 않다.

내 주요 이미지를 살펴 보자

http://www.thewallcompany.dk/test/main.gif

그리고 스케일 이미지 :

http://www.thewallcompany.dk/test/ScaledImage.gif

//Internal resize for indexed colored images 
void IndexedRezise(int xSize, int ySize) 
{ 
    BitmapData sourceData; 
    BitmapData targetData; 

    AdjustSizes(ref xSize, ref ySize); 

    scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat); 
    scaledBitmap.Palette = bitmap.Palette; 
    sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), 
    ImageLockMode.ReadOnly, bitmap.PixelFormat); 
    try 
    { 
    targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize), 
     ImageLockMode.WriteOnly, scaledBitmap.PixelFormat); 
    try 
    { 
     xFactor = (Double)bitmap.Width/(Double)scaledBitmap.Width; 
     yFactor = (Double)bitmap.Height/(Double)scaledBitmap.Height; 
     sourceStride = sourceData.Stride; 
     sourceScan0 = sourceData.Scan0; 
     int targetStride = targetData.Stride; 
     System.IntPtr targetScan0 = targetData.Scan0; 
     unsafe 
     { 
     byte* p = (byte*)(void*)targetScan0; 
     int nOffset = targetStride - scaledBitmap.Width; 
     int nWidth = scaledBitmap.Width; 
     for (int y = 0; y < scaledBitmap.Height; ++y) 
     { 
      for (int x = 0; x < nWidth; ++x) 
      { 
      p[0] = GetSourceByteAt(x, y); 
      ++p; 
      } 
      p += nOffset; 
     } 
     } 
    } 
    finally 
    { 
     scaledBitmap.UnlockBits(targetData); 
    } 
    } 
    finally 
    { 
    bitmap.UnlockBits(sourceData); 
    } 
} 

나는이 작업을 수행하려면 위의 코드를 사용하고 있습니다를 인덱싱 된 크기 조정.

누구에게 개선 아이디어가 있습니까?

+0

GDI의 끔찍한 GIF 지원을 수정하는 라이브러리를 사용하는 것이 좋습니다. 내 것과 같이, http://imageresizing.net 약 4 년 동안 있었고 잘 유지되고 지원됩니다. –

답변

47

크기 조정 후 파일 형식을 보존 할 필요가 없다면 다음 방법을 권장합니다.

using (Image src = Image.FromFile("main.gif")) 
using (Bitmap dst = new Bitmap(100, 129)) 
using (Graphics g = Graphics.FromImage(dst)) 
{ 
    g.SmoothingMode = SmoothingMode.AntiAlias; 
    g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
    g.DrawImage(src, 0, 0, dst.Width, dst.Height); 
    dst.Save("scale.png", ImageFormat.Png); 
} 

결과가있을 것이다 정말 좋은 안티 앨리어싱 가장자리

    당신은 GIF에서 이미지를 내 보내야합니다 경우 고라

에 의해 대체되었다

  • 제거 이미지 오두막 이미지 당신 타기 위해 들러. GDI +는 gif로 잘 재생되지 않습니다. 자세한 내용은 this blog post을 참조하십시오.

    편집 : 예에서 비트 맵을 삭제하는 것을 잊었습니다. 수정되었습니다

  • +0

    이미지와 같은 정사각형으로 만 작동하며 비례 적으로 크기가 조정되지 않습니다 – eKek0

    +1

    다음은 이미지의 크기를 조정할 때 TODO 항목 목록입니다 : http://nathanaeljones.com/163/20- image-resizing-pitfalls/ 다른 사람들이 필요로하는 경우 투명도 지원을 사용하여 GIF 양자화를 구현했습니다 (Google "ASP.NET 이미지 크기 조정 모듈") –

    +0

    와우, Markus - 아주 좋습니다. 나는 샘플을 온라인에 올려 놓았다 : [http://www.thewallcompany.dk/test/](http://www.thewallcompany.dk/test/) 내가 볼 수있는 한, 수동으로 크기를 재조정 한 것과 비교할 때 전혀 손실이 없다. gif 이미지. 고마워. – MartinHN

    3

    문제는 스캔 라인 기반 크기 조정을 수행하고있어 문제가 얼마나 힘들어도 jaggies로 이어질 것입니다. 좋은 이미지 크기 조정 품질은 크기 조정 된 픽셀이 다루는 사전 크기 조정 픽셀의 평균 색상을 파악하기 위해 더 많은 작업을해야합니다.

    이 웹 사이트를 운영하는 사람은 몇 가지 이미지 크기 조정 알고리즘을 설명하는 블로그 게시물이 있습니다. 아마도 bicubic 이미지 스케일링 알고리즘을 원할 것입니다.

    Better Image Resizing

    +3

    Heh, "이 웹 사이트를 운영하는 사람": –

    4

    이 나는 ​​그것이 작동하는지 GDI는 +

    /// <summary> 
    /// Resize image with GDI+ so that image is nice and clear with required size. 
    /// </summary> 
    /// <param name="SourceImage">Image to resize</param> 
    /// <param name="NewHeight">New height to resize to.</param> 
    /// <param name="NewWidth">New width to resize to.</param> 
    /// <returns>Image object resized to new dimensions.</returns> 
    /// <remarks></remarks> 
    public static Image ImageResize(Image SourceImage, Int32 NewHeight, Int32 NewWidth) 
    { 
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat); 
    
        if (bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format4bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format8bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Undefined | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.DontCare | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppGrayScale) 
        { 
         throw new NotSupportedException("Pixel format of the image is not supported."); 
        } 
    
        System.Drawing.Graphics graphicsImage = System.Drawing.Graphics.FromImage(bitmap); 
    
        graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality; 
        graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 
        graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height); 
        graphicsImage.Dispose(); 
        return bitmap; 
    } 
    

    난 내 머리 위로 떨어져 기억하지 않습니다 활용이 내 응용 프로그램의 몇 가지에 사용했습니다 기본 크기 조정 기능입니다 GIF와 함께,하지만 당신은 그것을 시도 줄 수 있습니다.

    참고 :이 기능에 대해서는 전적으로 인정하지 않습니다. 나는 다른 샘플을 온라인에서 몇 편 더 결합하여 내 필요에 맞도록 만들었습니다.^D

    1

    Markus Olsson의 솔루션을 사용하여 이미지의 크기를 동적으로 조정하고 응답 스트림에 쓸 수있는 모든 사용자에게 적합합니다.

    이 작동하지 않습니다

    Response.ContentType = "image/png"; 
    dst.Save(Response.OutputStream, ImageFormat.Png); 
    

    하지만이됩니다

    Response.ContentType = "image/png"; 
    using (MemoryStream stream = new MemoryStream()) 
    { 
        dst.Save(stream, ImageFormat.Png); 
    
        stream.WriteTo(Response.OutputStream); 
    } 
    
    +0

    두 번째 작품은 왜 첫 번째 작품이 아닌가? (단지 궁금해서) –

    +0

    이 링크는 사물을 설명합니다. http://www.west-wind.com/Weblog/posts/6008.aspx – Bela

    0

    을 PNG가 GIF는, 때때로 GIF 형식에 머물 필요에 대한 사용 사례가 있다는 것을 확실히 더 나은된다.

    GIF 또는 8 비트 PNG를 사용하면 양자화 문제를 해결해야합니다.

    양자화 란 이미지를 가장 잘 보존하고 표현할 256 가지 색상을 선택한 다음 RGB 값을 다시 색인으로 바꾸는 것입니다. 크기 조정 작업을 수행하면 이상적인 색상 표가 변경되어 색상을 혼합하고 저울을 변경합니다.

    약간의 크기 조정 (예 : 10-30 %)의 경우 원본 색상 표를 그대로 유지해도 문제가 없습니다.

    그러나 대부분의 경우 다시 양자화해야합니다.

    선택할 기본 알고리즘은 Octree와 nQuant입니다. Octree는 매우 빠르며, 특히 스마트 디더링 알고리즘을 오버레이 할 수있는 경우에 매우 효과적입니다. nQuant는 인코딩을 수행하는 데 최소 80MB의 RAM이 필요하며 (일반적으로 히스토그램을 만듭니다) 일반적으로 20-30X 느립니다 (평균 이미지에서 인코딩 당 1-5 초). 그러나 Octree가 일관된 성능을 유지하기 위해 값을 '반올림'하지 않기 때문에 Octree보다 높은 화질을 생성하는 경우가 있습니다.

    imageresizing.net 프로젝트에서 투명한 GIF 및 애니메이션 GIF 지원을 구현할 때 Octree를 선택했습니다. 이미지 팔레트를 제어하면 투명성 지원이 어렵지 않습니다.