http://coderepos.org/share/browser/lang/cpluspluscli/OpenCvSharp2/trunk/OpenCvSharp/Converter/BitmapConverter.cs?rev=31149
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace KwsmLab.OpenCvSharp
{
public static class BitmapConverter
{
#region ToIplImage
public static IplImage ToIplImage(this Bitmap bitmap)
{
if(bitmap == null){
throw new ArgumentNullException("bitmap");
}
int w = bitmap.Width;
int h = bitmap.Height;
BitDepth depth = BitDepth.U8;
int channels;
switch(bitmap.PixelFormat){
case PixelFormat.Format24bppRgb:
channels = 3; break;
case PixelFormat.Format32bppArgb:
channels = 4; break;
case PixelFormat.Format8bppIndexed:
case PixelFormat.Format1bppIndexed:
channels = 1; break;
default:
throw new NotImplementedException();
}
IplImage ipl = Cv.CreateImage(new CvSize(w, h), depth, channels);
Rectangle rect = new Rectangle(0, 0, w, h);
BitmapData bd = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
unsafe
{
byte* p = (byte*)bd.Scan0.ToPointer();
int stride = bd.Stride;
int offset = stride - (w / 8);
int widthStep = ipl.WidthStep;
byte* imageData = (byte*)ipl.ImageData.ToPointer();
switch (bitmap.PixelFormat)
{
case PixelFormat.Format1bppIndexed:
{
int x = 0;
int y;
int byte_pos;
byte b;
int i;
for (y = 0; y < h; y++)
{
// 横は必ず4byte幅に切り上げられる。
// この行の各バイトを調べていく
for (byte_pos = 0; byte_pos < stride; byte_pos++)
{
if (x < w)
{
// 現在の位置のバイトからそれぞれのビット8つを取り出す
b = p[byte_pos];
for (i = 0; i < 8; i++)
{
if (x >= w)
{
break;
}
// IplImageは8bit/pixel
imageData[widthStep * y + x] = ((b & 0x80) == 0x80) ? (byte)255 : (byte)0;
b <<= 1;
x++;
}
}
}
// 次の行へ
x = 0;
p += stride;
}
}
break;
case PixelFormat.Format8bppIndexed:
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
imageData[y * widthStep + x] = p[y * stride + x];
}
}
}
break;
case PixelFormat.Format24bppRgb:
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
imageData[y * widthStep + x * 3] = p[y * stride + x * 3];
imageData[y * widthStep + x * 3 + 1] = p[y * stride + x * 3 + 1];
imageData[y * widthStep + x * 3 + 2] = p[y * stride + x * 3 + 2];
}
}
}
break;
case PixelFormat.Format32bppArgb:
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
imageData[y * widthStep + x * 4] = p[y * stride + x * 4];
imageData[y * widthStep + x * 4 + 1] = p[y * stride + x * 4 + 1];
imageData[y * widthStep + x * 4 + 2] = p[y * stride + x * 4 + 2];
imageData[y * widthStep + x * 4 + 3] = p[y * stride + x * 4 + 3];
}
}
}
break;
}
}
bitmap.UnlockBits(bd);
return ipl;
}
#endregion
#region ToBitmap
public static Bitmap ToBitmap(this IplImage src)
{
if(src == null)
{
throw new ArgumentNullException("src");
}
PixelFormat pf;
switch(src.NChannels){
case 1:
pf = PixelFormat.Format8bppIndexed; break;
case 3:
pf = PixelFormat.Format24bppRgb; break;
case 4:
pf = PixelFormat.Format32bppArgb; break;
default:
throw new ArgumentOutOfRangeException("チャンネル数は 1, 3, 4 の場合み対応しています。");
}
return ToBitmap(src, pf);
}
public static Bitmap ToBitmap(this IplImage src, PixelFormat pf)
{
if(src == null)
{
throw new ArgumentNullException("src");
}
if(src.Depth != BitDepth.U8){
throw new ArgumentOutOfRangeException("ビット深度は BitDepth.U8 のみ対応しています。");
}
Bitmap bitmap = new Bitmap(src.Width, src.Height, pf);
ToBitmap(src, bitmap);
return bitmap;
}
public static void ToBitmap(IplImage src, Bitmap dst)
{
if (src == null)
throw new ArgumentNullException("src");
if (dst == null)
throw new ArgumentNullException("dst");
if(src.Depth != BitDepth.U8){
throw new ArgumentOutOfRangeException("ビット深度は BitDepth.U8 のみ対応しています。");
}
PixelFormat pf = dst.PixelFormat;
// 1プレーン用の場合、グレースケールのパレット情報を生成する
if(pf == PixelFormat.Format8bppIndexed){
ColorPalette plt = dst.Palette;
for(int x=0; x<256; x++){
plt.Entries[x] = System.Drawing.Color.FromArgb(x, x, x);
}
dst.Palette = plt;
}
unsafe
{
int w = src.Width;
int h = src.Height;
Rectangle rect = new Rectangle(0, 0, w, h);
BitmapData bd = dst.LockBits(rect, ImageLockMode.WriteOnly, pf);
byte* psrc = (byte*)(src.ImageData.ToPointer());
byte* pdst = (byte*)(bd.Scan0.ToPointer());
int widthStep = src.WidthStep;
int stride = bd.Stride;
switch(pf){
case PixelFormat.Format1bppIndexed:
{
// BitmapDataは4bytes幅だが、IplImageは1byte幅
// 手作業で移し替える
int offset = stride - (w / 8);
int x = 0;
int y;
int byte_pos;
byte mask;
byte b = 0;
int i;
for (y = 0; y < h; y++)
{
for (byte_pos = 0; byte_pos < stride; byte_pos++)
{
if (x < w)
{
for (i = 0; i < 8; i++)
{
mask = (byte)(0x80 >> i);
if (x < w && psrc[widthStep * y + x] == 0)
b &= (byte)(mask ^ 0xff);
else
b |= mask;
x++;
}
pdst[byte_pos] = b;
}
}
x = 0;
pdst += stride;
}
break;
}
case PixelFormat.Format8bppIndexed:
case PixelFormat.Format24bppRgb:
case PixelFormat.Format32bppArgb:
Win32API.CopyMemory(pdst, psrc, src.ImageSize);
break;
}
dst.UnlockBits(bd);
// 反転対策
if(src.Origin == 1){
dst.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
}
}
#endregion
}
}
2009年6月1日星期一
订阅:
博文评论 (Atom)
没有评论:
发表评论