Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
DemoIccMAXCmm.cpp
Go to the documentation of this file.
1/** @file
2 File: DemoIccMAXCmm.cpp
3
4 Contains: Defines the entry point for the DLL application.
5
6 Version: V1
7
8 Copyright: (c) see ICC Software License
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2015 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64//////////////////////////////////////////////////////////////////////
65// HISTORY:
66//
67// -Initial implementation by Max Derhak 1-15-2007
68//
69//////////////////////////////////////////////////////////////////////
70//
71
72#include "stdafx.h"
73#include "IccCmm.h"
74#include "IccDefs.h"
75#include "Icm.h"
76#include "DemoIccMAXCmm.h"
77#include "resource.h"
78#include <string>
79#include "Winerror.h"
80
81static CIccProfile* OpenProfile(HPROFILE hProfile)
82{
83 DWORD dwSize=0;
84
85 GetColorProfileFromHandle(hProfile, NULL, &dwSize);
86
87 if (!dwSize)
88 return NULL;
89
90 CIccMemIO *pIO = new CIccMemIO();
91
92 if (!pIO->Alloc(dwSize)) {
93 delete pIO;
94
95 return NULL;
96 }
97
98 if (!GetColorProfileFromHandle(hProfile, pIO->GetData(), &dwSize)) {
99 delete pIO;
100
101 return NULL;
102 }
103
104 CIccProfile *pProfile = new CIccProfile();
105
106 if (!pProfile)
107 return NULL;
108
109 if (!pProfile->Attach(pIO)) {
110 delete pProfile;
111 delete pIO;
112
113 return NULL;
114 }
115
116 return pProfile;
117}
118
119#define AVAILABLE_TRANSFORMS 1024
120
122
123BOOL APIENTRY DllMain( HANDLE hModule,
124 DWORD ul_reason_for_call,
125 LPVOID lpReserved
126 )
127{
128 switch (ul_reason_for_call)
129 {
130 case DLL_PROCESS_ATTACH:
131 memset(g_Transforms, 0, sizeof(g_Transforms));
132 break;
133 case DLL_THREAD_ATTACH:
134 case DLL_THREAD_DETACH:
135 case DLL_PROCESS_DETACH:
136 break;
137 }
138 return TRUE;
139}
140
141typedef HPROFILE* LPHPROFILE;
142
143static BOOL IsValidColorType(COLORTYPE ctSpace, icColorSpaceSignature sigSpace)
144{
145 switch(ctSpace) {
146 case COLOR_GRAY:
147 if (sigSpace!=icSigGrayData) {
148 return FALSE;
149 }
150 break;
151
152 case COLOR_RGB:
153 if (sigSpace!=icSigRgbData) {
154 return FALSE;
155 }
156 break;
157
158 case COLOR_XYZ:
159 if (sigSpace!=icSigXYZData) {
160 return FALSE;
161 }
162 break;
163
164 case COLOR_Yxy:
165 if (sigSpace!=icSigYxyData) {
166 return FALSE;
167 }
168 break;
169
170 case COLOR_Lab:
171 if (sigSpace!=icSigLabData) {
172 return FALSE;
173 }
174 break;
175
176 case COLOR_3_CHANNEL: // WORD per channel
177 if (icGetSpaceSamples(sigSpace)!=3) {
178 return FALSE;
179 }
180 break;
181
182 case COLOR_CMYK:
183 if (sigSpace!=icSigCmykData) {
184 return FALSE;
185 }
186 break;
187
188 case COLOR_5_CHANNEL: // BYTE per channel
189 if (sigSpace!=icSig5colorData) {
190 return FALSE;
191 }
192 break;
193
194 case COLOR_6_CHANNEL: // - do -
195 if (sigSpace!=icSig6colorData) {
196 return FALSE;
197 }
198 break;
199
200 case COLOR_7_CHANNEL: // - do -
201 if (sigSpace!=icSig7colorData) {
202 return FALSE;
203 }
204 break;
205
206 case COLOR_8_CHANNEL: // - do -
207 if (sigSpace!=icSig8colorData) {
208 return FALSE;
209 }
210 break;
211
212 case COLOR_NAMED: //DemoIccMAXCmm Unsupported color spaace in transform
213 default:
214 return FALSE;
215 }
216
217 return TRUE;
218}
219
220static BOOL IsValidBitmapType(BMFORMAT bmType, icColorSpaceSignature sigSpace)
221{
222 switch(bmType) {
223 case BM_GRAY:
224 if (sigSpace!=icSigGrayData) {
225 return FALSE;
226 }
227 break;
228
229 case BM_x555RGB:
230 case BM_RGBTRIPLETS:
231 case BM_BGRTRIPLETS:
232 case BM_xRGBQUADS:
233 case BM_xBGRQUADS:
234 case BM_10b_RGB:
235 case BM_16b_RGB:
236 case BM_565RGB:
237 if (sigSpace!=icSigRgbData) {
238 return FALSE;
239 }
240 break;
241
242 case BM_x555XYZ:
243 case BM_XYZTRIPLETS:
244 case BM_10b_XYZ:
245 case BM_16b_XYZ:
246 if (sigSpace!=icSigXYZData) {
247 return FALSE;
248 }
249 break;
250
251 case BM_x555Yxy:
252 case BM_YxyTRIPLETS:
253 case BM_10b_Yxy:
254 case BM_16b_Yxy:
255 if (sigSpace!=icSigYxyData) {
256 return FALSE;
257 }
258 break;
259
260 case BM_x555Lab:
261 case BM_LabTRIPLETS:
262 case BM_10b_Lab:
263 case BM_16b_Lab:
264 if (sigSpace!=icSigLabData) {
265 return FALSE;
266 }
267 break;
268
269 case BM_x555G3CH:
270 case BM_G3CHTRIPLETS:
271 case BM_xG3CHQUADS:
272 case BM_10b_G3CH:
273 case BM_16b_G3CH:
274 if (icGetSpaceSamples(sigSpace)!=3) {
275 return FALSE;
276 }
277 break;
278
279 case BM_KYMCQUADS:
280 case BM_CMYKQUADS:
281 if (sigSpace!=icSigCmykData) {
282 return FALSE;
283 }
284 break;
285
286 case BM_5CHANNEL:
287 if (sigSpace!=icSig5colorData) {
288 return FALSE;
289 }
290 break;
291
292 case BM_6CHANNEL:
293 if (sigSpace!=icSig6colorData) {
294 return FALSE;
295 }
296 break;
297
298 case BM_7CHANNEL:
299 if (sigSpace!=icSig7colorData) {
300 return FALSE;
301 }
302 break;
303
304 case BM_8CHANNEL:
305 if (sigSpace!=icSig8colorData) {
306 return FALSE;
307 }
308 break;
309
310 case COLOR_NAMED: //DemoIccMAXCmm Unsupported color spaace in transform
311 default:
312 return FALSE;
313 }
314
315 return TRUE;
316}
317
319{
320 if (v<0.0)
321 return 0.0;
322 if (v>1.0)
323 return 1.0;
324 return v;
325}
326
327
328BOOL WINAPI CMCheckColors(
329 HCMTRANSFORM hcmTransform, // transform handle
330 LPCOLOR lpaInputColors, // array of COLORs
331 DWORD nColors, // COLOR array size
332 COLORTYPE ctInput, // input color type
333 LPBYTE lpaResult // buffer for results
334 )
335{
336 size_t i = (size_t)hcmTransform;
337 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
338
339 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
340 SetLastError(ERROR_INVALID_HANDLE);
341 return FALSE;
342 }
343
344 CIccCmm *pCmm = g_Transforms[i-256];
345
346 //Check if color types matches transform color spaces
347 if (!IsValidColorType(ctInput, pCmm->GetSourceSpace()) ||
348 pCmm->GetDestSpace() != icSigGamutData) {
349 SetLastError(ERROR_INVALID_DATATYPE);
350 return FALSE;
351 }
352
353 for (i=0; i<nColors; i++) {
354 switch (ctInput) {
355 case COLOR_GRAY:
356 srcPixel[0] = (icFloatNumber)(lpaInputColors->gray.gray) / 65535.0f;
357 break;
358
359 case COLOR_RGB:
360 srcPixel[0] = (icFloatNumber)(lpaInputColors->rgb.red) / 65535.0f;
361 srcPixel[1] = (icFloatNumber)(lpaInputColors->rgb.green) / 65535.0f;
362 srcPixel[2] = (icFloatNumber)(lpaInputColors->rgb.blue) / 65535.0f;
363 break;
364
365 case COLOR_XYZ:
366 srcPixel[0] = (icFloatNumber)(lpaInputColors->XYZ.X) / 65535.0f;
367 srcPixel[1] = (icFloatNumber)(lpaInputColors->XYZ.Y) / 65535.0f;
368 srcPixel[2] = (icFloatNumber)(lpaInputColors->XYZ.Z) / 65535.0f;
369 break;
370
371 case COLOR_Yxy:
372 srcPixel[0] = (icFloatNumber)(lpaInputColors->XYZ.X) / 65535.0f;
373 srcPixel[1] = (icFloatNumber)(lpaInputColors->XYZ.Y) / 65535.0f;
374 srcPixel[2] = (icFloatNumber)(lpaInputColors->XYZ.Z) / 65535.0f;
375 break;
376
377 case COLOR_Lab:
378 srcPixel[0] = (icFloatNumber)(lpaInputColors->Lab.L) / 65535.0f;
379 srcPixel[1] = (icFloatNumber)(lpaInputColors->Lab.a) / 65535.0f;
380 srcPixel[2] = (icFloatNumber)(lpaInputColors->Lab.b) / 65535.0f;
381 break;
382
383 case COLOR_3_CHANNEL: // WORD per channel
384 srcPixel[0] = (icFloatNumber)(lpaInputColors->gen3ch.ch1) / 65535.0f;
385 srcPixel[1] = (icFloatNumber)(lpaInputColors->gen3ch.ch2) / 65535.0f;
386 srcPixel[2] = (icFloatNumber)(lpaInputColors->gen3ch.ch3) / 65535.0f;
387 break;
388
389 case COLOR_CMYK:
390 srcPixel[0] = (icFloatNumber)(lpaInputColors->cmyk.cyan) / 65535.0f;
391 srcPixel[1] = (icFloatNumber)(lpaInputColors->cmyk.magenta) / 65535.0f;
392 srcPixel[2] = (icFloatNumber)(lpaInputColors->cmyk.yellow) / 65535.0f;
393 srcPixel[3] = (icFloatNumber)(lpaInputColors->cmyk.black) / 65535.0f;
394 break;
395
396 // Hifi colors use BYTE per channel
397 case COLOR_8_CHANNEL:
398 srcPixel[7] = (icFloatNumber)(lpaInputColors->hifi.channel[7]) / 255.0f;
399 //No break here!
400
401 case COLOR_7_CHANNEL:
402 srcPixel[6] = (icFloatNumber)(lpaInputColors->hifi.channel[6]) / 255.0f;
403 //No break here!
404
405 case COLOR_6_CHANNEL:
406 srcPixel[5] = (icFloatNumber)(lpaInputColors->hifi.channel[5]) / 255.0f;
407 //No break here!
408
409 case COLOR_5_CHANNEL:
410 srcPixel[0] = (icFloatNumber)(lpaInputColors->hifi.channel[0]) / 255.0f;
411 srcPixel[1] = (icFloatNumber)(lpaInputColors->hifi.channel[1]) / 255.0f;
412 srcPixel[2] = (icFloatNumber)(lpaInputColors->hifi.channel[2]) / 255.0f;
413 srcPixel[3] = (icFloatNumber)(lpaInputColors->hifi.channel[3]) / 255.0f;
414 srcPixel[4] = (icFloatNumber)(lpaInputColors->hifi.channel[4]) / 255.0f;
415 break;
416
417 default:
418 SetLastError(ERROR_UNSUPPORTED_TYPE);
419 return FALSE;
420 }
421 lpaInputColors++;
422
423 if (pCmm->Apply(destPixel, srcPixel)!=icCmmStatOk) {
424 SetLastError(ERROR_FUNCTION_FAILED);
425 return FALSE;
426 }
427
428 *lpaResult = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
429
430 lpaResult++;
431 }
432
433 return TRUE;
434}
435
436
437// Avoid " warning C4995: 'CMxxxx': name was marked as #pragma deprecated
438#pragma warning(disable : 4995)
440 HCMTRANSFORM hcmTransform, // transform handle
441 RGBTRIPLE *lpaRGBTriple, // RGB triple array
442 LPBYTE lpaResult, // buffer for results
443 UINT nCount // result buffer size
444 )
445{
446 size_t i = (size_t)hcmTransform;
447 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
448
449 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
450 SetLastError(ERROR_INVALID_HANDLE);
451 return FALSE;
452 }
453
454 CIccCmm *pCmm = g_Transforms[i-256];
455
456 //Check if color types matches transform color spaces
457 if (pCmm->GetSourceSpace()!=icSigRgbData ||
458 pCmm->GetDestSpace() != icSigGamutData) {
459 SetLastError(ERROR_INVALID_DATATYPE);
460 return FALSE;
461 }
462
463 for (i=0; i<nCount; i++) {
464 srcPixel[0] = (icFloatNumber)(lpaRGBTriple->rgbtRed) / 65535.0f;
465 srcPixel[1] = (icFloatNumber)(lpaRGBTriple->rgbtGreen) / 65535.0f;
466 srcPixel[2] = (icFloatNumber)(lpaRGBTriple->rgbtBlue) / 65535.0f;
467
468 lpaRGBTriple++;
469
470 if (pCmm->Apply(destPixel, srcPixel)!=icCmmStatOk) {
471 SetLastError(ERROR_FUNCTION_FAILED);
472 return FALSE;
473 }
474
475 *lpaResult = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
476
477 lpaResult++;
478 }
479 return TRUE;
480}
481
482
483BOOL WINAPI CMCheckRGBs(
484 HCMTRANSFORM hcmTransform,
485 LPBYTE lpSrcBits,
486 BMFORMAT bmInput,
487 DWORD dwWidth,
488 DWORD dwHeight,
489 DWORD dwStride,
490 LPBYTE lpaResult,
491 PBMCALLBACKFN pfnCallback,
492 ULONG ulCallbackData
493 )
494{
495 size_t i = (size_t)hcmTransform;
496 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
497
498 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
499 SetLastError(ERROR_INVALID_HANDLE);
500 return FALSE;
501 }
502
503 CIccCmm *pCmm = g_Transforms[i-256];
504 LPBYTE lpSrcLine;
505 DWORD j;
506
507 //Check if color types matches transform color spaces
508 if (!IsValidBitmapType(bmInput, pCmm->GetSourceSpace()) ||
509 pCmm->GetDestSpace() != icSigGamutData) {
510 SetLastError(ERROR_INVALID_DATATYPE);
511 return FALSE;
512 }
513
514 for (j=0; j<dwHeight; j++) {
515 lpSrcLine = lpSrcBits;
516
517 for (i=0; i<dwWidth; i++) {
518 switch(bmInput) {
519 case BM_x555Lab:
520 case BM_x555RGB:
521 case BM_x555XYZ:
522 case BM_x555Yxy:
523 case BM_x555G3CH:
524 {
525 icUInt16Number bits = *((icUInt16Number*)lpSrcBits);
526
527 srcPixel[0] = (icFloatNumber)((bits&0x7C00)>>10) / 31.0f;
528 srcPixel[1] = (icFloatNumber)((bits&0x03E0)>>5) / 31.0f;
529 srcPixel[2] = (icFloatNumber)(bits&0x001F) / 31.0f;
530
531 lpSrcBits += 2;
532 }
533 break;
534
535 //
536 // Packed 8 bits per channel => 8bpp for GRAY and
537 // 24bpp for the 3 channel colors, more for hifi channels
538 //
539
540 case BM_LabTRIPLETS:
541 case BM_RGBTRIPLETS:
542 case BM_BGRTRIPLETS:
543 case BM_XYZTRIPLETS:
544 case BM_YxyTRIPLETS:
545 case BM_G3CHTRIPLETS:
546 {
547 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
548
549 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
550 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
551 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
552
553 lpSrcBits += 3;
554
555 }
556 break;
557
558 case BM_5CHANNEL:
559 {
560 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
561
562 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
563 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
564 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
565 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
566 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
567
568 lpSrcBits += 5;
569
570 }
571 break;
572
573 case BM_6CHANNEL:
574 {
575 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
576
577 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
578 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
579 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
580 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
581 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
582 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
583
584 lpSrcBits += 6;
585
586 }
587 break;
588
589 case BM_7CHANNEL:
590 {
591 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
592
593 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
594 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
595 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
596 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
597 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
598 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
599 srcPixel[6] = (icFloatNumber)bits[6] / 255.0f;
600
601 lpSrcBits += 7;
602
603 }
604 break;
605
606 case BM_8CHANNEL:
607 {
608 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
609
610 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
611 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
612 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
613 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
614 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
615 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
616 srcPixel[6] = (icFloatNumber)bits[6] / 255.0f;
617 srcPixel[7] = (icFloatNumber)bits[7] / 255.0f;
618
619 lpSrcBits += 8;
620
621 }
622 break;
623
624 case BM_GRAY:
625 {
626 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
627
628 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
629
630 lpSrcBits++;
631
632 }
633 break;
634
635 //
636 // 32bpp - 8 bits per channel. The most significant byte is ignored
637 // for the 3 channel colors.
638 //
639
640 case BM_xRGBQUADS:
641 case BM_xG3CHQUADS:
642 {
643 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
644
645 srcPixel[2] = (icFloatNumber)bits[0] / 255.0f;
646 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
647 srcPixel[0] = (icFloatNumber)bits[2] / 255.0f;
648
649 lpSrcBits += 4;
650
651 }
652 break;
653
654 case BM_xBGRQUADS:
655 {
656 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
657
658 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
659 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
660 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
661
662 lpSrcBits += 4;
663
664 }
665 break;
666
667 case BM_KYMCQUADS:
668 {
669 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
670
671 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
672 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
673 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
674 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
675
676 lpSrcBits += 4;
677
678 }
679 break;
680
681 case BM_CMYKQUADS:
682 {
683 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
684
685 srcPixel[3] = (icFloatNumber)bits[0] / 255.0f;
686 srcPixel[2] = (icFloatNumber)bits[1] / 255.0f;
687 srcPixel[1] = (icFloatNumber)bits[2] / 255.0f;
688 srcPixel[0] = (icFloatNumber)bits[3] / 255.0f;
689
690 lpSrcBits += 4;
691
692 }
693 break;
694
695 //
696 // 32bpp - 10 bits per channel. The 2 most significant bits are ignored.
697 //
698
699 case BM_10b_Lab:
700 case BM_10b_RGB:
701 case BM_10b_XYZ:
702 case BM_10b_Yxy:
703 case BM_10b_G3CH:
704 {
705 icUInt32Number bits = *((icUInt32Number*)lpSrcBits);
706
707 srcPixel[0] = (icFloatNumber)((bits&0x3FF00000)>>20) / 1023.0f;
708 srcPixel[1] = (icFloatNumber)((bits&0x000FFC00)>>10) / 1023.0f;
709 srcPixel[2] = (icFloatNumber)(bits&0x000003FF) / 1023.0f;
710
711 lpSrcBits += 4;
712 }
713 break;
714
715 //
716 // Packed 16 bits per channel => 16bpp for GRAY and
717 // 48bpp for the 3 channel colors.
718 //
719
720 case BM_16b_Lab:
721 case BM_16b_RGB:
722 case BM_16b_XYZ:
723 case BM_16b_Yxy:
724 case BM_16b_G3CH:
725 {
726 icUInt16Number *bits = (icUInt16Number*)lpSrcBits;
727
728 srcPixel[0] = (icFloatNumber)bits[0] / 65535.0f;
729 srcPixel[1] = (icFloatNumber)bits[1] / 65535.0f;
730 srcPixel[2] = (icFloatNumber)bits[2] / 65535.0f;
731
732 lpSrcBits += 6;
733 }
734 break;
735
736 case BM_16b_GRAY:
737 {
738 icUInt16Number *bits = (icUInt16Number*)lpSrcBits;
739
740 srcPixel[0] = (icFloatNumber)bits[0] / 65535.0f;
741
742 lpSrcBits += 2;
743 }
744 break;
745
746 //
747 // 16 bpp - 5 bits for Red & Blue, 6 bits for Green
748 //
749
750 case BM_565RGB:
751 {
752 icUInt16Number bits = *((icUInt16Number*)lpSrcBits);
753
754 srcPixel[0] = (icFloatNumber)((bits&0xF800)>>11) / 31.0f;
755 srcPixel[1] = (icFloatNumber)((bits&0x07E0)>>5) / 63.0f;
756 srcPixel[2] = (icFloatNumber)(bits&0x001F) / 31.0f;
757
758 lpSrcBits += 2;
759 }
760 break;
761
762 //
763 // 32bpp - named color indices (1-based)
764 //
765
766 case BM_NAMED_INDEX:
767 default:
768 SetLastError(ERROR_UNSUPPORTED_TYPE);
769 return FALSE;
770
771 }
772
773
774 if (pCmm->Apply(destPixel, srcPixel)!=icCmmStatOk) {
775 SetLastError(ERROR_FUNCTION_FAILED);
776 return FALSE;
777 }
778
779 *lpaResult = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
780
781 lpaResult++;
782 }
783
784 if (pfnCallback && !pfnCallback(j, dwHeight, ulCallbackData)) {
785 SetLastError(ERROR_CANCELLED);
786 return FALSE;
787 }
788
789 if (!dwStride) {
790 size_t dwAlignedSize = (((lpSrcBits - lpSrcLine) + 3)>>2)<<2;
791 lpSrcBits = lpSrcLine + dwAlignedSize;
792 }
793 else {
794 lpSrcBits = lpSrcLine + dwStride;
795 }
796 }
797 return TRUE;
798}
799
800
801/* Optionally defined
802BOOL WINAPI CMCreateDeviceLinkProfile(
803 LPHPROFILE lpahProfiles, // array of profiles
804 DWORD nProfiles, // profile array size
805 PDWORD padwIntents, // array of rendering intents
806 DWORD nIntents, // intent array size
807 DWORD dwFlags, // transform creation flags
808 LPBYTE *lpProfileData // pointer to pointer to buffer
809 )
810{
811 SetLastError(ERROR_NOT_SUPPORTED);
812 return FALSE;
813}
814*/
815
817{
818 switch(nIntent) {
819 case INTENT_PERCEPTUAL:
820 return icPerceptual;
821
822 case INTENT_SATURATION:
823 return icSaturation;
824
825 case INTENT_RELATIVE_COLORIMETRIC:
827
828 case INTENT_ABSOLUTE_COLORIMETRIC:
830
831 default:
832 return icUnknownIntent;
833 }
834
835 return icUnknownIntent;
836}
837
839 LPHPROFILE lpahProfiles, // array of profile handles
840 DWORD nProfiles, // profile handle array size
841 PDWORD padwIntents, // array of rendering intents
842 DWORD nIntents, // intent array size
843 DWORD dwFlags // transform creation flags
844 )
845{
846 size_t rv;
847 DWORD i, n=0;
848 DWORD dwIntent;
849
850 if (!nIntents) {
851 SetLastError(ERROR_BAD_ARGUMENTS);
852 return 0;
853 }
854
855 dwIntent = padwIntents[n];
856
857 for (rv=0; rv<AVAILABLE_TRANSFORMS; rv++) {
858 if (!g_Transforms[rv])
859 break;
860 }
861
862 if (rv==AVAILABLE_TRANSFORMS) {
863 SetLastError(ERROR_OUT_OF_STRUCTURES);
864 return 0;
865 }
866
867 CIccCmm *pCmm = new CIccCmm();
868
869 for (i=0; i<nProfiles; i++) {
870 CIccProfile *pProfile = OpenProfile(lpahProfiles[i]);
871
872 if (!pProfile) {
873 delete pCmm;
874 SetLastError(ERROR_BAD_ARGUMENTS);
875 return 0;
876 }
877
878 if (pCmm->AddXform(pProfile,
879 GetRenderingIntent(dwIntent),
881 NULL,
882 (i+1==nProfiles && (dwFlags & ENABLE_GAMUT_CHECKING)) ? icXformLutGamut : icXformLutColor
883 ) != icCmmStatOk) {
884 delete pProfile;
885 delete pCmm;
886 SetLastError(ERROR_BAD_ARGUMENTS);
887 return 0;
888 }
889
890 if (i) {
891 if (n+1<nIntents) {
892 n++;
893 }
894 dwIntent = padwIntents[n];
895 }
896 }
897
898 if (pCmm->Begin()!=icCmmStatOk) {
899 delete pCmm;
900 SetLastError(ERROR_FUNCTION_FAILED);
901 return 0;
902 }
903
904 pCmm->RemoveAllIO();
905
906 pCmm = CIccMruCmm::Attach(pCmm);
907
908 g_Transforms[rv] = pCmm;
909
910 return (HCMTRANSFORM)(rv+256);
911}
912
913
914/*
915BOOL WINAPI CMCreateProfile(
916 LPLOGCOLORSPACEA lpColorSpace, // pointer to a color space
917 LPBYTE *lpProfileData // pointer to pointer to buffer
918 )
919{
920 SetLastError(ERROR_NOT_SUPPORTED);
921 return FALSE;
922}
923
924
925BOOL WINAPI CMCreateProfileW(
926 LPLOGCOLORSPACEW lpColorSpace, // pointer to a color space
927 LPBYTE *lpProfileData // pointer to pointer to buffer
928 )
929{
930 SetLastError(ERROR_NOT_SUPPORTED);
931 return FALSE;
932}
933*/
934
935static CIccProfile *GetProfileFromBuf(LPBYTE lpBuf)
936{
937 BYTE size[4];
938 size[3] = lpBuf[0];
939 size[2] = lpBuf[1];
940 size[1] = lpBuf[2];
941 size[0] = lpBuf[3];
942
943 DWORD dwSize = *((DWORD*)&size[0]);
944
945 if (!(dwSize > 128 && lpBuf[36]=='a' && lpBuf[37]=='c' && lpBuf[38]=='s' && lpBuf[39]=='p')) {
946 return NULL;
947 }
948
949 return OpenIccProfile(lpBuf, dwSize);
950}
951
952
953HCMTRANSFORM WINAPI CMCreateTransformExt(
954 LPLOGCOLORSPACEA lpColorSpace, // color space pointer
955 LPBYTE lpDevCharacter, // device profile
956 LPBYTE lpTargetDevCharacter, // target profile
957 DWORD dwFlags // creation flags
958 )
959{
960 size_t rv;
961
962 for (rv=0; rv<AVAILABLE_TRANSFORMS; rv++) {
963 if (!g_Transforms[rv])
964 break;
965 }
966
967 if (rv==AVAILABLE_TRANSFORMS) {
968 SetLastError(ERROR_BAD_ARGUMENTS);
969 return 0;
970 }
971
972 CIccCmm *pCmm = new CIccCmm();
973 CIccProfile *pProfile;
974
975 LPBYTE lpSrcProfileBuf=NULL;
976
977 if (lpColorSpace) {
978 if (!CreateProfileFromLogColorSpaceA(lpColorSpace, &lpSrcProfileBuf) || !lpSrcProfileBuf) {
979 SetLastError(ERROR_INVALID_HANDLE);
980 return 0;
981 }
982
983 pProfile = GetProfileFromBuf(lpSrcProfileBuf);
984
985 if (!pProfile) {
986 GlobalFree(lpSrcProfileBuf);
987 SetLastError(ERROR_INVALID_HANDLE);
988 return 0;
989 }
990
991 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
992 delete pProfile;
993 delete pCmm;
994 GlobalFree(lpSrcProfileBuf);
995 return 0;
996 }
997 }
998
999 if (lpTargetDevCharacter) {
1000 pProfile = GetProfileFromBuf(lpTargetDevCharacter);
1001 if (!pProfile) {
1002 delete pCmm;
1003 if (lpSrcProfileBuf)
1004 GlobalFree(lpSrcProfileBuf);
1005 return 0;
1006 }
1007 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1008 delete pProfile;
1009 delete pCmm;
1010 if (lpSrcProfileBuf)
1011 GlobalFree(lpSrcProfileBuf);
1012 return 0;
1013 }
1014
1015 //If we are connecting a target between and input and output device profile we need to insert the target profile again
1016 if (lpSrcProfileBuf && lpDevCharacter) {
1017 pProfile = GetProfileFromBuf(lpTargetDevCharacter);
1018 if (!pProfile) {
1019 delete pCmm;
1020 GlobalFree(lpSrcProfileBuf);
1021 return 0;
1022 }
1023 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1024 delete pProfile;
1025 delete pCmm;
1026 GlobalFree(lpSrcProfileBuf);
1027 return 0;
1028 }
1029 }
1030 }
1031
1032 if (lpDevCharacter) {
1033 pProfile = GetProfileFromBuf(lpDevCharacter);
1034 if (!pProfile) {
1035 delete pCmm;
1036 if (lpSrcProfileBuf)
1037 GlobalFree(lpSrcProfileBuf);
1038 return 0;
1039 }
1040 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1041 delete pProfile;
1042 delete pCmm;
1043 if (lpSrcProfileBuf)
1044 GlobalFree(lpSrcProfileBuf);
1045 return 0;
1046 }
1047
1048 }
1049
1050 if (pCmm->Begin()!=icCmmStatOk) {
1051 delete pCmm;
1052 if (lpSrcProfileBuf)
1053 GlobalFree(lpSrcProfileBuf);
1054 return 0;
1055 }
1056
1057 pCmm->RemoveAllIO();
1058
1059 if (lpSrcProfileBuf)
1060 GlobalFree(lpSrcProfileBuf);
1061
1062 g_Transforms[rv] = pCmm;
1063
1064 return (HCMTRANSFORM)(rv+256);
1065}
1066
1067
1068HCMTRANSFORM WINAPI CMCreateTransformExtW(
1069 LPLOGCOLORSPACEW lpColorSpace, // color space pointer
1070 LPBYTE lpDevCharacter, // device profile
1071 LPBYTE lpTargetDevCharacter, // target profile
1072 DWORD dwFlags // creation flags
1073 )
1074{
1075 size_t rv;
1076
1077 for (rv=0; rv<AVAILABLE_TRANSFORMS; rv++) {
1078 if (!g_Transforms[rv])
1079 break;
1080 }
1081
1082 if (rv==AVAILABLE_TRANSFORMS) {
1083 return 0;
1084 }
1085
1086 CIccCmm *pCmm = new CIccCmm();
1087 CIccProfile *pProfile;
1088
1089 LPBYTE lpSrcProfileBuf=NULL;
1090
1091 if (lpColorSpace) {
1092 if (!CreateProfileFromLogColorSpaceW(lpColorSpace, &lpSrcProfileBuf) || !lpSrcProfileBuf) {
1093 return 0;
1094 }
1095
1096 pProfile = GetProfileFromBuf(lpSrcProfileBuf);
1097
1098 if (!pProfile) {
1099 GlobalFree(lpSrcProfileBuf);
1100 return 0;
1101 }
1102
1103 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1104 delete pProfile;
1105 delete pCmm;
1106 GlobalFree(lpSrcProfileBuf);
1107 return 0;
1108 }
1109 }
1110
1111 if (lpTargetDevCharacter) {
1112 pProfile = GetProfileFromBuf(lpTargetDevCharacter);
1113 if (!pProfile) {
1114 delete pCmm;
1115 if (lpSrcProfileBuf)
1116 GlobalFree(lpSrcProfileBuf);
1117 return 0;
1118 }
1119 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1120 delete pProfile;
1121 delete pCmm;
1122 if (lpSrcProfileBuf)
1123 GlobalFree(lpSrcProfileBuf);
1124 return 0;
1125 }
1126
1127 //If we are connecting a target between and input and output device profile we need to insert the target profile again
1128 if (lpSrcProfileBuf && lpDevCharacter) {
1129 pProfile = GetProfileFromBuf(lpTargetDevCharacter);
1130 if (!pProfile) {
1131 delete pCmm;
1132 GlobalFree(lpSrcProfileBuf);
1133 return 0;
1134 }
1135 if (pCmm->AddXform(pProfile)!=icCmmStatOk) {
1136 delete pProfile;
1137 delete pCmm;
1138 GlobalFree(lpSrcProfileBuf);
1139 return 0;
1140 }
1141 }
1142 }
1143
1144 if (lpDevCharacter) {
1145 pProfile = GetProfileFromBuf(lpDevCharacter);
1146 if (!pProfile) {
1147 delete pCmm;
1148 if (lpSrcProfileBuf)
1149 GlobalFree(lpSrcProfileBuf);
1150 return 0;
1151 }
1152 if (pCmm->AddXform(*pProfile)!=icCmmStatOk) {
1153 delete pProfile;
1154 delete pCmm;
1155 if (lpSrcProfileBuf)
1156 GlobalFree(lpSrcProfileBuf);
1157 return 0;
1158 }
1159
1160 }
1161
1162 if (pCmm->Begin()!=icCmmStatOk) {
1163 delete pCmm;
1164 if (lpSrcProfileBuf)
1165 GlobalFree(lpSrcProfileBuf);
1166 return 0;
1167 }
1168
1169 if (lpSrcProfileBuf)
1170 GlobalFree(lpSrcProfileBuf);
1171
1172 g_Transforms[rv] = pCmm;
1173
1174 return (HCMTRANSFORM)(rv+256);
1175}
1176
1177
1178HCMTRANSFORM WINAPI CMCreateTransform(
1179 LPLOGCOLORSPACEA lpColorSpace, // color space pointer
1180 LPBYTE lpDevCharacter, // device profile
1181 LPBYTE lpTargetDevCharacter // target profile
1182 )
1183{
1184 return CMCreateTransformExt(lpColorSpace, lpDevCharacter, lpTargetDevCharacter, NORMAL_MODE);
1185}
1186
1187
1188HCMTRANSFORM WINAPI CMCreateTransformW(
1189 LPLOGCOLORSPACEW lpColorSpace, // color space pointer
1190 LPBYTE lpDevCharacter, // device profile
1191 LPBYTE lpTargetDevCharacter // target profile
1192 )
1193{
1194 return CMCreateTransformExtW(lpColorSpace, lpDevCharacter, lpTargetDevCharacter, NORMAL_MODE);
1195}
1196
1197
1198
1199
1201 HCMTRANSFORM hcmTransform
1202 )
1203{
1204 size_t i = (size_t)hcmTransform;
1205
1206 if (i>256 && i<256+AVAILABLE_TRANSFORMS && g_Transforms[i-256]) {
1207 delete g_Transforms[i-256];
1208 g_Transforms[i-256] = NULL;
1209
1210 return TRUE;
1211 }
1212
1213 SetLastError(ERROR_INVALID_HANDLE);
1214 return FALSE;
1215}
1216
1217
1218DWORD WINAPI CMGetInfo(
1219 DWORD dwInfo
1220 )
1221{
1222 switch (dwInfo) {
1223 case CMM_DESCRIPTION:
1224 return IDS_DESCRIPTION;
1225
1226 case CMM_DLL_VERSION:
1227 return 0x00010000;
1228
1229 case CMM_DRIVER_VERSION:
1230 return 0x01;
1231
1232 case CMM_IDENT:
1233 return icSigDemoIccMAX;
1234
1235 case CMM_LOGOICON:
1236 return IDI_LOGO;
1237
1238 case CMM_VERSION:
1239 return 0x00500008;
1240
1241 case CMM_WIN_VERSION:
1242 return 0x00040000;
1243
1244 }
1245 return 0;
1246}
1247
1248
1250 HPROFILE hProfile,
1251 LPBOOL lpbValid
1252 )
1253{
1254 if (!lpbValid) {
1255 SetLastError(ERROR_BAD_ARGUMENTS);
1256 return FALSE;
1257 }
1258
1259 CIccProfile *pProfile = OpenProfile(hProfile);
1260
1261 if (pProfile) {
1262 std::string report;
1263
1264 if (pProfile->Validate(report)<=icValidateNonCompliant) {
1265 *lpbValid = TRUE;
1266 }
1267 else {
1268 *lpbValid = FALSE;
1269 }
1270 delete pProfile;
1271
1272 return TRUE;
1273 }
1274
1275 *lpbValid = FALSE;
1276
1277 SetLastError(ERROR_INVALID_HANDLE);
1278 return FALSE;
1279}
1280
1282 HCMTRANSFORM hcmTransform,
1283 LPCOLOR lpaInputColors,
1284 DWORD nColors,
1285 COLORTYPE ctInput,
1286 LPCOLOR lpaOutputColors,
1287 COLORTYPE ctOutput
1288 )
1289{
1290 size_t i = (size_t)hcmTransform;
1291 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
1292
1293 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
1294 SetLastError(ERROR_INVALID_HANDLE);
1295 return FALSE;
1296 }
1297
1298 CIccCmm *pCmm = g_Transforms[i-256];
1299
1300 //Check if color types matches transform color spaces
1301 if (!IsValidColorType(ctInput, pCmm->GetSourceSpace()) ||
1302 !IsValidColorType(ctOutput, pCmm->GetDestSpace())) {
1303 SetLastError(ERROR_INVALID_DATATYPE);
1304 return FALSE;
1305 }
1306
1307
1308 for (i=0; i<nColors; i++) {
1309 switch (ctInput) {
1310 case COLOR_GRAY:
1311 srcPixel[0] = (icFloatNumber)(lpaInputColors->gray.gray) / 65535.0f;
1312 break;
1313
1314 case COLOR_RGB:
1315 srcPixel[0] = (icFloatNumber)(lpaInputColors->rgb.red) / 65535.0f;
1316 srcPixel[1] = (icFloatNumber)(lpaInputColors->rgb.green) / 65535.0f;
1317 srcPixel[2] = (icFloatNumber)(lpaInputColors->rgb.blue) / 65535.0f;
1318 break;
1319
1320 case COLOR_XYZ:
1321 srcPixel[0] = (icFloatNumber)(lpaInputColors->XYZ.X) / 65535.0f;
1322 srcPixel[1] = (icFloatNumber)(lpaInputColors->XYZ.Y) / 65535.0f;
1323 srcPixel[2] = (icFloatNumber)(lpaInputColors->XYZ.Z) / 65535.0f;
1324
1325 break;
1326
1327 case COLOR_Yxy:
1328 srcPixel[0] = (icFloatNumber)(lpaInputColors->Yxy.Y) / 65535.0f;
1329 srcPixel[1] = (icFloatNumber)(lpaInputColors->Yxy.x) / 65535.0f;
1330 srcPixel[2] = (icFloatNumber)(lpaInputColors->Yxy.y) / 65535.0f;
1331 break;
1332
1333 case COLOR_Lab:
1334 srcPixel[0] = (icFloatNumber)(lpaInputColors->Lab.L) / 65535.0f;
1335 srcPixel[1] = (icFloatNumber)(lpaInputColors->Lab.a) / 65535.0f;
1336 srcPixel[2] = (icFloatNumber)(lpaInputColors->Lab.b) / 65535.0f;
1337 if (pCmm->GetFirstXformSource()!=icSigDevLabData) { //
1338 CIccPCS::Lab2ToLab4(srcPixel, srcPixel);
1339 }
1340 break;
1341
1342 case COLOR_3_CHANNEL: // WORD per channel
1343 srcPixel[0] = (icFloatNumber)(lpaInputColors->gen3ch.ch1) / 65535.0f;
1344 srcPixel[1] = (icFloatNumber)(lpaInputColors->gen3ch.ch2) / 65535.0f;
1345 srcPixel[2] = (icFloatNumber)(lpaInputColors->gen3ch.ch3) / 65535.0f;
1346 break;
1347
1348 case COLOR_CMYK:
1349 srcPixel[0] = (icFloatNumber)(lpaInputColors->cmyk.cyan) / 65535.0f;
1350 srcPixel[1] = (icFloatNumber)(lpaInputColors->cmyk.magenta) / 65535.0f;
1351 srcPixel[2] = (icFloatNumber)(lpaInputColors->cmyk.yellow) / 65535.0f;
1352 srcPixel[3] = (icFloatNumber)(lpaInputColors->cmyk.black) / 65535.0f;
1353 break;
1354
1355 // Hifi colors use BYTE per channel
1356 case COLOR_8_CHANNEL:
1357 srcPixel[7] = (icFloatNumber)(lpaInputColors->hifi.channel[7]) / 255.0f;
1358 //No break here!
1359
1360 case COLOR_7_CHANNEL:
1361 srcPixel[6] = (icFloatNumber)(lpaInputColors->hifi.channel[6]) / 255.0f;
1362 //No break here!
1363
1364 case COLOR_6_CHANNEL:
1365 srcPixel[5] = (icFloatNumber)(lpaInputColors->hifi.channel[5]) / 255.0f;
1366 //No break here!
1367
1368 case COLOR_5_CHANNEL:
1369 srcPixel[0] = (icFloatNumber)(lpaInputColors->hifi.channel[0]) / 255.0f;
1370 srcPixel[1] = (icFloatNumber)(lpaInputColors->hifi.channel[1]) / 255.0f;
1371 srcPixel[2] = (icFloatNumber)(lpaInputColors->hifi.channel[2]) / 255.0f;
1372 srcPixel[3] = (icFloatNumber)(lpaInputColors->hifi.channel[3]) / 255.0f;
1373 srcPixel[4] = (icFloatNumber)(lpaInputColors->hifi.channel[4]) / 255.0f;
1374 break;
1375
1376 default:
1377 SetLastError(ERROR_UNSUPPORTED_TYPE);
1378 return FALSE;
1379 }
1380 lpaInputColors++;
1381
1382 if (pCmm->Apply(destPixel, srcPixel) != icCmmStatOk) {
1383 SetLastError(ERROR_FUNCTION_FAILED);
1384 return FALSE;
1385 }
1386
1387 switch (ctOutput) {
1388 case COLOR_GRAY:
1389 lpaOutputColors->gray.gray = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1390 break;
1391
1392 case COLOR_RGB:
1393 lpaOutputColors->rgb.red = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1394 lpaOutputColors->rgb.green = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1395 lpaOutputColors->rgb.blue = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1396 break;
1397
1398 case COLOR_XYZ:
1399 lpaOutputColors->XYZ.X = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1400 lpaOutputColors->XYZ.Y = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1401 lpaOutputColors->XYZ.Z = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1402 break;
1403
1404 case COLOR_Yxy:
1405 lpaOutputColors->Yxy.Y = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1406 lpaOutputColors->Yxy.x = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1407 lpaOutputColors->Yxy.y = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1408 break;
1409
1410 case COLOR_Lab:
1411 if (pCmm->GetLastXformDest()!=icSigDevLabData) {
1412 CIccPCS::Lab4ToLab2(destPixel, destPixel);
1413 }
1414 lpaOutputColors->Lab.L = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1415 lpaOutputColors->Lab.a = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1416 lpaOutputColors->Lab.b = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1417 break;
1418
1419 case COLOR_3_CHANNEL: // WORD per channel
1420 lpaOutputColors->gen3ch.ch1 = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1421 lpaOutputColors->gen3ch.ch2 = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1422 lpaOutputColors->gen3ch.ch3 = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1423 break;
1424
1425 case COLOR_CMYK:
1426 lpaOutputColors->cmyk.cyan = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
1427 lpaOutputColors->cmyk.magenta = (icUInt16Number)(UnitClip(destPixel[1]) * 65535.0 + 0.5);
1428 lpaOutputColors->cmyk.yellow = (icUInt16Number)(UnitClip(destPixel[2]) * 65535.0 + 0.5);
1429 lpaOutputColors->cmyk.black = (icUInt16Number)(UnitClip(destPixel[3]) * 65535.0 + 0.5);
1430 break;
1431
1432 // Hifi colors use BYTE per channel
1433 case COLOR_8_CHANNEL:
1434 lpaOutputColors->hifi.channel[7] = (icUInt8Number)(UnitClip(destPixel[7]) * 255.0 + 0.5);
1435 //No break here!
1436
1437 case COLOR_7_CHANNEL:
1438 lpaOutputColors->hifi.channel[6] = (icUInt8Number)(UnitClip(destPixel[6]) * 255.0 + 0.5);
1439 //No break here!
1440
1441 case COLOR_6_CHANNEL:
1442 lpaOutputColors->hifi.channel[5] = (icUInt8Number)(UnitClip(destPixel[5]) * 255.0 + 0.5);
1443 //No break here!
1444
1445 case COLOR_5_CHANNEL:
1446 lpaOutputColors->hifi.channel[0] = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1447 lpaOutputColors->hifi.channel[1] = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1448 lpaOutputColors->hifi.channel[2] = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1449 lpaOutputColors->hifi.channel[3] = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
1450 lpaOutputColors->hifi.channel[4] = (icUInt8Number)(UnitClip(destPixel[4]) * 255.0 + 0.5);
1451 break;
1452
1453 default:
1454 SetLastError(ERROR_UNSUPPORTED_TYPE);
1455 return FALSE;
1456 }
1457 lpaOutputColors++;
1458 }
1459 return TRUE;
1460}
1461
1462
1463BOOL WINAPI CMTranslateRGB(
1464 HCMTRANSFORM hcmTransform,
1465 COLORREF ColorRef,
1466 LPCOLORREF lpColorRef,
1467 DWORD dwFlags
1468 )
1469{
1470 size_t i = (size_t)hcmTransform;
1471 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
1472
1473 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
1474 SetLastError(ERROR_INVALID_HANDLE);
1475 return FALSE;
1476 }
1477
1478 if (dwFlags != CMS_FORWARD) {
1479 SetLastError(ERROR_BAD_ARGUMENTS);
1480 return FALSE;
1481 }
1482
1483 CIccCmm *pCmm = g_Transforms[i-256];
1484
1485 //Check if color types matches transform color spaces
1486 if (pCmm->GetSourceSpace()!=icSigRgbData ||
1487 pCmm->GetDestSpace() != icSigRgbData) {
1488 SetLastError(ERROR_INVALID_DATATYPE);
1489 return FALSE;
1490 }
1491
1492 LPBYTE pSrc = (LPBYTE)(&ColorRef);
1493
1494 srcPixel[2] = (icFloatNumber)(*pSrc++) / 255.0f;
1495 srcPixel[1] = (icFloatNumber)(*pSrc++) / 255.0f;
1496 srcPixel[0] = (icFloatNumber)(*pSrc++) / 255.0f;
1497
1498 if (pCmm->Apply(destPixel, srcPixel)!=icCmmStatOk) {
1499 SetLastError(ERROR_FUNCTION_FAILED);
1500 return FALSE;
1501 }
1502
1503 LPBYTE pDest = (LPBYTE)lpColorRef;
1504 *pDest++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1505 *pDest++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1506 *pDest++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1507 *pDest = *pSrc;
1508
1509 return TRUE;
1510}
1511
1512
1514 HCMTRANSFORM hcmTransform,
1515 LPBYTE lpSrcBits,
1516 BMFORMAT bmInput,
1517 DWORD dwWidth,
1518 DWORD dwHeight,
1519 DWORD dwInputStride,
1520 LPBYTE lpDestBits,
1521 BMFORMAT bmOutput,
1522 DWORD dwOutputStride,
1523 LPBMCALLBACKFN lpfnCallback,
1524 ULONG ulCallbackData
1525 )
1526{
1527 size_t i = (size_t)hcmTransform;
1528 icFloatNumber srcPixel[MAX_COLOR_CHANNELS], destPixel[MAX_COLOR_CHANNELS];
1529
1530 if (i<256 || i>=256+AVAILABLE_TRANSFORMS || !g_Transforms[i-256]) {
1531 SetLastError(ERROR_INVALID_HANDLE);
1532 return FALSE;
1533 }
1534
1535 CIccCmm *pCmm = g_Transforms[i-256];
1536 LPBYTE lpSrcLine;
1537 LPBYTE lpDestLine;
1538 DWORD j;
1539
1540 //Check if color types matches transform color spaces
1541 if (!IsValidBitmapType(bmInput, pCmm->GetSourceSpace()) ||
1542 !IsValidBitmapType(bmOutput, pCmm->GetDestSpace())) {
1543 SetLastError(ERROR_INVALID_DATATYPE);
1544 return FALSE;
1545 }
1546
1547 for (j=0; j<dwHeight; j++) {
1548 lpSrcLine = lpSrcBits;
1549 lpDestLine = lpDestBits;
1550
1551 for (i=0; i<dwWidth; i++) {
1552 switch(bmInput) {
1553 case BM_x555Lab:
1554 {
1555 icUInt16Number bits = *((icUInt16Number*)lpSrcBits);
1556
1557 srcPixel[0] = (icFloatNumber)((bits&0x7C00)>>10) / 31.0f;
1558 srcPixel[1] = (icFloatNumber)((bits&0x03E0)>>5) / 31.0f;
1559 srcPixel[2] = (icFloatNumber)(bits&0x001F) / 31.0f;
1560
1561 if (pCmm->GetSourceSpace()!=icSigDevLabData) {
1562 CIccPCS::Lab2ToLab4(srcPixel, srcPixel);
1563 }
1564
1565 lpSrcBits += 2;
1566 }
1567 break;
1568
1569 case BM_x555RGB:
1570 case BM_x555XYZ:
1571 case BM_x555Yxy:
1572 case BM_x555G3CH:
1573 {
1574 icUInt16Number bits = *((icUInt16Number*)lpSrcBits);
1575
1576 srcPixel[0] = (icFloatNumber)((bits&0x7C00)>>10) / 31.0f;
1577 srcPixel[1] = (icFloatNumber)((bits&0x03E0)>>5) / 31.0f;
1578 srcPixel[2] = (icFloatNumber)(bits&0x001F) / 31.0f;
1579
1580 lpSrcBits += 2;
1581 }
1582 break;
1583
1584 //
1585 // Packed 8 bits per channel => 8bpp for GRAY and
1586 // 24bpp for the 3 channel colors, more for hifi channels
1587 //
1588
1589 case BM_LabTRIPLETS:
1590 {
1591 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1592
1593 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1594 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1595 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1596
1597 if (pCmm->GetSourceSpace()!=icSigDevLabData) {
1598 CIccPCS::Lab2ToLab4(srcPixel, srcPixel);
1599 }
1600
1601 lpSrcBits += 3;
1602
1603 }
1604 break;
1605
1606 case BM_RGBTRIPLETS:
1607 case BM_XYZTRIPLETS:
1608 case BM_YxyTRIPLETS:
1609 case BM_G3CHTRIPLETS:
1610 {
1611 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1612
1613 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1614 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1615 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1616
1617 lpSrcBits += 3;
1618
1619 }
1620 break;
1621
1622 case BM_BGRTRIPLETS:
1623 {
1624 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1625
1626 srcPixel[0] = (icFloatNumber)bits[2] / 255.0f;
1627 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1628 srcPixel[2] = (icFloatNumber)bits[0] / 255.0f;
1629
1630 lpSrcBits += 3;
1631
1632 }
1633 break;
1634
1635
1636 case BM_5CHANNEL:
1637 {
1638 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1639
1640 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1641 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1642 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1643 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
1644 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
1645
1646 lpSrcBits += 5;
1647
1648 }
1649 break;
1650
1651 case BM_6CHANNEL:
1652 {
1653 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1654
1655 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1656 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1657 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1658 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
1659 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
1660 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
1661
1662 lpSrcBits += 6;
1663
1664 }
1665 break;
1666
1667 case BM_7CHANNEL:
1668 {
1669 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1670
1671 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1672 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1673 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1674 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
1675 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
1676 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
1677 srcPixel[6] = (icFloatNumber)bits[6] / 255.0f;
1678
1679 lpSrcBits += 7;
1680
1681 }
1682 break;
1683
1684 case BM_8CHANNEL:
1685 {
1686 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1687
1688 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1689 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1690 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1691 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
1692 srcPixel[4] = (icFloatNumber)bits[4] / 255.0f;
1693 srcPixel[5] = (icFloatNumber)bits[5] / 255.0f;
1694 srcPixel[6] = (icFloatNumber)bits[6] / 255.0f;
1695 srcPixel[7] = (icFloatNumber)bits[7] / 255.0f;
1696
1697 lpSrcBits += 8;
1698
1699 }
1700 break;
1701
1702 case BM_GRAY:
1703 {
1704 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1705
1706 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1707
1708 lpSrcBits++;
1709
1710 }
1711 break;
1712
1713 //
1714 // 32bpp - 8 bits per channel. The most significant byte is ignored
1715 // for the 3 channel colors.
1716 //
1717
1718 case BM_xRGBQUADS:
1719 case BM_xG3CHQUADS:
1720 {
1721 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1722
1723 srcPixel[2] = (icFloatNumber)bits[0] / 255.0f;
1724 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1725 srcPixel[0] = (icFloatNumber)bits[2] / 255.0f;
1726
1727 lpSrcBits += 4;
1728
1729 }
1730 break;
1731
1732 case BM_xBGRQUADS:
1733 {
1734 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1735
1736 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1737 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1738 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1739
1740 lpSrcBits += 4;
1741
1742 }
1743 break;
1744
1745 case BM_KYMCQUADS:
1746 {
1747 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1748
1749 srcPixel[0] = (icFloatNumber)bits[0] / 255.0f;
1750 srcPixel[1] = (icFloatNumber)bits[1] / 255.0f;
1751 srcPixel[2] = (icFloatNumber)bits[2] / 255.0f;
1752 srcPixel[3] = (icFloatNumber)bits[3] / 255.0f;
1753
1754 lpSrcBits += 4;
1755
1756 }
1757 break;
1758
1759 case BM_CMYKQUADS:
1760 {
1761 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1762
1763 srcPixel[3] = (icFloatNumber)bits[0] / 255.0f;
1764 srcPixel[2] = (icFloatNumber)bits[1] / 255.0f;
1765 srcPixel[1] = (icFloatNumber)bits[2] / 255.0f;
1766 srcPixel[0] = (icFloatNumber)bits[3] / 255.0f;
1767
1768 lpSrcBits += 4;
1769
1770 }
1771 break;
1772
1773 //
1774 // 32bpp - 10 bits per channel. The 2 most significant bits are ignored.
1775 //
1776
1777 case BM_10b_Lab:
1778 {
1779 icUInt32Number bits = *((icUInt32Number*)lpSrcBits);
1780
1781 srcPixel[0] = (icFloatNumber)((bits&0x3FF00000)>>20) / 1023.0f;
1782 srcPixel[1] = (icFloatNumber)((bits&0x000FFC00)>>10) / 1023.0f;
1783 srcPixel[2] = (icFloatNumber)(bits&0x000003FF) / 1023.0f;
1784
1785 if (pCmm->GetSourceSpace()!=icSigDevLabData) {
1786 CIccPCS::Lab2ToLab4(srcPixel, srcPixel);
1787 }
1788
1789 lpSrcBits += 4;
1790 }
1791 break;
1792
1793 case BM_10b_RGB:
1794 case BM_10b_XYZ:
1795 case BM_10b_Yxy:
1796 case BM_10b_G3CH:
1797 {
1798 icUInt32Number bits = *((icUInt32Number*)lpSrcBits);
1799
1800 srcPixel[0] = (icFloatNumber)((bits&0x3FF00000)>>20) / 1023.0f;
1801 srcPixel[1] = (icFloatNumber)((bits&0x000FFC00)>>10) / 1023.0f;
1802 srcPixel[2] = (icFloatNumber)(bits&0x000003FF) / 1023.0f;
1803
1804 lpSrcBits += 4;
1805 }
1806 break;
1807
1808 //
1809 // Packed 16 bits per channel => 16bpp for GRAY and
1810 // 48bpp for the 3 channel colors.
1811 //
1812
1813 case BM_16b_Lab:
1814 {
1815 icUInt16Number *bits = (icUInt16Number*)lpSrcBits;
1816
1817 srcPixel[0] = (icFloatNumber)bits[0] / 65535.0f;
1818 srcPixel[1] = (icFloatNumber)bits[1] / 65535.0f;
1819 srcPixel[2] = (icFloatNumber)bits[2] / 65535.0f;
1820
1821 if (pCmm->GetSourceSpace()!=icSigDevLabData) {
1822 CIccPCS::Lab2ToLab4(srcPixel, srcPixel);
1823 }
1824
1825 lpSrcBits += 6;
1826 }
1827 break;
1828
1829 case BM_16b_RGB:
1830 case BM_16b_XYZ:
1831 case BM_16b_Yxy:
1832 case BM_16b_G3CH:
1833 {
1834 icUInt16Number *bits = (icUInt16Number*)lpSrcBits;
1835
1836 srcPixel[0] = (icFloatNumber)bits[0] / 65535.0f;
1837 srcPixel[1] = (icFloatNumber)bits[1] / 65535.0f;
1838 srcPixel[2] = (icFloatNumber)bits[2] / 65535.0f;
1839
1840 lpSrcBits += 6;
1841 }
1842 break;
1843
1844 case BM_16b_GRAY:
1845 {
1846 icUInt16Number *bits = (icUInt16Number*)lpSrcBits;
1847
1848 srcPixel[0] = (icFloatNumber)bits[0] / 65535.0f;
1849
1850 lpSrcBits += 2;
1851 }
1852 break;
1853
1854 //
1855 // 16 bpp - 5 bits for Red & Blue, 6 bits for Green
1856 //
1857
1858 case BM_565RGB:
1859 {
1860 icUInt16Number bits = *((icUInt16Number*)lpSrcBits);
1861
1862 srcPixel[0] = (icFloatNumber)((bits&0xF800)>>11) / 31.0f;
1863 srcPixel[1] = (icFloatNumber)((bits&0x07E0)>>5) / 63.0f;
1864 srcPixel[2] = (icFloatNumber)(bits&0x001F) / 31.0f;
1865
1866 lpSrcBits += 2;
1867 }
1868 break;
1869
1870 //
1871 // 32bpp - named color indices (1-based)
1872 //
1873
1874 case BM_NAMED_INDEX:
1875 default:
1876 SetLastError(ERROR_UNSUPPORTED_TYPE);
1877 return FALSE;
1878
1879 }
1880
1881 if (pCmm->Apply(destPixel, srcPixel)!=icCmmStatOk) {
1882 SetLastError(ERROR_FUNCTION_FAILED);
1883 return FALSE;
1884 }
1885
1886 switch(bmOutput) {
1887 case BM_x555Lab:
1888 {
1889 if (pCmm->GetDestSpace()!=icSigDevLabData) {
1890 CIccPCS::Lab4ToLab2(destPixel, destPixel);
1891 }
1892 *((icUInt16Number*)lpDestBits) = ((icUInt16Number)(UnitClip(destPixel[0]) * 31.0 + 0.5) << 10) +
1893 ((icUInt16Number)(UnitClip(destPixel[1]) * 31.0 + 0.5) << 5) +
1894 (icUInt16Number)(UnitClip(destPixel[2]) * 31.0 + 0.5);
1895
1896 lpDestBits += 2;
1897 }
1898 break;
1899
1900 case BM_x555RGB:
1901 case BM_x555XYZ:
1902 case BM_x555Yxy:
1903 case BM_x555G3CH:
1904 {
1905 *((icUInt16Number*)lpDestBits) = ((icUInt16Number)(UnitClip(destPixel[0]) * 31.0 + 0.5) << 10) +
1906 ((icUInt16Number)(UnitClip(destPixel[1]) * 31.0 + 0.5) << 5) +
1907 (icUInt16Number)(UnitClip(destPixel[2]) * 31.0 + 0.5);
1908
1909 lpDestBits += 2;
1910 }
1911 break;
1912
1913 //
1914 // Packed 8 bits per channel => 8bpp for GRAY and
1915 // 24bpp for the 3 channel colors, more for hifi channels
1916 //
1917
1918 case BM_LabTRIPLETS:
1919 {
1920 if (pCmm->GetDestSpace()!=icSigDevLabData) {
1921 CIccPCS::Lab4ToLab2(destPixel, destPixel);
1922 }
1923 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1924 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1925 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1926 }
1927 break;
1928
1929 case BM_RGBTRIPLETS:
1930 case BM_XYZTRIPLETS:
1931 case BM_YxyTRIPLETS:
1932 case BM_G3CHTRIPLETS:
1933 {
1934 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1935 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1936 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1937 }
1938 break;
1939
1940 case BM_BGRTRIPLETS:
1941 {
1942 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1943 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1944 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1945 }
1946 break;
1947
1948 case BM_5CHANNEL:
1949 {
1950 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1951 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1952 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1953 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
1954 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[4]) * 255.0 + 0.5);
1955 }
1956 break;
1957
1958 case BM_6CHANNEL:
1959 {
1960 icUInt8Number *bits = (icUInt8Number*)lpSrcBits;
1961
1962 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1963 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1964 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1965 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
1966 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[4]) * 255.0 + 0.5);
1967 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[5]) * 255.0 + 0.5);
1968 }
1969 break;
1970
1971 case BM_7CHANNEL:
1972 {
1973 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1974 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1975 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1976 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
1977 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[4]) * 255.0 + 0.5);
1978 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[5]) * 255.0 + 0.5);
1979 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[6]) * 255.0 + 0.5);
1980 }
1981 break;
1982
1983 case BM_8CHANNEL:
1984 {
1985 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
1986 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
1987 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
1988 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
1989 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[4]) * 255.0 + 0.5);
1990 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[5]) * 255.0 + 0.5);
1991 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[6]) * 255.0 + 0.5);
1992 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[7]) * 255.0 + 0.5);
1993 }
1994 break;
1995
1996 case BM_GRAY:
1997 {
1998 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);;
1999 }
2000 break;
2001
2002 //
2003 // 32bpp - 8 bits per channel. The most significant byte is ignored
2004 // for the 3 channel colors.
2005 //
2006
2007 case BM_xRGBQUADS:
2008 case BM_xG3CHQUADS:
2009 {
2010 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2011 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2012 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2013 *lpDestBits++ = 0x00;
2014 }
2015 break;
2016
2017 case BM_xBGRQUADS:
2018 {
2019 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2020 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2021 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2022 *lpDestBits++ = 0x00;
2023 }
2024 break;
2025
2026 case BM_KYMCQUADS:
2027 {
2028 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2029 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2030 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2031 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
2032 }
2033 break;
2034
2035 case BM_CMYKQUADS:
2036 {
2037 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[3]) * 255.0 + 0.5);
2038 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2039 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2040 *lpDestBits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2041 }
2042 break;
2043
2044 //
2045 // 32bpp - 10 bits per channel. The 2 most significant bits are ignored.
2046 //
2047
2048 case BM_10b_Lab:
2049 {
2050 if (pCmm->GetDestSpace()!=icSigDevLabData) {
2051 CIccPCS::Lab4ToLab2(destPixel, destPixel);
2052 }
2053 *((icUInt32Number*)lpDestBits) = ((icUInt32Number)(UnitClip(destPixel[0]) * 1023.0 + 0.5) << 20) +
2054 ((icUInt32Number)(UnitClip(destPixel[1]) * 1023.0 + 0.5) << 10) +
2055 (icUInt32Number)(UnitClip(destPixel[2]) * 1023.0 + 0.5);
2056
2057 lpDestBits += 4;
2058 }
2059 break;
2060
2061 case BM_10b_RGB:
2062 case BM_10b_XYZ:
2063 case BM_10b_Yxy:
2064 case BM_10b_G3CH:
2065 {
2066 *((icUInt32Number*)lpDestBits) = ((icUInt32Number)(UnitClip(destPixel[0]) * 1023.0 + 0.5) << 20) +
2067 ((icUInt32Number)(UnitClip(destPixel[1]) * 1023.0 + 0.5) << 10) +
2068 (icUInt32Number)(UnitClip(destPixel[2]) * 1023.0 + 0.5);
2069
2070 lpDestBits += 4;
2071 }
2072 break;
2073
2074 //
2075 // Packed 16 bits per channel => 16bpp for GRAY and
2076 // 48bpp for the 3 channel colors.
2077 //
2078
2079 case BM_16b_Lab:
2080 {
2081 if (pCmm->GetDestSpace()!=icSigDevLabData) {
2082 CIccPCS::Lab4ToLab2(destPixel, destPixel);
2083 }
2084 icUInt16Number *bits = (icUInt16Number*)lpDestBits;
2085
2086 *bits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2087 *bits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2088 *bits = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2089
2090 lpDestBits += 6;
2091 }
2092 break;
2093
2094 case BM_16b_RGB:
2095 case BM_16b_XYZ:
2096 case BM_16b_Yxy:
2097 case BM_16b_G3CH:
2098 {
2099 icUInt16Number *bits = (icUInt16Number*)lpDestBits;
2100
2101 *bits++ = (icUInt8Number)(UnitClip(destPixel[0]) * 255.0 + 0.5);
2102 *bits++ = (icUInt8Number)(UnitClip(destPixel[1]) * 255.0 + 0.5);
2103 *bits = (icUInt8Number)(UnitClip(destPixel[2]) * 255.0 + 0.5);
2104
2105 lpDestBits += 6;
2106 }
2107 break;
2108
2109 case BM_16b_GRAY:
2110 {
2111 *((icUInt16Number*)lpDestBits) = (icUInt16Number)(UnitClip(destPixel[0]) * 65535.0 + 0.5);
2112
2113 lpDestBits += 2;
2114 }
2115 break;
2116
2117 //
2118 // 16 bpp - 5 bits for Red & Blue, 6 bits for Green
2119 //
2120
2121 case BM_565RGB:
2122 {
2123 *((icUInt16Number*)lpDestBits) = ((icUInt16Number)(UnitClip(destPixel[0]) * 31.0 + 0.5) << 11) +
2124 ((icUInt16Number)(UnitClip(destPixel[1]) * 63.0 + 0.5) << 5) +
2125 (icUInt16Number)(UnitClip(destPixel[2]) * 31.0 + 0.5);
2126
2127 lpDestBits += 2;
2128 }
2129 break;
2130
2131 //
2132 // 32bpp - named color indices (1-based)
2133 //
2134
2135 case BM_NAMED_INDEX:
2136 default:
2137 SetLastError(ERROR_UNSUPPORTED_TYPE);
2138 return FALSE;
2139
2140 }
2141 }
2142
2143 if (lpfnCallback && !lpfnCallback(j, dwHeight, ulCallbackData)) {
2144 SetLastError(ERROR_CANCELLED);
2145 return FALSE;
2146 }
2147
2148 if (!dwInputStride) {
2149 size_t dwAlignedSize = (((lpSrcBits - lpSrcLine) + 3)>>2)<<2;
2150 lpSrcBits = lpSrcLine + dwAlignedSize;
2151 }
2152 else {
2153 lpSrcBits = lpSrcLine + dwInputStride;
2154 }
2155
2156 if (!dwOutputStride) {
2157 size_t dwAlignedSize = (((lpDestBits - lpDestLine) + 3)>>2)<<2;
2158 lpDestBits = lpDestLine + dwAlignedSize;
2159 }
2160 else {
2161 lpSrcBits = lpDestLine + dwOutputStride;
2162 }
2163 }
2164 return TRUE;
2165}
2166
2167
2169 HCMTRANSFORM hcmTransform,
2170 LPBYTE lpSrcBits,
2171 BMFORMAT bmInput,
2172 DWORD dwWidth,
2173 DWORD dwHeight,
2174 DWORD dwInputStride,
2175 LPBYTE lpDestBits,
2176 BMFORMAT bmOutput,
2177 DWORD dwTranslateDirection
2178 )
2179{
2180 if (dwTranslateDirection!=CMS_FORWARD) {
2181 SetLastError(ERROR_BAD_ARGUMENTS);
2182 return FALSE;
2183 }
2184
2185 return CMTranslateRGBsExt(
2186 hcmTransform,
2187 lpSrcBits,
2188 bmInput,
2189 dwWidth,
2190 dwHeight,
2191 dwInputStride,
2192 lpDestBits,
2193 bmOutput,
2194 0,
2195 NULL,
2196 NULL);
2197}
2198
2199
2201 HPROFILE hProfile,
2202 PCOLOR_NAME paColorName,
2203 PDWORD paIndex,
2204 DWORD dwCount
2205 )
2206{
2207 CIccProfile *pProfile = OpenProfile(hProfile);
2208
2209 if (!pProfile) {
2210 SetLastError(ERROR_INVALID_HANDLE);
2211 return false;
2212 }
2213
2214 CIccTagNamedColor2 *pTag = (CIccTagNamedColor2*)pProfile->FindTag(icSigNamedColor2Tag);
2215 if (!pTag) {
2216 delete pProfile;
2217 SetLastError(ERROR_INVALID_HANDLE);
2218 return FALSE;
2219 }
2220
2221 DWORD i;
2222
2223 for (i=0; i<dwCount; i++) {
2224 icInt32Number rv = pTag->FindRootColor(*paColorName);
2225 if (rv>=0)
2226 paIndex[i] = rv;
2227 else {
2228 delete pProfile;
2229
2230 SetLastError(ERROR_NOT_FOUND);
2231 return FALSE;
2232 }
2233
2234 paColorName++;
2235 paIndex++;
2236 }
2237
2238 delete pProfile;
2239
2240 return TRUE;
2241}
2242
2243
2245 HPROFILE hProfile,
2246 PDWORD paIndex,
2247 PCOLOR_NAME paColorName,
2248 DWORD dwCount
2249 )
2250{
2251 CIccProfile *pProfile = OpenProfile(hProfile);
2252
2253 if (!pProfile) {
2254 SetLastError(ERROR_INVALID_HANDLE);
2255 return FALSE;
2256 }
2257
2258 CIccTagNamedColor2 *pTag = (CIccTagNamedColor2*)pProfile->FindTag(icSigNamedColor2Tag);
2259 if (!pTag) {
2260 delete pProfile;
2261
2262 SetLastError(ERROR_INVALID_HANDLE);
2263 return FALSE;
2264 }
2265
2266 DWORD i;
2267
2268 for (i=0; i<dwCount; i++) {
2269
2270 if (paIndex[i] > pTag->GetSize()) {
2271 SetLastError(ERROR_BAD_ARGUMENTS);
2272 return FALSE;
2273 }
2274
2275 SIccNamedColorEntry *pEntry = pTag->GetEntry(paIndex[i]);
2276
2277 memcpy(*paColorName, pEntry->rootName, sizeof(pEntry->rootName));
2278
2279 paColorName++;
2280 paIndex++;
2281 }
2282
2283 delete pProfile;
2284
2285 return TRUE;
2286}
2287
2288
2290 HPROFILE hProfile,
2291 PNAMED_PROFILE_INFO pNamedProfileInfo
2292 )
2293{
2294 CIccProfile *pProfile = OpenProfile(hProfile);
2295
2296 if (!pProfile) {
2297 SetLastError(ERROR_INVALID_HANDLE);
2298 return FALSE;
2299 }
2300
2301 CIccTagNamedColor2 *pTag = (CIccTagNamedColor2*)pProfile->FindTag(icSigNamedColor2Tag);
2302 if (!pTag) {
2303 delete pProfile;
2304 SetLastError(ERROR_INVALID_HANDLE);
2305 return FALSE;
2306 }
2307
2308 pNamedProfileInfo->dwFlags = pTag->GetVendorFlags();
2309 pNamedProfileInfo->dwCount = pTag->GetSize();
2310 pNamedProfileInfo->dwCountDevCoordinates = pTag->GetDeviceCoords();
2311 memcpy(pNamedProfileInfo->szPrefix, pTag->GetPrefix(), sizeof(pNamedProfileInfo->szPrefix));
2312 memcpy(pNamedProfileInfo->szSuffix, pTag->GetSufix(), sizeof(pNamedProfileInfo->szSuffix));
2313
2314 delete pProfile;
2315
2316 return TRUE;
2317}
2318
BOOL WINAPI CMIsProfileValid(HPROFILE hProfile, LPBOOL lpbValid)
HCMTRANSFORM WINAPI CMCreateTransformExtW(LPLOGCOLORSPACEW lpColorSpace, LPBYTE lpDevCharacter, LPBYTE lpTargetDevCharacter, DWORD dwFlags)
BOOL WINAPI CMCheckColorsInGamut(HCMTRANSFORM hcmTransform, RGBTRIPLE *lpaRGBTriple, LPBYTE lpaResult, UINT nCount)
static CIccProfile * OpenProfile(HPROFILE hProfile)
BOOL WINAPI CMTranslateRGB(HCMTRANSFORM hcmTransform, COLORREF ColorRef, LPCOLORREF lpColorRef, DWORD dwFlags)
static BOOL IsValidColorType(COLORTYPE ctSpace, icColorSpaceSignature sigSpace)
static BOOL IsValidBitmapType(BMFORMAT bmType, icColorSpaceSignature sigSpace)
BOOL WINAPI CMDeleteTransform(HCMTRANSFORM hcmTransform)
BOOL WINAPI CMTranslateRGBsExt(HCMTRANSFORM hcmTransform, LPBYTE lpSrcBits, BMFORMAT bmInput, DWORD dwWidth, DWORD dwHeight, DWORD dwInputStride, LPBYTE lpDestBits, BMFORMAT bmOutput, DWORD dwOutputStride, LPBMCALLBACKFN lpfnCallback, ULONG ulCallbackData)
DWORD WINAPI CMGetInfo(DWORD dwInfo)
CIccCmm * g_Transforms[1024]
HCMTRANSFORM WINAPI CMCreateTransform(LPLOGCOLORSPACEA lpColorSpace, LPBYTE lpDevCharacter, LPBYTE lpTargetDevCharacter)
static CIccProfile * GetProfileFromBuf(LPBYTE lpBuf)
HCMTRANSFORM WINAPI CMCreateMultiProfileTransform(LPHPROFILE lpahProfiles, DWORD nProfiles, PDWORD padwIntents, DWORD nIntents, DWORD dwFlags)
HCMTRANSFORM WINAPI CMCreateTransformExt(LPLOGCOLORSPACEA lpColorSpace, LPBYTE lpDevCharacter, LPBYTE lpTargetDevCharacter, DWORD dwFlags)
__inline icFloatNumber UnitClip(icFloatNumber v)
static icRenderingIntent GetRenderingIntent(DWORD nIntent)
HCMTRANSFORM WINAPI CMCreateTransformW(LPLOGCOLORSPACEW lpColorSpace, LPBYTE lpDevCharacter, LPBYTE lpTargetDevCharacter)
#define AVAILABLE_TRANSFORMS
BOOL WINAPI CMConvertColorNameToIndex(HPROFILE hProfile, PCOLOR_NAME paColorName, PDWORD paIndex, DWORD dwCount)
BOOL WINAPI CMTranslateColors(HCMTRANSFORM hcmTransform, LPCOLOR lpaInputColors, DWORD nColors, COLORTYPE ctInput, LPCOLOR lpaOutputColors, COLORTYPE ctOutput)
BOOL WINAPI CMTranslateRGBs(HCMTRANSFORM hcmTransform, LPBYTE lpSrcBits, BMFORMAT bmInput, DWORD dwWidth, DWORD dwHeight, DWORD dwInputStride, LPBYTE lpDestBits, BMFORMAT bmOutput, DWORD dwTranslateDirection)
BOOL WINAPI CMCheckRGBs(HCMTRANSFORM hcmTransform, LPBYTE lpSrcBits, BMFORMAT bmInput, DWORD dwWidth, DWORD dwHeight, DWORD dwStride, LPBYTE lpaResult, PBMCALLBACKFN pfnCallback, ULONG ulCallbackData)
BOOL WINAPI CMGetNamedProfileInfo(HPROFILE hProfile, PNAMED_PROFILE_INFO pNamedProfileInfo)
BOOL WINAPI CMConvertIndexToColorName(HPROFILE hProfile, PDWORD paIndex, PCOLOR_NAME paColorName, DWORD dwCount)
BOOL WINAPI CMCheckColors(HCMTRANSFORM hcmTransform, LPCOLOR lpaInputColors, DWORD nColors, COLORTYPE ctInput, LPBYTE lpaResult)
HPROFILE * LPHPROFILE
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
File: IccCmm.h.
@ icXformLutGamut
Definition IccCmm.h:129
@ icXformLutColor
Definition IccCmm.h:126
@ icInterpLinear
Definition IccCmm.h:114
@ icCmmStatOk
Definition IccCmm.h:92
File: IccDefs.h
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
#define icSigDevLabData
Additional convenience color space signatures to distinguish between device encoding and PCS encoding...
Definition IccDefs.h:91
@ icValidateNonCompliant
Definition IccDefs.h:121
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Name: OpenIccProfile.
icUInt32Number icGetSpaceSamples(icColorSpaceSignature sig)
Definition IccUtil.cpp:1303
unsigned int icUInt32Number
Type: Class.
Definition IccIO.h:217
bool Alloc(icUInt32Number nSize, bool bWrite=false)
Definition IccIO.cpp:665
icUInt8Number * GetData()
Definition IccIO.h:235
Class: CIccTagNamedColor2.
icUInt32Number GetVendorFlags() const
icUInt32Number GetDeviceCoords() const
icUInt32Number GetSize() const
const icChar * GetSufix() const
SIccNamedColorEntry * GetEntry(icUInt32Number index) const
icInt32Number FindRootColor(const icChar *szRootColor) const
Name: CIccTagNamedColor2::FindRootColor.
const icChar * GetPrefix() const
unsigned char icUInt8Number
Number definitions.
#define icUnknownIntent
Convenience Enum Definitions - Not defined in ICC specification.
unsigned short icUInt16Number
long icInt32Number
icColorSpaceSignature
Color Space Signatures.
@ icSigLabData
@ icSig8colorData
@ icSig7colorData
@ icSigXYZData
@ icSig6colorData
@ icSigCmykData
@ icSigRgbData
@ icSigGrayData
@ icSigYxyData
@ icSig5colorData
@ icSigNamedColor2Tag
icRenderingIntent
Rendering Intents, used in the profile header.
@ icPerceptual
@ icRelativeColorimetric
@ icAbsoluteColorimetric
@ icSaturation
#define icSigGamutData
Convenience Enum Definitions - Not defined in ICC specification.
@ icSigDemoIccMAX
#define IDS_DESCRIPTION
Definition resource.h:5
#define IDI_LOGO
Definition resource.h:6
icChar rootName[32]