Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/liblcms/cmsalpha.c
41152 views
1
/*
2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation. Oracle designates this
7
* particular file as subject to the "Classpath" exception as provided
8
* by Oracle in the LICENSE file that accompanied this code.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*/
24
25
// This file is available under and governed by the GNU General Public
26
// License version 2 only, as published by the Free Software Foundation.
27
// However, the following notice accompanied the original version of this
28
// file:
29
//
30
//---------------------------------------------------------------------------------
31
//
32
// Little Color Management System
33
// Copyright (c) 1998-2020 Marti Maria Saguer
34
//
35
// Permission is hereby granted, free of charge, to any person obtaining
36
// a copy of this software and associated documentation files (the "Software"),
37
// to deal in the Software without restriction, including without limitation
38
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
39
// and/or sell copies of the Software, and to permit persons to whom the Software
40
// is furnished to do so, subject to the following conditions:
41
//
42
// The above copyright notice and this permission notice shall be included in
43
// all copies or substantial portions of the Software.
44
//
45
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
47
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52
//
53
//---------------------------------------------------------------------------------
54
//
55
56
#include "lcms2_internal.h"
57
58
// Alpha copy ------------------------------------------------------------------------------------------------------------------
59
60
// This macro return words stored as big endian
61
#define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
62
63
64
// Floor to byte, taking care of saturation
65
cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d)
66
{
67
d += 0.5;
68
if (d <= 0) return 0;
69
if (d >= 255.0) return 255;
70
71
return (cmsUInt8Number) _cmsQuickFloorWord(d);
72
}
73
74
75
// Return the size in bytes of a given formatter
76
static
77
cmsUInt32Number trueBytesSize(cmsUInt32Number Format)
78
{
79
cmsUInt32Number fmt_bytes = T_BYTES(Format);
80
81
// For double, the T_BYTES field returns zero
82
if (fmt_bytes == 0)
83
return sizeof(double);
84
85
// Otherwise, it is already correct for all formats
86
return fmt_bytes;
87
}
88
89
90
// Several format converters
91
92
typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src);
93
94
95
// From 8
96
97
static
98
void copy8(void* dst, const void* src)
99
{
100
memmove(dst, src, 1);
101
}
102
103
static
104
void from8to16(void* dst, const void* src)
105
{
106
cmsUInt8Number n = *(cmsUInt8Number*)src;
107
*(cmsUInt16Number*) dst = (cmsUInt16Number) FROM_8_TO_16(n);
108
}
109
110
static
111
void from8to16SE(void* dst, const void* src)
112
{
113
cmsUInt8Number n = *(cmsUInt8Number*)src;
114
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(FROM_8_TO_16(n));
115
}
116
117
static
118
void from8toFLT(void* dst, const void* src)
119
{
120
*(cmsFloat32Number*)dst = (cmsFloat32Number) (*(cmsUInt8Number*)src) / 255.0f;
121
}
122
123
static
124
void from8toDBL(void* dst, const void* src)
125
{
126
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt8Number*)src) / 255.0;
127
}
128
129
static
130
void from8toHLF(void* dst, const void* src)
131
{
132
#ifndef CMS_NO_HALF_SUPPORT
133
cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
134
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
135
#else
136
cmsUNUSED_PARAMETER(dst);
137
cmsUNUSED_PARAMETER(src);
138
#endif
139
}
140
141
// From 16
142
143
static
144
void from16to8(void* dst, const void* src)
145
{
146
cmsUInt16Number n = *(cmsUInt16Number*)src;
147
*(cmsUInt8Number*) dst = FROM_16_TO_8(n);
148
}
149
150
static
151
void from16SEto8(void* dst, const void* src)
152
{
153
cmsUInt16Number n = *(cmsUInt16Number*)src;
154
*(cmsUInt8Number*)dst = FROM_16_TO_8(CHANGE_ENDIAN(n));
155
}
156
157
static
158
void copy16(void* dst, const void* src)
159
{
160
memmove(dst, src, 2);
161
}
162
163
static
164
void from16to16(void* dst, const void* src)
165
{
166
cmsUInt16Number n = *(cmsUInt16Number*)src;
167
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(n);
168
}
169
170
static
171
void from16toFLT(void* dst, const void* src)
172
{
173
*(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
174
}
175
176
static
177
void from16SEtoFLT(void* dst, const void* src)
178
{
179
*(cmsFloat32Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
180
}
181
182
static
183
void from16toDBL(void* dst, const void* src)
184
{
185
*(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt16Number*)src) / 65535.0;
186
}
187
188
static
189
void from16SEtoDBL(void* dst, const void* src)
190
{
191
*(cmsFloat64Number*)dst = (cmsFloat64Number) (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0;
192
}
193
194
static
195
void from16toHLF(void* dst, const void* src)
196
{
197
#ifndef CMS_NO_HALF_SUPPORT
198
cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
199
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
200
#else
201
cmsUNUSED_PARAMETER(dst);
202
cmsUNUSED_PARAMETER(src);
203
#endif
204
}
205
206
static
207
void from16SEtoHLF(void* dst, const void* src)
208
{
209
#ifndef CMS_NO_HALF_SUPPORT
210
cmsFloat32Number n = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
211
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
212
#else
213
cmsUNUSED_PARAMETER(dst);
214
cmsUNUSED_PARAMETER(src);
215
#endif
216
}
217
// From Float
218
219
static
220
void fromFLTto8(void* dst, const void* src)
221
{
222
cmsFloat32Number n = *(cmsFloat32Number*)src;
223
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
224
}
225
226
static
227
void fromFLTto16(void* dst, const void* src)
228
{
229
cmsFloat32Number n = *(cmsFloat32Number*)src;
230
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
231
}
232
233
static
234
void fromFLTto16SE(void* dst, const void* src)
235
{
236
cmsFloat32Number n = *(cmsFloat32Number*)src;
237
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
238
239
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
240
}
241
242
static
243
void copy32(void* dst, const void* src)
244
{
245
memmove(dst, src, sizeof(cmsFloat32Number));
246
}
247
248
static
249
void fromFLTtoDBL(void* dst, const void* src)
250
{
251
cmsFloat32Number n = *(cmsFloat32Number*)src;
252
*(cmsFloat64Number*)dst = (cmsFloat64Number)n;
253
}
254
255
static
256
void fromFLTtoHLF(void* dst, const void* src)
257
{
258
#ifndef CMS_NO_HALF_SUPPORT
259
cmsFloat32Number n = *(cmsFloat32Number*)src;
260
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
261
#else
262
cmsUNUSED_PARAMETER(dst);
263
cmsUNUSED_PARAMETER(src);
264
#endif
265
}
266
267
268
// From HALF
269
270
static
271
void fromHLFto8(void* dst, const void* src)
272
{
273
#ifndef CMS_NO_HALF_SUPPORT
274
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
275
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
276
#else
277
cmsUNUSED_PARAMETER(dst);
278
cmsUNUSED_PARAMETER(src);
279
#endif
280
281
}
282
283
static
284
void fromHLFto16(void* dst, const void* src)
285
{
286
#ifndef CMS_NO_HALF_SUPPORT
287
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
288
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
289
#else
290
cmsUNUSED_PARAMETER(dst);
291
cmsUNUSED_PARAMETER(src);
292
#endif
293
}
294
295
static
296
void fromHLFto16SE(void* dst, const void* src)
297
{
298
#ifndef CMS_NO_HALF_SUPPORT
299
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
300
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
301
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
302
#else
303
cmsUNUSED_PARAMETER(dst);
304
cmsUNUSED_PARAMETER(src);
305
#endif
306
}
307
308
static
309
void fromHLFtoFLT(void* dst, const void* src)
310
{
311
#ifndef CMS_NO_HALF_SUPPORT
312
*(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
313
#else
314
cmsUNUSED_PARAMETER(dst);
315
cmsUNUSED_PARAMETER(src);
316
#endif
317
}
318
319
static
320
void fromHLFtoDBL(void* dst, const void* src)
321
{
322
#ifndef CMS_NO_HALF_SUPPORT
323
*(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
324
#else
325
cmsUNUSED_PARAMETER(dst);
326
cmsUNUSED_PARAMETER(src);
327
#endif
328
}
329
330
// From double
331
static
332
void fromDBLto8(void* dst, const void* src)
333
{
334
cmsFloat64Number n = *(cmsFloat64Number*)src;
335
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
336
}
337
338
static
339
void fromDBLto16(void* dst, const void* src)
340
{
341
cmsFloat64Number n = *(cmsFloat64Number*)src;
342
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
343
}
344
345
static
346
void fromDBLto16SE(void* dst, const void* src)
347
{
348
cmsFloat64Number n = *(cmsFloat64Number*)src;
349
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
350
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
351
}
352
353
static
354
void fromDBLtoFLT(void* dst, const void* src)
355
{
356
cmsFloat64Number n = *(cmsFloat64Number*)src;
357
*(cmsFloat32Number*)dst = (cmsFloat32Number) n;
358
}
359
360
static
361
void fromDBLtoHLF(void* dst, const void* src)
362
{
363
#ifndef CMS_NO_HALF_SUPPORT
364
cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
365
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
366
#else
367
cmsUNUSED_PARAMETER(dst);
368
cmsUNUSED_PARAMETER(src);
369
#endif
370
}
371
372
static
373
void copy64(void* dst, const void* src)
374
{
375
memmove(dst, src, sizeof(cmsFloat64Number));
376
}
377
378
379
// Returns the position (x or y) of the formatter in the table of functions
380
static
381
int FormatterPos(cmsUInt32Number frm)
382
{
383
cmsUInt32Number b = T_BYTES(frm);
384
385
if (b == 0 && T_FLOAT(frm))
386
return 5; // DBL
387
#ifndef CMS_NO_HALF_SUPPORT
388
if (b == 2 && T_FLOAT(frm))
389
return 3; // HLF
390
#endif
391
if (b == 4 && T_FLOAT(frm))
392
return 4; // FLT
393
if (b == 2 && !T_FLOAT(frm))
394
{
395
if (T_ENDIAN16(frm))
396
return 2; // 16SE
397
else
398
return 1; // 16
399
}
400
if (b == 1 && !T_FLOAT(frm))
401
return 0; // 8
402
return -1; // not recognized
403
}
404
405
// Obtains an alpha-to-alpha function formatter
406
static
407
cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out)
408
{
409
static cmsFormatterAlphaFn FormattersAlpha[6][6] = {
410
411
/* from 8 */ { copy8, from8to16, from8to16SE, from8toHLF, from8toFLT, from8toDBL },
412
/* from 16*/ { from16to8, copy16, from16to16, from16toHLF, from16toFLT, from16toDBL },
413
/* from 16SE*/{ from16SEto8, from16to16, copy16, from16SEtoHLF,from16SEtoFLT, from16SEtoDBL },
414
/* from HLF*/ { fromHLFto8, fromHLFto16, fromHLFto16SE, copy16, fromHLFtoFLT, fromHLFtoDBL },
415
/* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTto16SE, fromFLTtoHLF, copy32, fromFLTtoDBL },
416
/* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLto16SE, fromDBLtoHLF, fromDBLtoFLT, copy64 }};
417
418
int in_n = FormatterPos(in);
419
int out_n = FormatterPos(out);
420
421
if (in_n < 0 || out_n < 0 || in_n > 5 || out_n > 5) {
422
423
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width");
424
return NULL;
425
}
426
427
return FormattersAlpha[in_n][out_n];
428
}
429
430
431
432
// This function computes the distance from each component to the next one in bytes.
433
static
434
void ComputeIncrementsForChunky(cmsUInt32Number Format,
435
cmsUInt32Number ComponentStartingOrder[],
436
cmsUInt32Number ComponentPointerIncrements[])
437
{
438
cmsUInt32Number channels[cmsMAXCHANNELS];
439
cmsUInt32Number extra = T_EXTRA(Format);
440
cmsUInt32Number nchannels = T_CHANNELS(Format);
441
cmsUInt32Number total_chans = nchannels + extra;
442
cmsUInt32Number i;
443
cmsUInt32Number channelSize = trueBytesSize(Format);
444
cmsUInt32Number pixelSize = channelSize * total_chans;
445
446
// Sanity check
447
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
448
return;
449
450
memset(channels, 0, sizeof(channels));
451
452
// Separation is independent of starting point and only depends on channel size
453
for (i = 0; i < extra; i++)
454
ComponentPointerIncrements[i] = pixelSize;
455
456
// Handle do swap
457
for (i = 0; i < total_chans; i++)
458
{
459
if (T_DOSWAP(Format)) {
460
channels[i] = total_chans - i - 1;
461
}
462
else {
463
channels[i] = i;
464
}
465
}
466
467
// Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012
468
if (T_SWAPFIRST(Format) && total_chans > 1) {
469
470
cmsUInt32Number tmp = channels[0];
471
for (i = 0; i < total_chans-1; i++)
472
channels[i] = channels[i + 1];
473
474
channels[total_chans - 1] = tmp;
475
}
476
477
// Handle size
478
if (channelSize > 1)
479
for (i = 0; i < total_chans; i++) {
480
channels[i] *= channelSize;
481
}
482
483
for (i = 0; i < extra; i++)
484
ComponentStartingOrder[i] = channels[i + nchannels];
485
}
486
487
488
489
// On planar configurations, the distance is the stride added to any non-negative
490
static
491
void ComputeIncrementsForPlanar(cmsUInt32Number Format,
492
cmsUInt32Number BytesPerPlane,
493
cmsUInt32Number ComponentStartingOrder[],
494
cmsUInt32Number ComponentPointerIncrements[])
495
{
496
cmsUInt32Number channels[cmsMAXCHANNELS];
497
cmsUInt32Number extra = T_EXTRA(Format);
498
cmsUInt32Number nchannels = T_CHANNELS(Format);
499
cmsUInt32Number total_chans = nchannels + extra;
500
cmsUInt32Number i;
501
cmsUInt32Number channelSize = trueBytesSize(Format);
502
503
// Sanity check
504
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
505
return;
506
507
memset(channels, 0, sizeof(channels));
508
509
// Separation is independent of starting point and only depends on channel size
510
for (i = 0; i < extra; i++)
511
ComponentPointerIncrements[i] = channelSize;
512
513
// Handle do swap
514
for (i = 0; i < total_chans; i++)
515
{
516
if (T_DOSWAP(Format)) {
517
channels[i] = total_chans - i - 1;
518
}
519
else {
520
channels[i] = i;
521
}
522
}
523
524
// Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012
525
if (T_SWAPFIRST(Format) && total_chans > 0) {
526
527
cmsUInt32Number tmp = channels[0];
528
for (i = 0; i < total_chans - 1; i++)
529
channels[i] = channels[i + 1];
530
531
channels[total_chans - 1] = tmp;
532
}
533
534
// Handle size
535
for (i = 0; i < total_chans; i++) {
536
channels[i] *= BytesPerPlane;
537
}
538
539
for (i = 0; i < extra; i++)
540
ComponentStartingOrder[i] = channels[i + nchannels];
541
}
542
543
544
545
// Dispatcher por chunky and planar RGB
546
static
547
void ComputeComponentIncrements(cmsUInt32Number Format,
548
cmsUInt32Number BytesPerPlane,
549
cmsUInt32Number ComponentStartingOrder[],
550
cmsUInt32Number ComponentPointerIncrements[])
551
{
552
if (T_PLANAR(Format)) {
553
554
ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
555
}
556
else {
557
ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements);
558
}
559
560
}
561
562
563
564
// Handles extra channels copying alpha if requested by the flags
565
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
566
void* out,
567
cmsUInt32Number PixelsPerLine,
568
cmsUInt32Number LineCount,
569
const cmsStride* Stride)
570
{
571
cmsUInt32Number i, j, k;
572
cmsUInt32Number nExtra;
573
cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS];
574
cmsUInt32Number SourceIncrements[cmsMAXCHANNELS];
575
cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS];
576
cmsUInt32Number DestIncrements[cmsMAXCHANNELS];
577
578
cmsFormatterAlphaFn copyValueFn;
579
580
// Make sure we need some copy
581
if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA))
582
return;
583
584
// Exit early if in-place color-management is occurring - no need to copy extra channels to themselves.
585
if (p->InputFormat == p->OutputFormat && in == out)
586
return;
587
588
// Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time.
589
nExtra = T_EXTRA(p->InputFormat);
590
if (nExtra != T_EXTRA(p->OutputFormat))
591
return;
592
593
// Anything to do?
594
if (nExtra == 0)
595
return;
596
597
// Compute the increments
598
ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
599
ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
600
601
// Check for conversions 8, 16, half, float, dbl
602
copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
603
if (copyValueFn == NULL)
604
return;
605
606
if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly
607
608
cmsUInt8Number* SourcePtr;
609
cmsUInt8Number* DestPtr;
610
611
cmsUInt32Number SourceStrideIncrement = 0;
612
cmsUInt32Number DestStrideIncrement = 0;
613
614
// The loop itself
615
for (i = 0; i < LineCount; i++) {
616
617
// Prepare pointers for the loop
618
SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement;
619
DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement;
620
621
for (j = 0; j < PixelsPerLine; j++) {
622
623
copyValueFn(DestPtr, SourcePtr);
624
625
SourcePtr += SourceIncrements[0];
626
DestPtr += DestIncrements[0];
627
}
628
629
SourceStrideIncrement += Stride->BytesPerLineIn;
630
DestStrideIncrement += Stride->BytesPerLineOut;
631
}
632
633
}
634
else { // General case with more than one extra channel
635
636
cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
637
cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
638
639
cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
640
cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
641
642
memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
643
memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
644
645
// The loop itself
646
for (i = 0; i < LineCount; i++) {
647
648
// Prepare pointers for the loop
649
for (j = 0; j < nExtra; j++) {
650
651
SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j];
652
DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j];
653
}
654
655
for (j = 0; j < PixelsPerLine; j++) {
656
657
for (k = 0; k < nExtra; k++) {
658
659
copyValueFn(DestPtr[k], SourcePtr[k]);
660
661
SourcePtr[k] += SourceIncrements[k];
662
DestPtr[k] += DestIncrements[k];
663
}
664
}
665
666
for (j = 0; j < nExtra; j++) {
667
668
SourceStrideIncrements[j] += Stride->BytesPerLineIn;
669
DestStrideIncrements[j] += Stride->BytesPerLineOut;
670
}
671
}
672
}
673
}
674
675
676
677