mfplat/sample: Refactor sample_CopyToBuffer().
[wine.git] / dlls / mscms / transform.c
blobc66c76a4c41611f5daa77b86e44cff6f5f7a1939
1 /*
2 * MSCMS - Color Management System for Wine
4 * Copyright 2005, 2006, 2008 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "icm.h"
30 #include "wine/debug.h"
32 #include "mscms_priv.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mscms);
36 static DWORD from_bmformat( BMFORMAT format )
38 static BOOL quietfixme = FALSE;
39 DWORD ret;
41 switch (format)
43 case BM_RGBTRIPLETS: ret = TYPE_BGR_8; break;
44 case BM_BGRTRIPLETS: ret = TYPE_RGB_8; break;
45 case BM_GRAY: ret = TYPE_GRAY_8; break;
46 case BM_xRGBQUADS: ret = TYPE_BGRA_8; break;
47 case BM_xBGRQUADS: ret = TYPE_RGBA_8; break;
48 case BM_KYMCQUADS: ret = TYPE_CMYK_8; break;
49 default:
50 if (!quietfixme)
52 FIXME( "unhandled bitmap format %#x\n", format );
53 quietfixme = TRUE;
55 ret = TYPE_RGB_8;
56 break;
58 TRACE( "color space: %#x -> %#lx\n", format, ret );
59 return ret;
62 static DWORD from_type( COLORTYPE type )
64 DWORD ret;
66 switch (type)
68 case COLOR_GRAY: ret = TYPE_GRAY_16; break;
69 case COLOR_RGB: ret = TYPE_RGB_16; break;
70 case COLOR_XYZ: ret = TYPE_XYZ_16; break;
71 case COLOR_Yxy: ret = TYPE_Yxy_16; break;
72 case COLOR_Lab: ret = TYPE_Lab_16; break;
73 case COLOR_CMYK: ret = TYPE_CMYK_16; break;
74 default:
75 FIXME( "unhandled color type %08x\n", type );
76 ret = TYPE_RGB_16;
77 break;
80 TRACE( "color type: %#x -> %#lx\n", type, ret );
81 return ret;
84 /******************************************************************************
85 * CreateColorTransformA [MSCMS.@]
87 * See CreateColorTransformW.
89 HTRANSFORM WINAPI CreateColorTransformA( LPLOGCOLORSPACEA space, HPROFILE dest, HPROFILE target, DWORD flags )
91 LOGCOLORSPACEW spaceW;
92 DWORD len;
94 TRACE( "( %p, %p, %p, %#lx )\n", space, dest, target, flags );
96 if (!space || !dest) return FALSE;
98 memcpy( &spaceW, space, FIELD_OFFSET(LOGCOLORSPACEA, lcsFilename) );
99 spaceW.lcsSize = sizeof(LOGCOLORSPACEW);
101 len = MultiByteToWideChar( CP_ACP, 0, space->lcsFilename, -1, NULL, 0 );
102 MultiByteToWideChar( CP_ACP, 0, space->lcsFilename, -1, spaceW.lcsFilename, len );
104 return CreateColorTransformW( &spaceW, dest, target, flags );
107 static void close_transform( struct object *obj )
109 struct transform *transform = (struct transform *)obj;
110 if (transform->cmstransform) cmsDeleteTransform( transform->cmstransform );
113 /******************************************************************************
114 * CreateColorTransformW [MSCMS.@]
116 * Create a color transform.
118 * PARAMS
119 * space [I] Input color space.
120 * dest [I] Color profile of destination device.
121 * target [I] Color profile of target device.
122 * flags [I] Flags.
124 * RETURNS
125 * Success: Handle to a transform.
126 * Failure: NULL
128 HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, HPROFILE target, DWORD flags )
130 HTRANSFORM ret = NULL;
131 struct transform *transform;
132 cmsHTRANSFORM cmstransform;
133 struct profile *dst, *tgt = NULL;
134 DWORD proofing = 0;
135 cmsHPROFILE input;
136 int intent;
138 TRACE( "( %p, %p, %p, %#lx )\n", space, dest, target, flags );
140 if (!space || !(dst = (struct profile *)grab_object( dest, OBJECT_TYPE_PROFILE ))) return FALSE;
141 if (target && !(tgt = (struct profile *)grab_object( target, OBJECT_TYPE_PROFILE )))
143 release_object( &dst->hdr );
144 return FALSE;
146 intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent;
148 TRACE( "lcsIntent: %#lx\n", space->lcsIntent );
149 TRACE( "lcsCSType: %s\n", debugstr_fourcc( space->lcsCSType ) );
150 TRACE( "lcsFilename: %s\n", debugstr_w( space->lcsFilename ) );
152 input = cmsCreate_sRGBProfile(); /* FIXME: create from supplied color space */
153 if (target) proofing = cmsFLAGS_SOFTPROOFING;
154 cmstransform = cmsCreateProofingTransform( input, 0, dst->cmsprofile, 0, tgt ? tgt->cmsprofile : NULL,
155 intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing );
156 if (!cmstransform)
158 if (tgt) release_object( &tgt->hdr );
159 release_object( &dst->hdr );
160 return FALSE;
163 if ((transform = calloc( 1, sizeof(*transform) )))
165 transform->hdr.type = OBJECT_TYPE_TRANSFORM;
166 transform->hdr.close = close_transform;
167 transform->cmstransform = cmstransform;
168 if (!(ret = alloc_handle( &transform->hdr ))) free( transform );
171 if (tgt) release_object( &tgt->hdr );
172 release_object( &dst->hdr );
173 return ret;
176 /******************************************************************************
177 * CreateMultiProfileTransform [MSCMS.@]
179 * Create a color transform from an array of color profiles.
181 * PARAMS
182 * profiles [I] Array of color profiles.
183 * nprofiles [I] Number of color profiles.
184 * intents [I] Array of rendering intents.
185 * flags [I] Flags.
186 * cmm [I] Profile to take the CMM from.
188 * RETURNS
189 * Success: Handle to a transform.
190 * Failure: NULL
192 HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofiles,
193 PDWORD intents, DWORD nintents, DWORD flags, DWORD cmm )
195 HTRANSFORM ret = NULL;
196 cmsHPROFILE cmsprofiles[2];
197 cmsHTRANSFORM cmstransform;
198 struct transform *transform;
199 struct profile *profile0, *profile1;
201 TRACE( "( %p, %#lx, %p, %lu, %#lx, %#lx )\n", profiles, nprofiles, intents, nintents, flags, cmm );
203 if (!profiles || !nprofiles || !intents) return NULL;
205 if (nprofiles > 2)
207 FIXME("more than 2 profiles not supported\n");
208 return NULL;
211 profile0 = (struct profile *)grab_object( profiles[0], OBJECT_TYPE_PROFILE );
212 if (!profile0) return NULL;
213 profile1 = (struct profile *)grab_object( profiles[1], OBJECT_TYPE_PROFILE );
214 if (!profile1)
216 release_object( &profile0->hdr );
217 return NULL;
220 cmsprofiles[0] = profile0->cmsprofile;
221 cmsprofiles[1] = profile1->cmsprofile;
222 if (!(cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, 0, 0, *intents, 0 )))
224 release_object( &profile0->hdr );
225 release_object( &profile1->hdr );
226 return FALSE;
229 if ((transform = calloc( 1, sizeof(*transform) )))
231 transform->hdr.type = OBJECT_TYPE_TRANSFORM;
232 transform->hdr.close = close_transform;
233 transform->cmstransform = cmstransform;
234 if (!(ret = alloc_handle( &transform->hdr ))) free( transform );
237 release_object( &profile0->hdr );
238 release_object( &profile1->hdr );
239 return ret;
242 /******************************************************************************
243 * DeleteColorTransform [MSCMS.@]
245 * Delete a color transform.
247 * PARAMS
248 * transform [I] Handle to a color transform.
250 * RETURNS
251 * Success: TRUE
252 * Failure: FALSE
254 BOOL WINAPI DeleteColorTransform( HTRANSFORM handle )
256 struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
258 TRACE( "( %p )\n", handle );
260 if (!transform) return FALSE;
261 free_handle( handle );
262 release_object( &transform->hdr );
263 return TRUE;
266 /******************************************************************************
267 * TranslateBitmapBits [MSCMS.@]
269 * Perform color translation.
271 * PARAMS
272 * transform [I] Handle to a color transform.
273 * srcbits [I] Source bitmap.
274 * input [I] Format of the source bitmap.
275 * width [I] Width of the source bitmap.
276 * height [I] Height of the source bitmap.
277 * inputstride [I] Number of bytes in one scanline.
278 * destbits [I] Destination bitmap.
279 * output [I] Format of the destination bitmap.
280 * outputstride [I] Number of bytes in one scanline.
281 * callback [I] Callback function.
282 * data [I] Callback data.
284 * RETURNS
285 * Success: TRUE
286 * Failure: FALSE
288 BOOL WINAPI TranslateBitmapBits( HTRANSFORM handle, PVOID srcbits, BMFORMAT input,
289 DWORD width, DWORD height, DWORD inputstride, PVOID destbits, BMFORMAT output,
290 DWORD outputstride, PBMCALLBACKFN callback, ULONG data )
292 BOOL ret;
293 struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
295 TRACE( "( %p, %p, %#x, %lu, %lu, %lu, %p, %#x, %lu, %p, %#lx )\n",
296 handle, srcbits, input, width, height, inputstride, destbits, output,
297 outputstride, callback, data );
299 if (!transform) return FALSE;
300 ret = cmsChangeBuffersFormat( transform->cmstransform, from_bmformat(input), from_bmformat(output) );
301 if (ret) cmsDoTransform( transform->cmstransform, srcbits, destbits, width * height );
302 release_object( &transform->hdr );
303 return ret;
306 /******************************************************************************
307 * TranslateColors [MSCMS.@]
309 * Perform color translation.
311 * PARAMS
312 * transform [I] Handle to a color transform.
313 * input [I] Array of input colors.
314 * number [I] Number of colors to translate.
315 * input_type [I] Input color format.
316 * output [O] Array of output colors.
317 * output_type [I] Output color format.
319 * RETURNS
320 * Success: TRUE
321 * Failure: FALSE
323 BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count,
324 COLORTYPE input_type, PCOLOR out, COLORTYPE output_type )
326 BOOL ret;
327 unsigned int i;
328 struct transform *transform = (struct transform *)grab_object( handle, OBJECT_TYPE_TRANSFORM );
330 TRACE( "( %p, %p, %lu, %d, %p, %d )\n", handle, in, count, input_type, out, output_type );
332 if (!transform) return FALSE;
334 ret = cmsChangeBuffersFormat( transform->cmstransform, from_type(input_type), from_type(output_type) );
335 if (ret)
336 for (i = 0; i < count; i++) cmsDoTransform( transform->cmstransform, &in[i], &out[i], 1 );
338 release_object( &transform->hdr );
339 return ret;