I'm currently writing a C# implementation of a little program which I have written in Java.
我现在正在编写一个用Java编写的小程序的c#实现。
I had used BufferedImage.getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
function in my Java app. But I couldn't exactly find a version of this in C# and I am not sure how to write it manually.
我有BufferedImage使用。getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)函数在我的Java应用程序中,但我无法在c#中找到这个版本,我也不知道怎么手动写。
5 个解决方案
#1
17
There's not a direct equivalent in the .NET Framework to this method. However, if your image is a System.Drawing.Bitmap, you can call the LockBits method, and this will return a BitmapData structure that contains the address of the first scanline. You can then use it to create what should be an API-compatible wrapper. I'm assuming you're using C# 3.5 or greater, so I'm using an extension method - if you're using an older flavor, change this to a regular method by dropping the 'this' from the Bitmap argument:
这个方法在。net框架中没有直接的等效项。但是,如果你的图像是一个系统。位图,您可以调用LockBits方法,这将返回一个包含第一个扫描线地址的位图数据结构。然后您可以使用它来创建一个与api兼容的包装器。我假设你使用的是c# 3.5或者更大,所以我使用的是扩展方法——如果你使用的是更老的味道,请将它从位图参数中去掉,改为常规方法:
public static void getRGB(this Bitmap image, int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
{
const int PixelWidth = 3;
const PixelFormat PixelFormat = PixelFormat.Format24bppRgb;
// En garde!
if (image == null) throw new ArgumentNullException("image");
if (rgbArray == null) throw new ArgumentNullException("rgbArray");
if (startX < 0 || startX + w > image.Width) throw new ArgumentOutOfRangeException("startX");
if (startY < 0 || startY + h > image.Height) throw new ArgumentOutOfRangeException("startY");
if (w < 0 || w > scansize || w > image.Width) throw new ArgumentOutOfRangeException("w");
if (h < 0 || (rgbArray.Length < offset + h * scansize) || h > image.Height) throw new ArgumentOutOfRangeException("h");
BitmapData data = image.LockBits(new Rectangle(startX, startY, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat);
try
{
byte[] pixelData = new Byte[data.Stride];
for (int scanline = 0; scanline < data.Height; scanline++)
{
Marshal.Copy(data.Scan0 + (scanline * data.Stride), pixelData, 0, data.Stride);
for (int pixeloffset = 0; pixeloffset < data.Width; pixeloffset++)
{
// PixelFormat.Format32bppRgb means the data is stored
// in memory as BGR. We want RGB, so we must do some
// bit-shuffling.
rgbArray[offset + (scanline * scansize) + pixeloffset] =
(pixelData[pixeloffset * PixelWidth + 2] << 16) + // R
(pixelData[pixeloffset * PixelWidth + 1] << 8) + // G
pixelData[pixeloffset * PixelWidth]; // B
}
}
}
finally
{
image.UnlockBits(data);
}
}
This wrapper can now be called like this:
这个包装器现在可以这样称呼:
Bitmap foo = Bitmap.FromFile(@"somefile.jpg") as Bitmap;
int[] rgbArray = new int[100];
foo.getRGB(1, 1, 10, 10, rgbArray, 0, 10);
Hope this helps, and welcome to .NET!
希望这能有所帮助,欢迎来到。net !
#2
6
You'd use Bitmap.LockBits to get direct access to the pixels in a bitmap. Here's a sample implementation, it returns one scanline from the passed bitmap as an int[]:
可以使用位图。锁定位可以直接访问位图中的像素。这里是一个示例实现,它将从传递的位图返回一个scanline作为int[]:
int[] getRGB(Bitmap bmp, int line) {
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try {
var ptr = (IntPtr)((long)data.Scan0 + data.Stride * (bmp.Height - line - 1));
var ret = new int[bmp.Width];
System.Runtime.InteropServices.Marshal.Copy(ptr, ret, 0, ret.Length * 4);
return ret;
}
finally {
bmp.UnlockBits(data);
}
}
#3
2
I think the closest one is Bitmap.GetPixel(x,y)
that return a single pixel color at a point. In order to simulate the java function, you will need to write some helper.
我认为最近的一个是位图. getpixel (x,y),它在一个点上返回一个像素颜色。为了模拟java函数,您需要编写一些helper。
#4
2
You may need to check
你可能需要检查一下。
- Bitmap.GetPixel
- Bitmap.GetPixel
- Bitmap.LockBits
- Bitmap.LockBits
Also check Converting an array of Pixels to an image in C#.
还可以检查在c#中将一个像素数组转换为一个图像。
#5
1
It depends how fast you need to do it.
这取决于你需要多快。
Bitmap
has GetPixel()
method which works fine for a pixel.
位图有GetPixel()方法,它适用于像素。
If you need to do fast image processing you need to use LockBits
which you can find a sample here.
如果你需要做快速的图像处理,你需要使用LockBits,你可以在这里找到一个样本。
Bitmap img = (Bitmap) Image.FromFile(imageFileName);
BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat);
byte* ptr = (byte*) data.Scan0;
for (int j = 0; j < data.Height; j++)
{
byte* scanPtr = ptr + (j * data.Stride);
for (int i = 0; i < data.width; i++, scanPtr+=NO_OF_CHANNELS)
{
for (int m = 0; m < NO_OF_CHANNELS; m++)
Console.WriteLine(*scanPtr); // value of each channel
}
}
img.UnlockBits(data);
#1
17
There's not a direct equivalent in the .NET Framework to this method. However, if your image is a System.Drawing.Bitmap, you can call the LockBits method, and this will return a BitmapData structure that contains the address of the first scanline. You can then use it to create what should be an API-compatible wrapper. I'm assuming you're using C# 3.5 or greater, so I'm using an extension method - if you're using an older flavor, change this to a regular method by dropping the 'this' from the Bitmap argument:
这个方法在。net框架中没有直接的等效项。但是,如果你的图像是一个系统。位图,您可以调用LockBits方法,这将返回一个包含第一个扫描线地址的位图数据结构。然后您可以使用它来创建一个与api兼容的包装器。我假设你使用的是c# 3.5或者更大,所以我使用的是扩展方法——如果你使用的是更老的味道,请将它从位图参数中去掉,改为常规方法:
public static void getRGB(this Bitmap image, int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
{
const int PixelWidth = 3;
const PixelFormat PixelFormat = PixelFormat.Format24bppRgb;
// En garde!
if (image == null) throw new ArgumentNullException("image");
if (rgbArray == null) throw new ArgumentNullException("rgbArray");
if (startX < 0 || startX + w > image.Width) throw new ArgumentOutOfRangeException("startX");
if (startY < 0 || startY + h > image.Height) throw new ArgumentOutOfRangeException("startY");
if (w < 0 || w > scansize || w > image.Width) throw new ArgumentOutOfRangeException("w");
if (h < 0 || (rgbArray.Length < offset + h * scansize) || h > image.Height) throw new ArgumentOutOfRangeException("h");
BitmapData data = image.LockBits(new Rectangle(startX, startY, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat);
try
{
byte[] pixelData = new Byte[data.Stride];
for (int scanline = 0; scanline < data.Height; scanline++)
{
Marshal.Copy(data.Scan0 + (scanline * data.Stride), pixelData, 0, data.Stride);
for (int pixeloffset = 0; pixeloffset < data.Width; pixeloffset++)
{
// PixelFormat.Format32bppRgb means the data is stored
// in memory as BGR. We want RGB, so we must do some
// bit-shuffling.
rgbArray[offset + (scanline * scansize) + pixeloffset] =
(pixelData[pixeloffset * PixelWidth + 2] << 16) + // R
(pixelData[pixeloffset * PixelWidth + 1] << 8) + // G
pixelData[pixeloffset * PixelWidth]; // B
}
}
}
finally
{
image.UnlockBits(data);
}
}
This wrapper can now be called like this:
这个包装器现在可以这样称呼:
Bitmap foo = Bitmap.FromFile(@"somefile.jpg") as Bitmap;
int[] rgbArray = new int[100];
foo.getRGB(1, 1, 10, 10, rgbArray, 0, 10);
Hope this helps, and welcome to .NET!
希望这能有所帮助,欢迎来到。net !
#2
6
You'd use Bitmap.LockBits to get direct access to the pixels in a bitmap. Here's a sample implementation, it returns one scanline from the passed bitmap as an int[]:
可以使用位图。锁定位可以直接访问位图中的像素。这里是一个示例实现,它将从传递的位图返回一个scanline作为int[]:
int[] getRGB(Bitmap bmp, int line) {
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try {
var ptr = (IntPtr)((long)data.Scan0 + data.Stride * (bmp.Height - line - 1));
var ret = new int[bmp.Width];
System.Runtime.InteropServices.Marshal.Copy(ptr, ret, 0, ret.Length * 4);
return ret;
}
finally {
bmp.UnlockBits(data);
}
}
#3
2
I think the closest one is Bitmap.GetPixel(x,y)
that return a single pixel color at a point. In order to simulate the java function, you will need to write some helper.
我认为最近的一个是位图. getpixel (x,y),它在一个点上返回一个像素颜色。为了模拟java函数,您需要编写一些helper。
#4
2
You may need to check
你可能需要检查一下。
- Bitmap.GetPixel
- Bitmap.GetPixel
- Bitmap.LockBits
- Bitmap.LockBits
Also check Converting an array of Pixels to an image in C#.
还可以检查在c#中将一个像素数组转换为一个图像。
#5
1
It depends how fast you need to do it.
这取决于你需要多快。
Bitmap
has GetPixel()
method which works fine for a pixel.
位图有GetPixel()方法,它适用于像素。
If you need to do fast image processing you need to use LockBits
which you can find a sample here.
如果你需要做快速的图像处理,你需要使用LockBits,你可以在这里找到一个样本。
Bitmap img = (Bitmap) Image.FromFile(imageFileName);
BitmapData data = img.LockBits(new Rectangle(0,0,img.Width, img.Height), ImageLockMode.ReadWrite, img.PixelFormat);
byte* ptr = (byte*) data.Scan0;
for (int j = 0; j < data.Height; j++)
{
byte* scanPtr = ptr + (j * data.Stride);
for (int i = 0; i < data.width; i++, scanPtr+=NO_OF_CHANNELS)
{
for (int m = 0; m < NO_OF_CHANNELS; m++)
Console.WriteLine(*scanPtr); // value of each channel
}
}
img.UnlockBits(data);