Сохранение оттенков серого в CMYK с использованием libjpeg в c

Если эта функция делает то, что я думаю, то кажется, что на моей машине по крайней мере в CMYK C=0, M=0, Y=0 и K=0 не соответствует белому! В чем проблема?

float *arr — это массив с плавающей запятой, состоящий из size элементов. Я хочу сохранить этот массив в формате JPEG с libjpeg IJG в двух цветовых пространствах по требованию: g: Шкала серого и c: CMYK. Я следую их примеру и делаю входной массив JSAMPLE *jsr с количеством JSAMPLE элементов в зависимости от цветового пространства: size элементов для шкалы серого и 4*size элементов для CMYK. JSAMPLE — это просто другое имя для unsigned char, по крайней мере, на моей машине. Полную программу можно увидеть на Github. Вот как я заполняю jsr:

void
floatfilljsarr(JSAMPLE *jsr, float *arr, size_t size, char color)
{
  size_t i;
  double m;
  float min, max;

  /* Find the minimum and maximum of the array:*/
  fminmax(arr, size, &min, &max);
  m=(double)UCHAR_MAX/((double)max-(double)min);

  if(color=='g')
    {
      for(i=0;i<size;i++)
        jsr[i]=(arr[i]-min)*m;
    }
  else
    for(i=0;i<size;i++)
      {
        jsr[i*4+3]=(arr[i]-min)*m;
        jsr[i*4]=jsr[i*4+1]=jsr[i*4+2]=0;
      }
}

Я должен отметить, что color перед этой функцией было проверено либо на c, либо на g. Затем я записываю изображение в формате JPEG точно так же, как программа example.c в исходном коде libjpeg.

Вот результат после печати обоих изображений в документе TeX. Оттенки серого слева, а CMYK справа. Оба изображения сделаны из одного и того же упорядоченного массива, поэтому нижний левый элемент (первый в массиве, как я его определил и отобразил здесь) имеет значение JSAMPLE 0, а верхний правый элемент имеет значение JSAMPLE 255.

сравнение оттенков серого (слева) и CMYK (справа).

Почему эти два изображения не похожи? Из-за другой природы я ожидаю, что изображение CMYK будет перевернутым: его нижняя часть будет яркой, а верхняя - черной. Их отображаемые значения JSAMPLE (единственное значение в оттенках серого и канал K в CMYK) идентичны, но я получаю не то, что ожидал! Изображение CMYK также ярче кверху, но очень слабо!

Кажется, что C=0, M=0, Y=0 и K=0 не соответствуют белому по крайней мере с этим алгоритмом и на моей машине!?! Как я могу установить белый цвет, когда мне нужно изменить только канал K, а остальные оставить равными нулю?


person makhlaghi    schedule 17.04.2014    source источник


Ответы (2)


Попробуйте инвертировать ваш K-канал:

       jsr[i*4+3]= (m - ((arr[i]-min)*m);
person Shawn C    schedule 17.04.2014
comment
Спасибо, я инвертировал изображение, вычитая каждое значение из UCHAR_MAX, потому что (arr[i]-min)*m находится между 0 и UCHAR_MAX. Я обновил вопрос. Он все еще не становится таким четким, как оттенки серого. - person makhlaghi; 17.04.2014
comment
Убедитесь, что белый цвет представлен как 0 для CYMK, а черный — как UCHAR_MAX. Я думаю, что ваша исходная формула оттенков серого (которая на самом деле является RGB, где R = G = B) была немного другой и точно отображала ваши {min, max} в диапазоне 0..UCHAR_MAX. - person Shawn C; 17.04.2014
comment
Спасибо, но как я могу убедиться, что CMYK определяет черный и белый? - person makhlaghi; 17.04.2014
comment
CMYK белый: C=0, M=0, Y=0, K=0; CMYK черный: C/M/Y (на самом деле не определено, но 0 экономит чернила), K={максимум}. Поскольку вы работаете с оттенками серого, вы можете думать о канале K как о противоположности оттенкам серого (RGB). В зависимости от того, как вы используете данные, не исключайте забавного использования каналов CMY для добавления контраста изображению. - person Shawn C; 17.04.2014
comment
Я обновил вопрос с новым массивом в качестве входных данных. Кажется, что C=0, M=0, Y=0 и K=0 не соответствуют белому! Хотя согласен, что по идее должен! Так что я думаю, что я делаю что-то не так, но я не могу понять, что!?! - person makhlaghi; 18.04.2014

Я думаю, что нашел ответ сам. Сначала я попытался установить для всех четырех цветов одинаковое значение. Это дало разумный результат, но вывод не был инвертирован, как я ожидал. Так, чтобы пиксель с наибольшим значением во всех четырех цветах был белым, а не черным!

Тут-то мне и пришло в голову, что где-то в процессе, то ли в IJG's libjpeg, то ли вообще в стандарте JPEG я понятия не имею какие, цвета CMYK перевернуты. Так, например, значение Cyan, равное 0, фактически интерпретируется как UCHAR_MAX на дисплее или печатающем устройстве и наоборот. Если бы это было решением, то тот факт, что изображение в вопросе было настолько темным и что его оттенок серого был таким же, как изображение в оттенках серого, можно было бы легко объяснить (поскольку я установил все три других цвета равными нулю, что фактически интерпретировалось как максимальное значение). интенсивность!).

Поэтому я установил для первых трех цветов CMYK полный диапазон (=UCHAR_MAX):

jsr[i*4]=jsr[i*4+1]=jsr[i*4+2]=UCHAR_MAX /* Was 0 before! */;

Затем, к моему удивлению, изображение сработало. Оттенки серого (слева) темнее, но, по крайней мере, в целом все можно объяснить и они достаточно похожи. Я проверил отдельно, и абсолютный черный цвет идентичен в обоих, но оттенки серого в шкале серого темнее для одного и того же значения пикселя.

На мониторе

После того, как я проверил их на распечатке (ниже), результаты, казалось, отличались меньше, хотя оттенки серого в шкале серого темнее! Фото сделано на мой смартфон!

На бумаге

Кроме того, пока я не внес это изменение, в обычном средстве просмотра изображений (я использую Scientific Linux) изображение было бы полностью черным, поэтому я думал, что не вижу изображение CMYK! Но после этой коррекции я мог видеть CMYK-изображение как обычное изображение. Фактически, используя Eye of GNOME (средство просмотра изображений по умолчанию в GNOME), они почти идентичны.

person makhlaghi    schedule 20.04.2014