microsoft ICM сконвертить в La*b*
От: nik0la  
Дата: 23.05.05 07:13
Оценка:
Пытаюсь разобраться с MS ICM (Image Color Management)
Не могу нормально сконвертировать изображение в La*b* из исходного icm профиля
Нашел в интернете несколько профилей, описывающих La*b*
http://www.littlecms.com/profiles.zip

RGB -> CMYK и обратно вроде получается нормально при соответствующих профилях,
В La*b* — получается что-то похожее на правду, но с серьезными артефактами в районе серых цветов.
Гистограмма канала a* после конвертации sRGB->La*b* выглядит примерно так:

I=======================================================I
I                          --                           I
I                         -  -                          I
I                         l   -                         I
I                       -+l    -                        I
I                      - ll     l                       I
Il          l         -  ll     l       l               I
Il          l        -   ++     l       l               I
Il          l       -           l       l               I
Il          l      -            l       l               I
Il          l     -             l       l               I
Il          l    -               +      l               I
I+          +  --                 ------+-----          I
I                                                       I
I=======================================================I


Столбики на гистограмме соответствуют 1,63,191 и как раз представляют из себя артефакты на La*b*изображении
Провал на гистограмме соответствует 128
Если все значения 1,63,191 принудительно заменить на 128 — в целом картинка воспринимается более или менее нормально (цвета всё равно немного уходят в зеленый).
С каналом b* — такая же фигня.
Канал L — вроде всё нормально.

Делаю так:
(исходное изображение в raw формате Photoshop)

#include <stdio.h>
#include <windows.h>
#include <icm.h>

int main (int argc, char *argv[])
{
    int h=1200;
    int w=1600;

    COLOR *scolorBuf=new COLOR[w];
    COLOR *dcolorBuf=new COLOR[w];
    BYTE *dbuf=new BYTE[w*3];
    unsigned char *buf=new unsigned char[w*3];

    HPROFILE pr[2];
    PROFILE p;
    p.dwType = PROFILE_FILENAME;

    p.pProfileData = "G:\\icm\\sRGB Color Space Profile.ICM";
    p.cbDataSize = strlen((char*)p.pProfileData)+1;
    pr[0]=OpenColorProfile( &p, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);

    p.pProfileData = "G:\\icm\\Tifflab8spac.icm";
    p.cbDataSize = strlen((char*)p.pProfileData)+1;
    pr[1]=OpenColorProfile( &p, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);

    DWORD intent=INTENT_ABSOLUTE_COLORIMETRIC;
    HTRANSFORM ht=CreateMultiProfileTransform( pr, 2, &intent, 1, 0, INDEX_DONT_CARE);

    FILE *ifp=fopen("rgb.raw", "rb");
    FILE *ofp=fopen("lab.raw", "wb");
    for (int i=0; i<h; i++) {
        fread( buf, w, 3, ifp);
        for (int j=0; j<w; j++) {
            scolorBuf[j].rgb.red = buf[j*3+0]*257;
            scolorBuf[j].rgb.green = buf[j*3+1]*257;
            scolorBuf[j].rgb.blue = buf[j*3+2]*257;
        }
        TranslateColors( ht, scolorBuf, w, COLOR_RGB, dcolorBuf, COLOR_Lab);

        for (int j=0; j<w; j++) {
            buf[j*3+0] = BYTE(dcolorBuf[j].Lab.L/257.0+0.5);
            buf[j*3+1] = BYTE((dcolorBuf[j].Lab.a^0x8000)/257.0+0.5);
            buf[j*3+2] = BYTE((dcolorBuf[j].Lab.b^0x8000)/257.0+0.5);
        }
        fwrite( buf, w, 3, ofp);
    }

    delete[] buf;
    delete[] dcolorBuf;
    delete[] scolorBuf;
    
    fclose( ofp);
    fclose( ifp);
}


Может кто знает в чем трабл?

Нашел формулы для перевода из sRGB в La*b* вручную, а ICM можно будет использовать для перевода в sRGB и обратно, но как сделать по нормальному — не знаю,
Re: microsoft ICM сконвертить в La*b*
От: adontz Грузия http://adontz.wordpress.com/
Дата: 23.05.05 08:27
Оценка:
Здравствуйте, nik0la, Вы писали:

А чем ты потом изображение в Lab-формате смотришь?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: microsoft ICM сконвертить в La*b*
От: nik0la  
Дата: 23.05.05 11:24
Оценка:
Здравствуйте, adontz, Вы писали:

A>А чем ты потом изображение в Lab-формате смотришь?


Загружаю в Photoshop (в raw формате приходится задавать вручную размеры и количество каналов), он его по-умолчанию интерпретирует как RGB
Переключаю изображение в режим Multichannel (Image->Mode->Multichannel), затем в Lab (Image->Mode->Lab)
Re[3]: microsoft ICM сконвертить в La*b*
От: adontz Грузия http://adontz.wordpress.com/
Дата: 23.05.05 11:27
Оценка:
Здравствуйте, nik0la, Вы писали:

N>Загружаю в Photoshop (в raw формате приходится задавать вручную размеры и количество каналов), он его по-умолчанию интерпретирует как RGB

N>Переключаю изображение в режим Multichannel (Image->Mode->Multichannel), затем в Lab (Image->Mode->Lab)

Просто PhotoShop может сам применять какие-то ICM в процессе конвертации.
Лучше бы конвертировать туда-обратно и смотреть на разницу между исходным и дважды сконвертированным RGB.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[4]: microsoft ICM сконвертить в La*b*
От: Аноним  
Дата: 23.05.05 12:52
Оценка:
Здравствуйте, adontz, Вы писали:

