DrawImage无法正确定位切片图像

本文关键字:定位 切片 图像 DrawImage | 更新日期: 2023-09-27 18:03:05

几天来,我一直在试图弄清楚为什么我的九段代码没有像预期的那样工作。据我所知,似乎有一个问题与图像。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;
    }
}

我的问题是,有人知道我该如何补偿不正确的缩放吗?

DrawImage无法正确定位切片图像

经过反复试验,我终于找到了解决问题的办法。缩放问题一直存在于上中心、右中心、下中心和左中心切片,因为它们总是按照九片缩放的逻辑只向一个方向拉伸。如果我在应用正确的拉伸之前对这些切片应用临时的正方形拉伸,那么最终的位图将是正确的。同样,这个问题只在Windows CE设备(智能设备)的。net Compact Framework中可见。这里是一个代码片段,在CF中调整了这个bug。我现在唯一担心的是,由于纠正代码,得到方形拉伸的切片将占用更多的内存。另一方面,这一步只需要很短的时间,所以我可能会侥幸逃脱。;)

    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;
    }
}