1

我试图弄清楚如何将我的位图图像旋转任意度数,类似于此处发布的解决方案。但是,当我尝试使用此解决方案(将位图转换为图形对象)以及我搜索过的其他解决方案时,我不断收到异常:

A Graphics object cannot be created from an image that has an indexed pixel format.

我需要索引像素,以便我可以访问每个像素并在我的程序中获取颜色信息,但我还需要能够以 90 度以外的度数增量动态旋转。

我想知道 A)是否有对索引像素位图友好的解决方案,或者 B)是否有办法临时更改位图以允许将其转换为图形对象,然后将其更改回索引像素应用了旋转的位图?

提前非常感谢!

编辑:我正在使用的位图的 PixelFormat 是“1bppIndexed”。

4

2 回答 2

1

我想您在这里使用的是 Windows 窗体和 GDI+?我已经为此做了很多工作,并且可以非常自信地告诉您您想要使用 24 位或 32 位图像(我不记得哪个对不起)。性能大大提高了大约 10 到 100 倍。在我的应用程序中,用户在文本框中指定旋转与能够用鼠标抓取图像并动态平滑旋转、动态缩放等有所不同。

假设您遵循该建议,只留下能够访问每个像素的问题。为什么您认为无法获得 24 或 32 位图像的每个像素?

编辑:在我的应用程序中,我只对所有内容使用了 32 位位图。如果我得到另一种格式的位图(例如从文件打开),我会立即转换它。实际上,即使我得到 32 位格式,我也会立即克隆它,然后处理原始位图,因为我发现它在文件上保留了一些锁。内置克隆产生了奇怪的结果,所以我最终在下面编写了这段代码。请注意,这是我大概 8 年前写的东西,所以没有使用任何最新功能:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace ImageCloneTest
{
    static class Program
    {
        [DllImport("kernel32", EntryPoint = "RtlMoveMemory")]
        public unsafe static extern void CopyMemory(byte* Destination, byte* Source, int Length);

        [DllImport("kernel32", EntryPoint = "RtlMoveMemory")]
        public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);


        public static Bitmap Clone(Bitmap SourceBitmap, PixelFormat Format)
        {
            // copy image if pixel format is the same
            if (SourceBitmap.PixelFormat == Format) return Clone(SourceBitmap);

            int width = SourceBitmap.Width;
            int height = SourceBitmap.Height;

            // create new image with desired pixel format
            Bitmap bitmap = new Bitmap(width, height, Format);

            // draw source image on the new one using Graphics
            Graphics g = Graphics.FromImage(bitmap);
            //fill background in case orig bitmap contains transparent regions.
            g.FillRectangle(Brushes.White, 0, 0, bitmap.Width, bitmap.Height);
            g.DrawImage(SourceBitmap, 0, 0, width, height);
            g.Dispose();

            return bitmap;
        }

        // and with unspecified PixelFormat it works strange too
        public static Bitmap Clone(Bitmap SourceBitmap)
        {
            // get source image size
            int width = SourceBitmap.Width;
            int height = SourceBitmap.Height;
            Rectangle rect = new Rectangle(0, 0, width, height);

            // lock source bitmap data
            BitmapData srcData = SourceBitmap.LockBits(rect, ImageLockMode.ReadOnly, SourceBitmap.PixelFormat);

            // create new image
            Bitmap dstBitmap = new Bitmap(width, height, SourceBitmap.PixelFormat);

            // lock destination bitmap data
            BitmapData dstData = dstBitmap.LockBits(rect, ImageLockMode.WriteOnly, dstBitmap.PixelFormat);

            CopyMemory(dstData.Scan0, srcData.Scan0, height * srcData.Stride);

            // unlock both images
            dstBitmap.UnlockBits(dstData);
            SourceBitmap.UnlockBits(srcData);

            // copy pallete
            if (BitmapHasPalette(SourceBitmap) && BitmapHasPalette(dstBitmap))
            {
                ColorPalette srcPalette = SourceBitmap.Palette;
                ColorPalette dstPalette = dstBitmap.Palette;
                int n = srcPalette.Entries.Length;
                for (int i = 0; i < n; i++)
                {
                    dstPalette.Entries[i] = srcPalette.Entries[i];
                }
                dstBitmap.Palette = dstPalette;
            }
            return dstBitmap;
        }

        public static bool BitmapHasPalette(Bitmap SourceBitmap)
        {
            if (SourceBitmap == null) return false;
            switch (SourceBitmap.PixelFormat)
            {
                case PixelFormat.Format1bppIndexed:
                case PixelFormat.Format4bppIndexed:
                case PixelFormat.Format8bppIndexed:
                case PixelFormat.Indexed:
                    return true;
            }
            return false;
        }
    }
}
于 2012-08-02T23:23:41.073 回答
0

我在这里使用了 Hans 的解决方案:https ://stackoverflow.com/a/2016509/1464630

看来我仍然可以使用相同的程序逻辑,但它不再采用索引像素格式,因此 Graphics 类不会抱怨。

于 2012-08-03T16:25:51.930 回答