1

ここに投稿されたソリューションと同様に、ビットマップ画像を任意の角度だけ回転させる方法を見つけようとしています。ただし、ビットマップを Graphics オブジェクトに変換するこのソリューションと、Google で調べた他のソリューションを使用しようとすると、例外が発生し続けます。

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

プログラムで各ピクセルにアクセスして色情報を取得できるように、インデックス付きピクセルが必要ですが、90 度以外の角度でオンザフライで回転できる機能も必要です。

A) インデックス付きピクセル ビットマップに適したソリューションがあるかどうか、または B) ビットマップを一時的に変更して Graphics オブジェクトに変換できるようにしてからインデックス付きピクセルに戻す方法があるかどうか疑問に思っていました回転が適用されたビットマップ?

よろしくお願いします!

編集:私が使用しているビットマップの 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

ここでハンスのソリューションを使用しました: https://stackoverflow.com/a/2016509/1464630

同じプログラムロジックを引き続き使用できるようですが、インデックス付きピクセル形式ではなくなったため、Graphics クラスは文句を言いません。

于 2012-08-03T16:25:51.930 に答える