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