简体   繁体   中英

RGB formats in .NET Color

I have been checking the documentation on Color (I am writing a C# program) Setting a color to Color

If you see there, it sets a color based on 8-bit values of RGB. In other words, this is I suppose a RGB-888 format...I guess.

I am using in my camera a RGB-565 format (5 bits for R,B and 6 for G) Is there a way to set Color to a color based on this format and not 888? Or do I have to do this manually myself?

I have recently written code to do exactly that, based on the generic colour format converter of the ScummVM project .

The answer is on a different question here on StackOverflow, and although the question isn't really a duplicate, I think, the answer is, so I'll just link to it:

Working with 10 bits depth digital image

Mind you, I'm not sure exactly how the multiplier for each factor works on the 5-6-5 format. Is the 6-bit component simply more accurate? In that case, the automated conversion system will do the job.

Anyway, with the code linked above, this example should suit your needs perfectly. Here it is used to convert a custom 5-5-5-1 RGBA format:

//bytes 84 21 ==> 0x8421 (BE) ==bin==> 1000 0100 0010 0001 ==split==> 10000 10000 10000 1 ==dec==> 16 16 16 1 (RGBA) ==adjust==> 128 128 128 255
// values in constructor are: bytes per pixel, amount of bits and amount to shift for getting R, G, B and A components, and data endianness.
private static PixelFormatter SixteenBppFormatter = new PixelFormatter(2, 5, 11, 5, 6, 5, 1, 1, 0, false);

protected static Byte[] Convert16bTo32b(Byte[] imageData, Int32 startOffset, Int32 width, Int32 height, ref Int32 stride)
{
    Int32 newImageStride = width * 4; ;
    Byte[] newImageData = new Byte[height * newImageStride];
    for (Int32 y = 0; y < height; y++)
    {
        for (Int32 x = 0; x < width; x++)
        {
            Int32 sourceOffset = y * stride + x * 2;
            Int32 targetOffset = y * newImageStride + x * 4;
            Color c = SixteenBppFormatter.GetColor(imageData, startOffset + sourceOffset);
            PixelFormatter.Format32BitArgb.WriteColor(newImageData, targetOffset, c);
        }
    }
    stride = newImageStride;
    return newImageData;
}

All you need to do is define your own PixelFormatter with the correct bits distribution for the 5-6-5 format.

You will indeed need to look into Bitmap.LockBits() to get the original 16-bit data out of the image, and to write that data into a new 32-bit ARGB image. My BuildImage function mentioned in this answer should show how to handle the writing. The read method is actually a lot simpler:

/// <summary>
/// Gets the raw bytes from an image.
/// </summary>
/// <param name="sourceImage">The image to get the bytes from.</param>
/// <param name="stride">Stride of the retrieved image data.</param>
/// <returns>The raw bytes of the image</returns>
public static Byte[] GetImageData(Bitmap sourceImage, out Int32 stride)
{
    BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, sourceImage.PixelFormat);
    stride = sourceData.Stride;
    Byte[] data = new Byte[stride * sourceImage.Height];
    Marshal.Copy(sourceData.Scan0, data, 0, data.Length);
    sourceImage.UnlockBits(sourceData);
    return data;
}

Do note, in all situations where you edit raw image bytes, the difference between "stride" and "width". In a lot of formats, one line of pixels in an image is padded to the next multiple of four bytes, so you can't just read and process it as array assuming it's all image data; those padding bytes will mess that up really quickly. As shown in my example code to convert my 16bpp format to ARGB, you really need to do that line by line, and per line make sure you only use the data that is still within the (width * bytes per pixel) range.

I've noticed that for all functions that may change the stride, it's advised to give it as ref parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM