Форматы RGB в.NET Color

Я проверял документацию по цвету (я пишу программу на C#).

Если вы видите там, он устанавливает цвет на основе 8-битных значений RGB. Другими словами, это, я полагаю, формат RGB-888... Я думаю.

Я использую в своей камере формат RGB-565 (5 бит для R,B и 6 для G). Есть ли способ установить цвет на цвет, основанный на этом формате, а не на 888? Или я должен сделать это вручную сам?

1 ответ

Я недавно написал код для этой цели, основанный на универсальном конвертере цветовых форматов проекта ScummVM.

Ответ на другой вопрос здесь, на Stackru, и, хотя вопрос на самом деле не является дубликатом, я думаю, что ответ есть, поэтому я просто сделаю ссылку на него:

Работа с цифровым изображением глубиной 10 бит

Имейте в виду, я не уверен точно, как множитель для каждого фактора работает в формате 5-6-5. Является ли 6-битный компонент просто более точным? В этом случае, автоматизированная система преобразования сделает эту работу.

В любом случае, с кодом, приведенным выше, этот пример должен идеально соответствовать вашим потребностям. Здесь он используется для преобразования пользовательского формата 5-5-5-1 RGBA:

//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;
}

Все, что вам нужно сделать, это определить свой собственный PixelFormatter с правильным распределением битов для формата 5-6-5.

Вам действительно нужно будет заглянуть в Bitmap.LockBits() получить исходные 16-битные данные из изображения и записать эти данные в новое 32-битное ARGB-изображение. мой BuildImage Функция, упомянутая в этом ответе, должна показать, как справиться с написанием. Метод read на самом деле намного проще:

/// <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;
}

Обратите внимание, что во всех ситуациях, когда вы редактируете необработанные байты изображения, разница между "шагом" и "шириной". Во многих форматах одна строка пикселей на изображении дополняется до следующей кратности четырех байтов, поэтому вы не можете просто прочитать и обработать его как массив, предполагая, что это все данные изображения; эти байты заполнения очень быстро это испортят. Как показано в моем примере кода для преобразования моего формата 16bpp в ARGB, вам действительно нужно делать это построчно, и для каждой строки убедитесь, что вы используете только те данные, которые все еще находятся в диапазоне (ширина * байт на пиксель).

Я заметил, что для всех функций, которые могут изменить шаг, рекомендуется дать его как ref параметр.

Другие вопросы по тегам