2011-07-21 37 views
3

几天后,我试图找出为什么我的9切片代码无法按预期工作。据我所见,Graphics.DrawImage方法似乎有一个问题,它错误地处理了我的九个切片图像。所以我的问题是如何补偿在紧凑框架上运行我的代码时执行的不正确缩放。我可能会补充说,当在完整的框架环境中运行时,这段代码当然是完美的。只有将图像缩放到较大图像时才会出现问题,而不是相反。这里是片段:DrawImage无法正确定位切片图像

public class NineSliceBitmapSnippet 
{ 
    private Bitmap m_OriginalBitmap; 

    public int CornerLength { get; set; } 

    /// <summary> 
    /// Initializes a new instance of the NineSliceBitmapSnippet class. 
    /// </summary> 
    public NineSliceBitmapSnippet(Bitmap bitmap) 
    { 
     CornerLength = 5; 
     m_OriginalBitmap = bitmap; 
    } 

    public Bitmap ScaleSingleBitmap(Size size) 
    { 
     Bitmap scaledBitmap = new Bitmap(size.Width, size.Height); 
     int[] horizontalTargetSlices = Slice(size.Width); 
     int[] verticalTargetSlices = Slice(size.Height); 

     int[] horizontalSourceSlices = Slice(m_OriginalBitmap.Width); 
     int[] verticalSourceSlices = Slice(m_OriginalBitmap.Height); 

     using (Graphics graphics = Graphics.FromImage(scaledBitmap)) 
     { 
      using (Brush brush = new SolidBrush(Color.Fuchsia)) 
      { 
       graphics.FillRectangle(brush, new Rectangle(0, 0, size.Width, size.Height)); 
      } 

      int horizontalTargetOffset = 0; 
      int verticalTargetOffset = 0; 

      int horizontalSourceOffset = 0; 
      int verticalSourceOffset = 0; 

      for (int x = 0; x < horizontalTargetSlices.Length; x++) 
      { 
       verticalTargetOffset = 0; 
       verticalSourceOffset = 0; 
       for (int y = 0; y < verticalTargetSlices.Length; y++) 
       { 
        Rectangle destination = new Rectangle(horizontalTargetOffset, verticalTargetOffset, horizontalTargetSlices[x], verticalTargetSlices[y]); 
        Rectangle source = new Rectangle(horizontalSourceOffset, verticalSourceOffset, horizontalSourceSlices[x], verticalSourceSlices[y]); 

        graphics.DrawImage(m_OriginalBitmap, destination, source, GraphicsUnit.Pixel); 

        verticalTargetOffset += verticalTargetSlices[y]; 
        verticalSourceOffset += verticalSourceSlices[y]; 
       } 

       horizontalTargetOffset += horizontalTargetSlices[x]; 
       horizontalSourceOffset += horizontalSourceSlices[x]; 
      } 
     } 
     return scaledBitmap; 
    } 

    public int[] Slice(int length) 
    { 
     int cornerLength = CornerLength; 

     if (length <= (cornerLength * 2)) 
      throw new Exception("Image to small for sliceing up"); 

     int[] slices = new int[3]; 
     slices[0] = cornerLength; 
     slices[1] = length - (2 * cornerLength); 
     slices[2] = cornerLength; 

     return slices; 
    } 
} 

所以,我的问题是,现在有人有我如何补偿不正确的缩放?

/丹

+0

什么是错误?或者你可以链接什么是不工作的图像? – LarsTech

+0

问题是,当我再次将图像拼接在一起时,缩放到较大的图像时,只沿一个方向拉伸的部分将沿相反方向拉伸,同时一个像素拉伸。当我获得更高的声誉评价时,我会尝试发布不正确的DrawImage行为图像。 –

+0

在智能设备(WCE)上运行时,DrawImage的紧凑框架版本似乎只能在一个方向上拉伸图像,从而导致此错误行为。如果我在两个方向上拉伸图像,它都会正确完成。总结这个问题:使用DrawImage水平拉伸图像会意外地导致图像在垂直方向上被拉伸,甚至是稍微拉伸。 –

回答

1

一些试验和错误之后,我终于找到了解决我的问题。缩放问题一直存在于上中心,右中心,下中心和左中心切片,因为它们总是根据九切片缩放的逻辑仅在一个方向上拉伸。如果我在应用正确的拉伸之前对这些切片应用临时正方形拉伸,则最终的位图将是正确的。问题再次出现在Windows CE设备(智能设备)的.Net Compact Framework中。以下是代码调整CF中的错误的代码片段。我现在唯一担心的是由于纠正码,得到方形拉伸的切片将占用更多的内存。另一方面,这一步只是短暂的一段时间,所以我可能会摆脱它。 ;)

