像素数据到图像

本文关键字:图像 数据 像素数 像素 | 更新日期: 2023-09-27 18:10:23

我有这个格式的列表像素

ArrayList list = new ArrayList();
list.add(Red);
list.add(Blue);
list.add(Green);

我有很多这样的价值观。我想把数组列表转换成image..试了很多,但没有找到合适的材料。

EDIT:这可能有帮助:

List<byte> pic = new List<byte>(); 
for (int j = 0; j < headdata.Count; j++)
{ 
    if(headdata.ElementAt(j).getHead() == i) 
    { 
        pic.Add((byte)headdata.ElementAt(j).getRed());
        pic.Add((byte)headdata.ElementAt(j).getGreen());
        pic.Add((byte)headdata.ElementAt(j).getBlue()); 
    }
} 

像素数据到图像

更新

我想我应该改进这个答案以供将来参考。

将像素存储为一个无符号32位整数数组(c# uint)可能更方便(也更高效)。这允许每个像素的4个通道(alpha,红色,绿色和蓝色)一次设置。如果您对使用alpha通道(用于透明度)不感兴趣,请参阅下面代码片段中关于像素格式的注释。

表示颜色的方式现在是32位数字,如0xff0000,你可以识别为类似于CSS十六进制颜色值。

// Image dimensions.
var width = 640;
var height = 480;
// Array to contain pixel data, with each element representing one pixel.
var pixelBuffer = new uint[width * height];
// When creating the bitmap, the operating system needs to be told the memory
// address of the pixel data array created above. This memory address can be
// found using a pinned GC handle, which also tells the GC (garbage collector)
// that it cannot move the array in memory after this point (as that would
// change the memory address).
//
// Note that the handle prevents the GC from freeing the object automatically,
// so remember to call the handle's `Free` method once finished (see below). 
var pixelBufferHandle = GCHandle.Alloc(pixelBuffer, GCHandleType.Pinned);
// Create the bitmap using a constructor that takes a pointer to the array of
// pixel data:
//
// The `width` and `height` parameters are the image dimensions in pixels.
// These should match the values used above.
//
// The `stride` parameter specifies the number of _bytes_ required for each row
// of image data. Calculate this by multiplying the image's width by the number
// of bytes per pixel (here that's `sizeof(uint)`).
//
// The `format` parameter specifies how the colour data of each pixel is stored
// in the pixel data array:
//    - For 32-bit RGB colour, use `Format32bppPArgb`. This signifies that the
//      alpha channel is present (i.e. each pixel is 4 bytes) but should be
//      ignored. Each pixel will be 100% opaque, and the alpha can be zero.
//    - For 32-bit ARGB colour, use `Format32bppArgb`. Each pixel will be drawn
//      opaque, semi-transparent, or fully transparent based on the alpha.
//
// The `scan0` parameter takes a pointer to the pixel data - use the GC handle
// created above to acquire the address of the array object.
var bitmap = new Bitmap(
    width:  width,
    height: height,
    stride: width * sizeof(uint),
    format: PixelFormat.Format32bppPArgb,
    scan0:  pixelBufferHandle.AddrOfPinnedObject()
);
// At this point, the pixel data array can be freely manipulated independently
// of the bitmap. Each time the bitmap is draw, it will reflect the current
// content of the pixel data array.
// Once finished...
// Free the GC handle, allowing the GC to free the object automatically.
gchPixels.Free();

您可以创建用于读取和写入特定坐标像素的函数:

uint GetPixel(int x, int y) => pixels[x + y * width];
void SetPixel(int x, int y, uint argb) => pixels[x + y * width] = argb;

starbeamrainbowlabs指出:

GCHandleBitmapPixelFormat分别存在于System.Runtime.InteropServicesSystem.DrawingSystem.Drawing.Imaging中。

有一种很好的方法可以做到这一点,但它要求您使用数组或字节,而不是列表。

考虑一下:

// Define the width and the height of the image
int width = 100;
int height = 100;
/// Create an array of bytes consisting of the area's worth of pixels
/// with 3 bytes of data each.
byte[] pixels = new byte[width * height * 3];
/* ... Code for making the image etc. here ... */
// Create the bitmap.
// GCHandle requires System.Runtime.InteropServices
/// PixelFormat requires System.Drawing.Imaging.
Bitmap bmp = new Bitmap(width, height, width * 3, PixelFormat.Format24bppRgb,
                        GCHandle.Alloc(pixels, GCHandleType.Pinned).AddrOfPinnedObject());

如果您想将其更改为ARGB,只需将'3'的所有实例更改为'4',并使用PixelFormat.Format32bppArgb.

就像我说的,这要求你使用数组而不是列表,但是这个只要你知道图像的宽度和高度,应该不会太难。在数组中设置单个像素的一个好方法是(也许是创建一个方法对于这个):

pixels[x + y * width]     = R;
pixels[x + y * width + 1] = G;
pixels[x + y * width + 2] = B;

这个方法通常也是相当快的,如果有必要的话做什么。

首先,正如我在评论中所说,最好使用List而不是ArrayList,以避免装箱/拆箱。

然后,您需要bpp(每像素位)和宽度高度来创建图像。

如果你有所有这些值,那么你可以开始像素索引:

int i = ((y * Width) + x) * (depth / 8);
例如:

    List<byte> bytes = new List<byte>(); // this list should be filled with values
    int width = 100;
    int height = 100;
    int bpp = 24;
    Bitmap bmp = new Bitmap(width, height);
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {   
            int i = ((y * width) + x) * (bpp / 8);
            if(bpp == 24) // in this case you have 3 color values (red, green, blue)
            {
                 // first byte will be red, because you are writing it as first value
                 byte r = bytes[i]; 
                 byte g = bytes[i + 1]; 
                 byte b = bytes[i + 2]; 
                 Color color = Color.FromArgb(r, g, b);
                 bmp.SetPixel(x, y, color); 
            }
        }
    }

您可以使用其他库来更快地创建位图和写入值。(SetPixel()非常慢。看到)