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 и обратно, но как сделать по нормальному — не знаю,
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.