A>Просто PhotoShop может сам применять какие-то ICM в процессе конвертации.

A>Лучше бы конвертировать туда-обратно и смотреть на разницу между исходным и дважды сконвертированным RGB.

Только что попробовал писать не в raw а в tiff:



    TIFF *out=TIFFOpen( "lab.tif",  "wb");
    
    TIFFSetField( out, TIFFTAG_IMAGEWIDTH, w);
    TIFFSetField( out, TIFFTAG_IMAGELENGTH, h);
    TIFFSetField( out, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
    TIFFSetField( out, TIFFTAG_SAMPLESPERPIXEL, 3);
    TIFFSetField( out, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField( out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField( out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB);
    TIFFSetField( out, TIFFTAG_XRESOLUTION, 72.0);
    TIFFSetField( out, TIFFTAG_YRESOLUTION, 72.0);

...
        for (int j=0; j<w; j++) {
            buf[j*3+0] = BYTE(dcolorBuf[j].Lab.L/257.0+0.5);
            buf[j*3+1] = BYTE((dcolorBuf[j].Lab.a)/257.0+0.5);
            buf[j*3+2] = BYTE((dcolorBuf[j].Lab.b)/257.0+0.5);
        }
        TIFFWriteScanline( out, buf, i, 0);
...

    TIFFClose( out);


Тут уже вроде влияния Photoshop'а должны исключиться.
Артефакты и свистопляска на гистограмме a* и b* каналов осталась как и была

Попробовал сконвертнуть туда-обратно (sRGB -> La*b* -> sRGB) на выходе получил RGB картинку с точно такими-же артефактами
что были на La*b* картинке, и тоже цвета ушли немного в зеленый. Теперь вообще не знаю что делать. Пробовал другие профили La*b*, например LCMSLABI.ICM
Привожу полный текст:

#include <stdio.h>
#include <windows.h>
#include <icm.h>
#include "tiff.h"
#include "tiffconf.h"
#include "tiffio.h"
#include "tiffvers.h"

int main (int argc, char *argv[])
{

    int h=1200;
    int w=1600;

    COLOR *scolorBuf=new COLOR[w];
    COLOR *dcolorBuf=new COLOR[w];
    BYTE *dbuf=new BYTE[w*3];
    unsigned char *buf=new unsigned char[w*3];

    HPROFILE pr[2];
    PROFILE p;
    p.dwType = PROFILE_FILENAME;

    p.pProfileData = "G:\\icm\\sRGB Color Space Profile.ICM";
    p.cbDataSize = strlen((char*)p.pProfileData)+1;
    pr[0]=OpenColorProfile( &p, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);

    p.pProfileData = "G:\\icm\\Tifflab8spac.icm";
    p.cbDataSize = strlen((char*)p.pProfileData)+1;
    pr[1]=OpenColorProfile( &p, PROFILE_READ, FILE_SHARE_READ, OPEN_EXISTING);

    DWORD intent=INTENT_ABSOLUTE_COLORIMETRIC;
    HTRANSFORM ht=CreateMultiProfileTransform( pr, 2, &intent, 1, 0, INDEX_DONT_CARE);

    HPROFILE pr_rev[2]={pr[1],pr[0]};
    HTRANSFORM ht_rev=CreateMultiProfileTransform( pr_rev, 2, &intent, 1, 0, INDEX_DONT_CARE);


    FILE *ifp=fopen("rgb.raw", "rb");
    FILE *ofp=fopen("rgb_out.raw", "wb");
    for (int i=0; i<h; i++) {
        fread( buf, w, 3, ifp);
        for (int j=0; j<w; j++) {
            scolorBuf[j].rgb.red = buf[j*3+0]*257;
            scolorBuf[j].rgb.green = buf[j*3+1]*257;
            scolorBuf[j].rgb.blue = buf[j*3+2]*257;
        }
        TranslateColors( ht, scolorBuf, w, COLOR_RGB, dcolorBuf, COLOR_Lab);
        TranslateColors( ht_rev, dcolorBuf, w, COLOR_Lab, scolorBuf, COLOR_RGB);
        for (int j=0; j<w; j++) {
            buf[j*3+0] = BYTE(scolorBuf[j].rgb.red/257.0+0.5);
            buf[j*3+1] = BYTE(scolorBuf[j].rgb.green/257.0+0.5);
            buf[j*3+2] = BYTE(scolorBuf[j].rgb.blue/257.0+0.5);
        }
        fwrite( buf, w, 3, ofp);
    }

    delete[] buf;
    delete[] dcolorBuf;
    delete[] scolorBuf;
    
    fclose( ofp);
    fclose( ifp);
}
Re: microsoft ICM сконвертить в La*b*
От: nen777w  
Дата: 23.05.05 14:26
Оценка:
n> Нашел формулы для перевода из sRGB в La*b* вручную, а ICM можно
n> будет использовать для перевода в sRGB и обратно, но как сделать по
n> нормальному — не знаю,

Я вручную конвертил, там простые операции перемножения матриц и всё
работало отлично.
Posted via RSDN NNTP Server 1.9
Re: microsoft ICM сконвертить в La*b*
От: nik0la  
Дата: 28.05.05 05:43
Оценка:
Кажется решил проблему.
Нашел другой Lab профиль (LCMSLABI.ICM, из комплекта www.littlecms.com)
Переправил в шестнадцатеричном редакторе его из абтрактного ('abst') в профиль пространства('spac').
Нашел нормально описание структуры COLOR в описании ColorSync для mac с которой передрана MS ICM
Вроде заработало.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.