Как конвертировать 12-битное изображение в 8-битное в C / C ++? - PullRequest
3 голосов
/ 13 октября 2010

Хорошо, поэтому я очень расстроился, пытаясь преобразовать 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));
    }
}

Теперь я могу сказать, что должны быть некоторые настройки контрастности.Любые идеи кто-нибудь?

Большое спасибо заранее

Ответы [ 5 ]

2 голосов
/ 13 октября 2010

В действительности, это были просто некоторые простые настройки контрастности, которые нужно было сделать.Я понял это, как только я загрузил результирующее изображение в Photoshop и сделал автоконтраст ... результат будет очень похож на ожидаемое выходное изображение.Я нашел алгоритм, который делает контраст и опубликует его здесь для удобства других:

#include <math.h>

 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));


 }
0 голосов
/ 16 июня 2015

Как это:

// Image is stored in 'data'
unsigned short* I = (unsigned short*)data;

for(int i=0; i<imageSize; i++) {
// 'color' is the 8-bit value  
   char color = (char)((double)(255*I[i])/(double)(1<<12));
   /*...*/ 
}
0 голосов
/ 06 мая 2012

если вы просто хотите отбросить младшие 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

Обратите внимание на «без знака». Вы не хотите, чтобы подписанный бит смешивался с вашими значениями.

0 голосов
/ 13 октября 2010

Основная проблема, как я понимаю, заключается в преобразовании 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 я понял, что яоставил без внимания скорость вопроса.Вышеупомянутое решение из-за операций с плавающей запятой может быть медленнее, чем операции с целыми числами.

Затем я начал рассматривать другое решение.Как насчет построения y с 8 старшими значащими битами x?Другими словами, обрезая 4 младшие значащие биты.

y = x >> 4;

Будет ли это работать?

0 голосов
/ 13 октября 2010

Дикая догадка: в вашем коде используется машина с прямым порядком байтов (сначала старший байт).ПК с Windows имеет младший порядок.Так что, возможно, попробуйте

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

Если действительно проблема заключается в бесконечности, то код, который вы представили, просто сбрил бы 4 наиболее значимых бита каждого значения и расширил бы остальные до диапазона интенсивности.Хм, РЕДАКТИРОВАТЬ, через 2 секунды: нет, это был Thinko.Но все равно попробуйте?

Приветствия & hth.,

- Alf

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...