C# 将 24 位 bmp 转换为 16 位?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2378690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:55:48  来源:igfitidea点击:

Convert 24-bit bmp to 16-bit?

c#image

提问by drowneath

I know that the .NET Framework comes with an image conversion class (the System.Drawing.Image.Save method).

我知道 .NET Framework 带有一个图像转换类(System.Drawing.Image.Save 方法)。

But I need to convert a 24-bit (R8G8B8) bitmap image to a 16-bit (X1R5G5B5) and I really got no idea on this kind of conversion, and a 24-to-16-bit change in the bmp header wouldn't work (since we need to convert the entire image data).

但是我需要将 24 位 (R8G8B8) 位图图像转换为 16 位 (X1R5G5B5) 并且我真的不知道这种转换,并且 bmp 标头中的 24 到 16 位更改不会t 工作(因为我们需要转换整个图像数据)。

Also I would like to know if I can control over the image Dither, etc.

另外我想知道我是否可以控制图像抖动等。

Ideas? Any kind of help would be appreciated.

想法?任何形式的帮助将不胜感激。

采纳答案by Hans Passant

The Format16bppRgb1555 pixel format is declared but GDI+ doesn't actually support it. There is no main-stream video driver or image codec that ever used that pixel format. Something that the GDI+ designers guessed couldhave happened, their time machine wasn't accurate enough. Otherwise a pretty sloppy copy/paste from the programmer that worked on System.Drawing.

Format16bppRgb1555 像素格式已声明,但 GDI+ 实际上并不支持它。没有使用过这种像素格式的主流视频驱动程序或图像编解码器。GDI+ 设计师猜测可能会发生一些事情,他们的时间机器不够准确。否则来自从事 System.Drawing 的程序员的相当草率的复制/粘贴。

Rgb555 is the closest match for available hardware and codecs:

Rgb555 是可用硬件和编解码器最接近的匹配:

public static Bitmap ConvertTo16bpp(Image img) {
    var bmp = new Bitmap(img.Width, img.Height,
                  System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
    using (var gr = Graphics.FromImage(bmp))
        gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
    return bmp;
}

回答by Dead account

You need to save the bitmap with an Encoderparameter specifying color depth.

您需要使用指定颜色深度的编码器参数保存位图。

    myEncoder = Encoder.ColorDepth;
    myEncoderParameters = new EncoderParameters(1);

    // Save the image with a color depth of 24 bits per pixel.
    myEncoderParameter = new EncoderParameter(myEncoder, 24L);
    myEncoderParameters.Param[0] = myEncoderParameter;

    myBitmap.Save("MyBitmap.bmp", myImageCodecInfo, myEncoderParameters);

回答by Blindy

A really straightforward way to do this is to loop over the old bitmap data and covert every pair of r8-g8-b8 values to x1-r5-g5-b5, something akin to this function:

一个非常直接的方法是循环旧位图数据并将每对 r8-g8-b8 值转换为 x1-r5-g5-b5,类似于此函数:

char condense(char i)
{ 
  return (char)(i*255.0f/31.0f);
}

short transform(long input)// note that the last 8 bytes are ignored
{
  return condense(input&0xff) || (condense((input&0xff00)>>8)<<5)
    || (condense((intput&0xff0000)>>16)<<10);
}

// and somewhere in your program
{
  int len; // the length of your data in pixels
  char *data; // your data
  char *newdata; // this is where you store the new data; make sure it's allocated

  for(char *p=data; p<data+len*3; p+=3)
    *(short *)newdata=transform(*(long *)data);
}