質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

1回答

6970閲覧

Bitmapクラスでのbit深さの変換

Auger

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/10/06 10:22

前提・実現したいこと

32bitの画像を8bitに変換したいと考えています。

ここに質問の内容を詳しく書いてください。
C#で画像に矩形を描画するというプログラムを作っています。
矩形を書くことはできたのですが、元画像のbit深さが8bitなのに対し、
矩形描画後には32bitになってしまいました。
32bitでは都合が悪いので、なんとか8bitで出力したいです。

■■な機能を実装中に以下のエラーメッセージが発生しました。

該当のソースコード

Bitmap image = new Bitmap(画像のパス) //この時点では8bit Bitmap canvas = new Bitmap(image) //ここで32bit Graphic g = Graphics.FromImage(canvas); Pen p = new Pen(Color.Black, 1); //位置(10, 20)に100x80の長方形を描く g.DrawRectangle(p, 10, 20, 100, 80); //リソースを解放する p.Dispose(); g.Dispose(); canvas.Save(保存先のパス);

試したこと

https://docs.microsoft.com/en-us/dotnet/api/system.drawing.image.fromfile?redirectedfrom=MSDN&view=dotnet-plat-ext-3.1#System_Drawing_Image_FromFile_System_String_System_Boolean_
などを試しました。
調べる中で、画像のビット深度を変えることはできないと見たのですが、
どうなのでしょうか?

補足情報(FW/ツールのバージョンなど)

VisualAtudio2019で作成しております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Auger

2020/10/06 10:42

この方法も試しましたが、32bitのままでした。
Auger

2020/10/06 14:09

イメージにインデックス付きピクセル形式がある というエラーが色々試しているうちに出てきたことを思い出しました。このurlの方法を試してみたいと思います。 https://stackoverrun.com/ja/q/12063421
guest

回答1

0

懐かしのGDIで8bit化。
残念画質になるので、質を求めるなら自力で減色ルーチン・最適化パレット作らないとダメですね。
グレースケールなら、それほど難しくはないのですが。

using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsFormsApp2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public enum BitmapCompressionMode : uint { BI_RGB = 0, BI_RLE8 = 1, BI_RLE4 = 2, BI_BITFIELDS = 3, BI_JPEG = 4, BI_PNG = 5 } [StructLayout(LayoutKind.Sequential)] public struct BITMAPINFOHEADER { public uint biSize; public int biWidth; public int biHeight; public ushort biPlanes; public ushort biBitCount; public BitmapCompressionMode biCompression; public uint biSizeImage; public int biXPelsPerMeter; public int biYPelsPerMeter; public uint biClrUsed; public uint biClrImportant; } public enum DibColorsUsage : uint { RGB = 0, PAL = 1 } [StructLayout(LayoutKind.Sequential)] public struct BITMAPINFO { public BITMAPINFOHEADER bmiHeader; [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U4, SizeConst = 256)] public uint[] bmiColors; } [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC(IntPtr hwnd); [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteDC(IntPtr hdc); [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern int GetDIBits( IntPtr hdc, IntPtr hbm, int start, int cLines, IntPtr lpvBits, ref BITMAPINFO lpbmi, DibColorsUsage usage ); private void button1_Click(object sender, EventArgs e) { using (var bmp8_src = new Bitmap("c:/test/test.bmp")) using (var canvas = new Bitmap(bmp8_src)) using (var graph = Graphics.FromImage(canvas)) using (var pen = new Pen(Color.Black, 1)) { //位置(10, 20)に100x80の長方形を描く graph.DrawRectangle(pen, 10, 20, 100, 80); using (var bmp8_dst = ConvertBmp8(canvas)) { bmp8_dst.Save("c:/test/test2.bmp"); } } } private Bitmap ConvertBmp8(Bitmap bmp) { //出力用8bitビットマップ var bmp8 = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); //GetDIBitsで8bitビットマップ取得 BITMAPINFO bi = new BITMAPINFO(); bi.bmiHeader.biSize = (uint)Marshal.SizeOf(bi.bmiHeader); bi.bmiHeader.biWidth = bmp.Width; bi.bmiHeader.biHeight = -bmp.Height; //トップダウンにするためマイナス(上下逆転する) bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 8; bi.bmiHeader.biCompression = BitmapCompressionMode.BI_RGB; var hdc = CreateCompatibleDC(IntPtr.Zero); var hBmp = bmp.GetHbitmap(); var hBmpOld = SelectObject(hdc, hBmp); var bmData = bmp8.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); GetDIBits(hdc, hBmp, 0, bmp.Height, bmData.Scan0, ref bi, DibColorsUsage.RGB); bmp8.UnlockBits(bmData); SelectObject(hdc, hBmpOld); DeleteObject(hBmp); DeleteDC(hdc); //パレット転送 var palette = bmp8.Palette; for (var i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb((int)(bi.bmiColors[i] | 0xff000000)); } bmp8.Palette = palette; return bmp8; } } }

投稿2020/10/07 05:55

編集2020/10/07 06:04
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問