public class NineSliceBitmapSnippet 
{ 
    private Bitmap m_OriginalBitmap; 

    public int CornerLength { get; set; } 

    public NineSliceBitmapSnippet(Bitmap bitmap) 
    { 
     CornerLength = 5; 
     m_OriginalBitmap = bitmap; 
    } 

    public Bitmap Scale(Size size) 
    { 
     if (m_OriginalBitmap != null) 
     { 
      return ScaleSingleBitmap(size); 
     } 

     return null; 
    } 

    public Bitmap ScaleSingleBitmap(Size size) 
    { 
     Bitmap scaledBitmap = new Bitmap(size.Width, size.Height); 
     int[] horizontalTargetSlices = Slice(size.Width); 
     int[] verticalTargetSlices = Slice(size.Height); 

     int[] horizontalSourceSlices = Slice(m_OriginalBitmap.Width); 
     int[] verticalSourceSlices = Slice(m_OriginalBitmap.Height); 

     using (Graphics graphics = Graphics.FromImage(scaledBitmap)) 
     { 
      using (Brush brush = new SolidBrush(Color.Fuchsia)) 
      { 
       graphics.FillRectangle(brush, new Rectangle(0, 0, size.Width, size.Height)); 
      } 

      int horizontalTargetOffset = 0; 
      int verticalTargetOffset = 0; 

      int horizontalSourceOffset = 0; 
      int verticalSourceOffset = 0; 

      for (int x = 0; x < horizontalTargetSlices.Length; x++) 
      { 
       verticalTargetOffset = 0; 
       verticalSourceOffset = 0; 
       for (int y = 0; y < verticalTargetSlices.Length; y++) 
       { 
        Rectangle destination = new Rectangle(horizontalTargetOffset, verticalTargetOffset, horizontalTargetSlices[x], verticalTargetSlices[y]); 
        Rectangle source = new Rectangle(horizontalSourceOffset, verticalSourceOffset, horizontalSourceSlices[x], verticalSourceSlices[y]); 

        bool isWidthAffectedByVerticalStretch = (y == 1 && (x == 0 || x == 2) && destination.Height > source.Height); 
        bool isHeightAffectedByHorizontalStretch = (x == 1 && (y == 0 || y == 2) && destination.Width > source.Width); 
        if (isHeightAffectedByHorizontalStretch) 
        { 
         BypassDrawImageError(graphics, destination, source, Orientation.Horizontal); 
        } 
        else if (isWidthAffectedByVerticalStretch) 
        { 
         BypassDrawImageError(graphics, destination, source, Orientation.Vertical); 
        } 
        else 
        { 
         graphics.DrawImage(m_OriginalBitmap, destination, source, GraphicsUnit.Pixel); 
        } 

        verticalTargetOffset += verticalTargetSlices[y]; 
        verticalSourceOffset += verticalSourceSlices[y]; 
       } 

       horizontalTargetOffset += horizontalTargetSlices[x]; 
       horizontalSourceOffset += horizontalSourceSlices[x]; 
      } 
     } 
     return scaledBitmap; 
    } 

    private void BypassDrawImageError(Graphics graphics, Rectangle destination, Rectangle source, Orientation orientationAdjustment) 
    { 
     Size adjustedSize = Size.Empty; 
     switch (orientationAdjustment) 
     { 
      case Orientation.Horizontal: 
       adjustedSize = new Size(destination.Width, destination.Width); 
       break; 
      case Orientation.Vertical: 
       adjustedSize = new Size(destination.Height, destination.Height); 
       break; 
      default: 
       break; 
     } 

     using (Bitmap quadScaledBitmap = new Bitmap(adjustedSize.Width, adjustedSize.Height)) 
     { 
      using (Graphics tempGraphics = Graphics.FromImage(quadScaledBitmap)) 
      { 
       tempGraphics.Clear(Color.Fuchsia); 
       tempGraphics.DrawImage(m_OriginalBitmap, new Rectangle(0, 0, adjustedSize.Width, adjustedSize.Height), source, GraphicsUnit.Pixel); 
      } 
      graphics.DrawImage(quadScaledBitmap, destination, new Rectangle(0, 0, quadScaledBitmap.Width, quadScaledBitmap.Height), GraphicsUnit.Pixel); 
     } 
    } 

    public int[] Slice(int length) 
    { 
     int cornerLength = CornerLength; 

     if (length <= (cornerLength * 2)) 
      throw new Exception("Image to small for sliceing up"); 

     int[] slices = new int[3]; 
     slices[0] = cornerLength; 
     slices[1] = length - (2 * cornerLength); 
     slices[2] = cornerLength; 

     return slices; 
    } 
}