如何在C / C ++中将12位图像转换为8位?

好吧,所以我一直非常沮丧地尝试将12位缓冲区转换为8位缓冲区。 图像源是12位GrayScale(从JPEG2000解压缩),其颜色范围为0-4095。 现在我必须将其减少到0-255。 常识告诉我,我应该像这样简单地划分每个像素值。 但是当我尝试这个时,图像太亮了。

void TwelveToEightBit( unsigned char * charArray, unsigned char * shortArray, const int num ) { short shortValue = 0; //Will contain the two bytes in the shortArray. double doubleValue = 0; //Will contain intermediary calculations. for( int i = 0, j =0; i < num; i++, j +=2 ) { // Bitwise manipulations to fit two chars onto one short. shortValue = (shortArray[j]<<8); shortValue += (shortArray[j+1]); charArray[i] = (( unsigned char)(shortValue/16)); } } 

现在我可以说需要进行一些对比度调整。 任何人的想法?

提前谢谢了

实际上,只需要进行一些简单的对比度调整。 我在Photoshop中加载结果图像并进行自动对比后就意识到了这一点……图像结果非常类似于预期的输出图像。 我找到了一个算法来做对比,并将其张贴在这里为了方便起见:

 #include  short shortValue = 0; //Will contain the two bytes in the shortBuffer. double doubleValue = 0; //Will contain intermediary calculations. //Contrast adjustment necessary when converting //setting 50 as the contrast seems to be real sweetspot. double contrast = pow( ((100.0f + 50.0f) / 100.0f), 2); for ( int i = 0, j =0; i < num; i++, j += 2 ) { //Bitwise manipulations to fit two chars onto one short. shortValue = (shortBuffer[j]<<8); shortValue += (shortBuffer[j+1]); doubleValue = (double)shortValue; //Divide by 16 to bring down to 0-255 from 0-4095 (12 to 8 bits) doubleValue /= 16; //Flatten it out from 0-1 doubleValue /= 255; //Center pixel values at 0, so that the range is -0.5 to 0.5 doubleValue -= 0.5f; //Multiply and just by the contrast ratio, this distances the color //distributing right at the center....see histogram for further details doubleValue *= contrast; //change back to a 0-1 range doubleValue += 0.5f; //and back to 0-255 doubleValue *= 255; //If the pixel values clip a little, equalize them. if (doubleValue >255) doubleValue = 255; else if (doubleValue<0) doubleValue = 0; //Finally, put back into the char buffer. charBuffer[i] = (( unsigned char)(doubleValue)); } 

据我所知,主要问题是将12位值转换为8位值。

 Range of 12-bit value = 0 - 4095 (4096 values) Range of 8-bit value = 0 - 255 ( 256 values) 

我会尝试将12位值x转换为8位值y

  1. 首先,首先缩小到0-1的范围,然后
  2. 然后,扩展到0-256范围。

一些C-ish代码:

 uint16_t x = some_value; uint8_t y = (uint8_t) ((double) x/4096 ) * 256; 

更新

感谢Kriss的评论,我意识到我无视速度问题。 由于浮动操作,上述解决方案可能比纯整数操作慢。

然后我开始考虑其他解决方案。 用x8最高有效位构造y怎么样? 换句话说,通过削减4最低有效位。

 y = x >> 4; 

这会有用吗?

如果您只想删除底部的4个最低有效位,您可以执行以下操作:

 unsigned int start_value = SOMEVALUE; // starting value value = (value & 0xFF0 ); // drop bits unsigned char final_value =(uint8_t)value >> 4; //bit shift to 8 bits 

注意“未签名”。 您不希望签名位与您的值混淆。

像这样:

 // Image is stored in 'data' unsigned short* I = (unsigned short*)data; for(int i=0; i 

狂野猜测:你的代码假设一个大端机器(最重要的字节优先)。 Windows PC是小端的。 所以也许试试吧

  shortValue = (shortArray[j+1]<<8); shortValue += (shortArray[j]); 

如果确实是endiasness是问题,那么您提供的代码将削减每个值的4个最重要位,并将其余部分扩展到强度范围。 嗯,编辑,2秒后:不,这是一个思考。 但是还是试试呢?

干杯&hth。,

- 阿尔夫