diff --git a/dlls/mscms/mscms_priv.h b/dlls/mscms/mscms_priv.h index fd89ba2e64b..2f9be8bc750 100644 --- a/dlls/mscms/mscms_priv.h +++ b/dlls/mscms/mscms_priv.h @@ -90,4 +90,6 @@ extern void MSCMS_get_profile_header( const icProfile *iccprofile, PROFILEHEADER extern void MSCMS_set_profile_header( icProfile *iccprofile, const PROFILEHEADER *header ); extern DWORD MSCMS_get_profile_size( const icProfile *iccprofile ); +extern const char *MSCMS_dbgstr_tag(DWORD); + #endif /* HAVE_LCMS */ diff --git a/dlls/mscms/profile.c b/dlls/mscms/profile.c index af636ef0a30..8f4931af841 100644 --- a/dlls/mscms/profile.c +++ b/dlls/mscms/profile.c @@ -56,7 +56,7 @@ static inline LPWSTR MSCMS_strdupW( LPCSTR str ) return ret; } -static const char *MSCMS_dbgstr_tag( DWORD tag ) +const char *MSCMS_dbgstr_tag( DWORD tag ) { return wine_dbg_sprintf( "'%c%c%c%c'", (char)(tag >> 24), (char)(tag >> 16), (char)(tag >> 8), (char)(tag) ); diff --git a/dlls/mscms/stub.c b/dlls/mscms/stub.c index 0e5f443ff5d..f142201f3b5 100644 --- a/dlls/mscms/stub.c +++ b/dlls/mscms/stub.c @@ -29,6 +29,8 @@ #include "winuser.h" #include "icm.h" +#include "mscms_priv.h" + WINE_DEFAULT_DEBUG_CHANNEL(mscms); BOOL WINAPI CheckBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT format, DWORD width, @@ -149,7 +151,7 @@ BOOL WINAPI RegisterCMMW( PCWSTR machine, DWORD id, PCWSTR dll ) BOOL WINAPI SelectCMM( DWORD id ) { - FIXME( "( 0x%08x ) stub\n", id ); + FIXME( "( %s ) stub\n", MSCMS_dbgstr_tag(id) ); return TRUE; } @@ -186,15 +188,6 @@ BOOL WINAPI SpoolerCopyFileEvent( LPWSTR printer, LPWSTR key, DWORD event ) return TRUE; } -BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR inputcolors, DWORD number, - COLORTYPE input, PCOLOR outputcolors, COLORTYPE output ) -{ - FIXME( "( %p, %p, 0x%08x, 0x%08x, %p, 0x%08x ) stub\n", transform, inputcolors, - number, input, outputcolors, output ); - - return FALSE; -} - BOOL WINAPI UnregisterCMMA( PCSTR machine, DWORD id ) { FIXME( "( %p, 0x%08x ) stub\n", machine, id ); diff --git a/dlls/mscms/transform.c b/dlls/mscms/transform.c index 0cc45052e8c..13bc55a6177 100644 --- a/dlls/mscms/transform.c +++ b/dlls/mscms/transform.c @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2005, 2006 Hans Leidekker + * Copyright 2005, 2006, 2008 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -58,6 +58,28 @@ HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, return CreateColorTransformW( &spaceW, dest, target, flags ); } +static DWORD from_profile( HPROFILE profile ) +{ + PROFILEHEADER header; + + GetColorProfileHeader( profile, &header ); + TRACE( "color space: 0x%08x %s\n", header.phDataColorSpace, MSCMS_dbgstr_tag( header.phDataColorSpace ) ); + + switch (header.phDataColorSpace) + { + case 0x434d594b: return TYPE_CMYK_16; /* 'CMYK' */ + case 0x47524159: return TYPE_GRAY_16; /* 'GRAY' */ + case 0x4c616220: return TYPE_Lab_16; /* 'Lab ' */ + case 0x52474220: return TYPE_RGB_16; /* 'RGB ' */ + case 0x58595a20: return TYPE_XYZ_16; /* 'XYZ ' */ + default: + { + WARN("unhandled format\n"); + return TYPE_RGB_16; + } + } +} + /****************************************************************************** * CreateColorTransformW [MSCMS.@] * @@ -79,7 +101,8 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HTRANSFORM ret = NULL; #ifdef HAVE_LCMS cmsHTRANSFORM cmstransform; - cmsHPROFILE cmsprofiles[3]; + cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL; + DWORD in_format, out_format, proofing = 0; int intent; TRACE( "( %p, %p, %p, 0x%08x )\n", space, dest, target, flags ); @@ -88,18 +111,22 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent; - cmsprofiles[0] = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */ - cmsprofiles[1] = MSCMS_hprofile2cmsprofile( dest ); + TRACE( "lcsIntent: %x\n", space->lcsIntent ); + TRACE( "lcsCSType: %s\n", MSCMS_dbgstr_tag( space->lcsCSType ) ); + TRACE( "lcsFilename: %s\n", debugstr_w( space->lcsFilename ) ); + in_format = TYPE_RGB_16; + out_format = from_profile( dest ); + + cmsinput = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */ if (target) { - cmsprofiles[2] = MSCMS_hprofile2cmsprofile( target ); - cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, 3, TYPE_BGR_8, - TYPE_BGR_8, intent, 0 ); + proofing = cmsFLAGS_SOFTPROOFING; + cmstarget = MSCMS_hprofile2cmsprofile( target ); } - else - cmstransform = cmsCreateTransform( cmsprofiles[0], TYPE_BGR_8, cmsprofiles[1], - TYPE_BGR_8, intent, 0 ); + cmsoutput = MSCMS_hprofile2cmsprofile( dest ); + cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget, + intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing); ret = MSCMS_create_htransform_handle( cmstransform ); @@ -128,27 +155,50 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS - cmsHPROFILE *cmsprofiles; + cmsHPROFILE *cmsprofiles, cmsconvert = NULL; cmsHTRANSFORM cmstransform; - DWORD i; + DWORD in_format, out_format; - TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x ) stub\n", + TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", profiles, nprofiles, intents, nintents, flags, cmm ); - if (!profiles || !intents) return NULL; + if (!profiles || !nprofiles || !intents) return NULL; - cmsprofiles = HeapAlloc( GetProcessHeap(), 0, nprofiles * sizeof(cmsHPROFILE) ); - - if (cmsprofiles) + if (nprofiles > 2) { - for (i = 0; i < nprofiles; i++) - cmsprofiles[i] = MSCMS_hprofile2cmsprofile( profiles[i] ); + FIXME("more than 2 profiles not supported\n"); + return NULL; } - cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, TYPE_BGR_8, - TYPE_BGR_8, *intents, 0 ); - HeapFree( GetProcessHeap(), 0, cmsprofiles ); - ret = MSCMS_create_htransform_handle( cmstransform ); + in_format = from_profile( profiles[0] ); + out_format = from_profile( profiles[nprofiles - 1] ); + + if (in_format != out_format) + { + /* insert a conversion profile for pairings that lcms doesn't handle */ + if (out_format == TYPE_RGB_16) cmsconvert = cmsCreate_sRGBProfile(); + if (out_format == TYPE_Lab_16) cmsconvert = cmsCreateLabProfile( NULL ); + } + + cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE *) ); + if (cmsprofiles) + { + cmsprofiles[0] = MSCMS_hprofile2cmsprofile( profiles[0] ); + if (cmsconvert) + { + cmsprofiles[1] = cmsconvert; + cmsprofiles[2] = MSCMS_hprofile2cmsprofile( profiles[1] ); + nprofiles++; + } + else + { + cmsprofiles[1] = MSCMS_hprofile2cmsprofile( profiles[1] ); + } + cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 ); + + HeapFree( GetProcessHeap(), 0, cmsprofiles ); + ret = MSCMS_create_htransform_handle( cmstransform ); + } #endif /* HAVE_LCMS */ return ret; @@ -184,6 +234,23 @@ BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) return ret; } +static DWORD from_bmformat( BMFORMAT format ) +{ + TRACE( "bitmap format: 0x%08x\n", format ); + + switch (format) + { + case BM_RGBTRIPLETS: return TYPE_RGB_8; + case BM_BGRTRIPLETS: return TYPE_BGR_8; + case BM_GRAY: return TYPE_GRAY_8; + default: + { + FIXME("unhandled bitmap format\n"); + return TYPE_RGB_8; + } + } +} + /****************************************************************************** * TranslateBitmapBits [MSCMS.@] * @@ -219,9 +286,141 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT i outputstride, callback, data ); cmstransform = MSCMS_htransform2cmstransform( transform ); + cmsChangeBuffersFormat( cmstransform, from_bmformat(input), from_bmformat(output) ); + cmsDoTransform( cmstransform, srcbits, destbits, width * height ); ret = TRUE; #endif /* HAVE_LCMS */ return ret; } + +static DWORD from_type( COLORTYPE type ) +{ + TRACE( "color type: 0x%08x\n", type ); + + switch (type) + { + case COLOR_GRAY: return TYPE_GRAY_16; + case COLOR_RGB: return TYPE_RGB_16; + case COLOR_XYZ: return TYPE_XYZ_16; + case COLOR_Yxy: return TYPE_Yxy_16; + case COLOR_Lab: return TYPE_Lab_16; + case COLOR_CMYK: return TYPE_CMYK_16; + default: + { + FIXME("unhandled color type\n"); + return TYPE_RGB_16; + } + } +} + +/****************************************************************************** + * TranslateColors [MSCMS.@] + * + * Perform color translation. + * + * PARAMS + * transform [I] Handle to a color transform. + * input [I] Array of input colors. + * number [I] Number of colors to translate. + * input_type [I] Input color format. + * output [O] Array of output colors. + * output_type [I] Output color format. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR in, DWORD count, + COLORTYPE input_type, PCOLOR out, COLORTYPE output_type ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS + cmsHTRANSFORM xfrm = MSCMS_htransform2cmstransform( transform ); + unsigned int i; + + TRACE( "( %p, %p, %d, %d, %p, %d )\n", transform, in, count, input_type, out, output_type ); + + cmsChangeBuffersFormat( xfrm, from_type(input_type), from_type(output_type) ); + + switch (input_type) + { + case COLOR_RGB: + { + switch (output_type) + { + case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].rgb, 1 ); return TRUE; + case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].Lab, 1 ); return TRUE; + case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].gray, 1 ); return TRUE; + case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].cmyk, 1 ); return TRUE; + case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].XYZ, 1 ); return TRUE; + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + return FALSE; + } + } + case COLOR_Lab: + { + switch (output_type) + { + case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].rgb, 1 ); return TRUE; + case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].Lab, 1 ); return TRUE; + case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].gray, 1 ); return TRUE; + case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].cmyk, 1 ); return TRUE; + case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].XYZ, 1 ); return TRUE; + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + return FALSE; + } + } + case COLOR_GRAY: + { + switch (output_type) + { + case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].rgb, 1 ); return TRUE; + case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].Lab, 1 ); return TRUE; + case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].gray, 1 ); return TRUE; + case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].cmyk, 1 ); return TRUE; + case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].XYZ, 1 ); return TRUE; + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + return FALSE; + } + } + case COLOR_CMYK: + { + switch (output_type) + { + case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].rgb, 1 ); return TRUE; + case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].Lab, 1 ); return TRUE; + case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].gray, 1 ); return TRUE; + case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].cmyk, 1 ); return TRUE; + case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].XYZ, 1 ); return TRUE; + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + return FALSE; + } + } + case COLOR_XYZ: + { + switch (output_type) + { + case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].rgb, 1 ); return TRUE; + case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].Lab, 1 ); return TRUE; + case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].gray, 1 ); return TRUE; + case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].cmyk, 1 ); return TRUE; + case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].XYZ, 1 ); return TRUE; + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + return FALSE; + } + } + default: + FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); + break; + } + +#endif /* HAVE_LCMS */ + return ret; +}