3

几天来,我试图弄清楚为什么我的九片代码不能按预期工作。据我所见,Graphics.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;
    }
}

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

/担

4

1 回答 1

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;
    }
}
于 2011-07-25T07:38:29.700 回答