本站首页    管理页面    写新日志    退出

The Neurotic Fishbowl

[C/C++]Working with 8bit images in .NET
silenceZRY 发表于 2006-4-11 11:10:39

转载自: http://www.sharpgis.net/PermaLink,guid,f42989a8-fe4c-4695-a631-fa6a60d24b31.aspx Working with 8bit images in .NET For some reason Microsoft made it pretty hard to work with anything but 24bit images. This is even though they provide you with several pixel formats, but no way of setting and getting the values of a pixel. If you use the SetPixel(x,y) or GetPixel(x,y) methods, your application will fail. There are plenty of articles and blogs on the Internet on how to do direct access on 1bit and 24bit, but I wasn't able to find anything on 8bit. This article will cover some of the basics on how to access 8 bit greyscale or indexed images, by accessing the bitmapdata directly in memory. This also has the benefit of being much faster than the Set/GetPixel methods provided by the .NET Framework. Before we can access the memory directly, we must lock its place in memory. We can do this by calling the Bitmap.LockBits() method:BitmapData bmd = myBitmap.LockBits(new Rectangle(0, 0, myBitmap.Width, myBitmap.Height), ImageLockMode.ReadWrite, myBitmap.PixelFormat); Likewise when we are done using the BitmapData, remember to unlock the data:myBitmap.UnlockBits(bmd); Now we need a method that can access the BitmapData. Lets make our own SetPixel and GetPixel method. Here we assume that we are dealing with 8bit pixels. We also add the 'unsafe' keyword since direct memory access isn't thread safe. I won't cover the Stride and Scan0 values. Bob Powell has a nice article on this.public unsafe void SetPixel(int x, int y, byte c) { byte* p = (byte *)bmd.Scan0.ToPointer(); int offset=y*bmd.Stride+(x); p[offset] = c; } public unsafe Byte GetPixel(int x, int y) { byte* p = (byte *)bmd.Scan0.ToPointer(); int offset=y*bmd.Stride+x; return p[offset]; } It is worth noting that GetPixel only returns a byte and not a color. The byte represents a number between 0 and 255. Each of the values is actually an index to a color palette. The palette could specify that for instance index 0 is black, index 1 is red, index 3 is blue etc. If you want a greyscale image, we can override the color palette. Let's set index 0 to black, index 255 to white, and linearly distribute the grayscale in between. public static void SetGrayscalePalette(Bitmap b) { ColorPalette pal = b.Palette; for(int i = 0; i < 256; i++) pal.Entries[i] = Color.FromArgb( 255, i, i, i ); b.Palette = pal; } You can easily override this palette to specify other than grayscale images. We can likewise create a function that can convert an index to a System.Drawing.Color. If you are working with a grayscale image, there is probably no need for this.public System.Drawing.Color GetColorFromIndex(byte c) { return = myBitmap.Palette.Entries[c]; } Now let's put it all together into an easy-to-use 8bit image access class. Remember to allow unsafe code blocks before compiling.using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace ImageProc { /// /// Class used for direct memory access to 8bit grayscale images /// public class Image8Bit { private BitmapData bmd; private Bitmap b; /// /// Locks an 8bit image in memory for fast get/set pixel functions. /// Remember to Dispose object to release memory. /// /// Bitmap reference public Image8Bit (Bitmap bitmap) { if(bitmap.PixelFormat!=System.Drawing.Imaging.PixelFormat.Format8bppIndexed) throw(new System.Exception("Invalid PixelFormat. 8 bit indexed required")); b = bitmap; //Store a private reference to the bitmap bmd = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat); } /// /// Releases memory /// public void Dispose() { b.UnlockBits(bmd); } /// /// Gets color of an 8bit-pixel /// /// Row /// Column /// Color of pixel public unsafe System.Drawing.Color GetPixel(int x, int y) { byte* p = (byte *)bmd.Scan0.ToPointer(); //always assumes 8 bit per pixels int offset=y*bmd.Stride+x; return GetColorFromIndex(p[offset]); } /// /// Sets color of an 8bit-pixel /// /// Row /// Column /// Color index public unsafe void SetPixel(int x, int y, byte c) { byte* p = (byte *)bmd.Scan0.ToPointer(); //always assumes 8 bit per pixels int offset=y*bmd.Stride+(x); p[offset] = c; } /// /// Sets the palette for the referenced image to Grayscale /// public void MakeGrayscale() { SetGrayscalePalette(this.b); } /// /// Sets the palette of an image to grayscales (0=black, 255=white) /// /// Bitmap to set palette on public static void SetGrayscalePalette(Bitmap b) { ColorPalette pal = b.Palette; for(int i = 0; i < 256; i++) pal.Entries[i] = Color.FromArgb( 255, i, i, i ); b.Palette = pal; } private System.Drawing.Color GetColorFromIndex(byte c) { return = b.Palette.Entries[c]; } } }

阅读全文(3538) | 回复(0) | 编辑 | 精华

 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)

 
 



The Neurotic Fishbowl

.: 公告

暂无公告...


Bloginess

«June 2019»
1
2345678
9101112131415
16171819202122
23242526272829
30

.: 我的分类(专题)

首页(18)
数据结构/算法(0)
web design(0)
J2SDK(3)
C/C++(5)
设计模式(1)
基础知识(8)


In the Bowl

.: 最新日志

设计模式-各类模式简介
药品批号及条形码知识
ape cue 刻录
英文书信书写[转载]
Matlab
Using the LockBits m
Working with 8bit im
Using the LockBits m
VC6中如何使用GDI+ 最近的工作,需
Loading JPEG and GIF


.: 最新回复

回复:ASCII 编码表
回复:ASCII 编码表
回复:ASCII 编码表
回复:ASCII 编码表
回复:ASCII 编码表
回复:ASCII 编码表
回复:ASCII 编码表
回复:ape cue 刻录
回复:ASCII 编码表
回复:颜色空间FAQ


The Fishkeeper
blog名称:
日志总数:18
评论数量:86
留言数量:-1
访问次数:191887
建立时间:2005年7月17日



Text Me

.: 留言板

签写新留言

请大师帮忙


Other Fish in the Sea

.: 链接





站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.016 second(s), page refreshed 144282074 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号