jdk

Форк
0
677 строк · 19.8 Кб
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-2023 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.0);
224
}
225

226
static
227
void fromFLTto16(void* dst, const void* src)
228
{
229
    cmsFloat32Number n = *(cmsFloat32Number*)src;
230
    *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0);
231
}
232

233
static
234
void fromFLTto16SE(void* dst, const void* src)
235
{
236
    cmsFloat32Number n = *(cmsFloat32Number*)src;
237
    cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0);
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.0);
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.0);
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.0);
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
cmsBool 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 FALSE;
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
       return TRUE;
487
}
488

489

490

491
//  On planar configurations, the distance is the stride added to any non-negative
492
static
493
cmsBool ComputeIncrementsForPlanar(cmsUInt32Number Format,
494
                                cmsUInt32Number BytesPerPlane,
495
                                cmsUInt32Number ComponentStartingOrder[],
496
                                cmsUInt32Number ComponentPointerIncrements[])
497
{
498
       cmsUInt32Number channels[cmsMAXCHANNELS];
499
       cmsUInt32Number extra = T_EXTRA(Format);
500
       cmsUInt32Number nchannels = T_CHANNELS(Format);
501
       cmsUInt32Number total_chans = nchannels + extra;
502
       cmsUInt32Number i;
503
       cmsUInt32Number channelSize = trueBytesSize(Format);
504

505
       // Sanity check
506
       if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
507
           return FALSE;
508

509
       memset(channels, 0, sizeof(channels));
510

511
       // Separation is independent of starting point and only depends on channel size
512
       for (i = 0; i < extra; i++)
513
              ComponentPointerIncrements[i] = channelSize;
514

515
       // Handle do swap
516
       for (i = 0; i < total_chans; i++)
517
       {
518
              if (T_DOSWAP(Format)) {
519
                     channels[i] = total_chans - i - 1;
520
              }
521
              else {
522
                     channels[i] = i;
523
              }
524
       }
525

526
       // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012
527
       if (T_SWAPFIRST(Format) && total_chans > 0) {
528

529
              cmsUInt32Number tmp = channels[0];
530
              for (i = 0; i < total_chans - 1; i++)
531
                     channels[i] = channels[i + 1];
532

533
              channels[total_chans - 1] = tmp;
534
       }
535

536
       // Handle size
537
       for (i = 0; i < total_chans; i++) {
538
              channels[i] *= BytesPerPlane;
539
       }
540

541
       for (i = 0; i < extra; i++)
542
              ComponentStartingOrder[i] = channels[i + nchannels];
543

544
       return TRUE;
545
}
546

547

548

549
// Dispatcher por chunky and planar RGB
550
static
551
cmsBool ComputeComponentIncrements(cmsUInt32Number Format,
552
                                 cmsUInt32Number BytesPerPlane,
553
                                 cmsUInt32Number ComponentStartingOrder[],
554
                                 cmsUInt32Number ComponentPointerIncrements[])
555
{
556
       if (T_PLANAR(Format)) {
557

558
              return ComputeIncrementsForPlanar(Format,  BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
559
       }
560
       else {
561
              return ComputeIncrementsForChunky(Format,  ComponentStartingOrder, ComponentPointerIncrements);
562
       }
563

564
}
565

566
// Handles extra channels copying alpha if requested by the flags
567
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
568
                                               void* out,
569
                                               cmsUInt32Number PixelsPerLine,
570
                                               cmsUInt32Number LineCount,
571
                                               const cmsStride* Stride)
572
{
573
    cmsUInt32Number i, j, k;
574
    cmsUInt32Number nExtra;
575
    cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS];
576
    cmsUInt32Number SourceIncrements[cmsMAXCHANNELS];
577
    cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS];
578
    cmsUInt32Number DestIncrements[cmsMAXCHANNELS];
579

580
    cmsFormatterAlphaFn copyValueFn;
581

582
    // Make sure we need some copy
583
    if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA))
584
        return;
585

586
    // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves.
587
    if (p->InputFormat == p->OutputFormat && in == out)
588
        return;
589

590
    // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time.
591
    nExtra = T_EXTRA(p->InputFormat);
592
    if (nExtra != T_EXTRA(p->OutputFormat))
593
        return;
594

595
    // Anything to do?
596
    if (nExtra == 0)
597
        return;
598

599
    // Compute the increments
600
    if (!ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements))
601
        return;
602
    if (!ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements))
603
        return;
604

605
    // Check for conversions 8, 16, half, float, dbl
606
    copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
607
    if (copyValueFn == NULL)
608
        return;
609

610
    if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly
611

612
        cmsUInt8Number* SourcePtr;
613
        cmsUInt8Number* DestPtr;
614

615
        cmsUInt32Number SourceStrideIncrement = 0;
616
        cmsUInt32Number DestStrideIncrement = 0;
617

618
        // The loop itself
619
        for (i = 0; i < LineCount; i++) {
620

621
            // Prepare pointers for the loop
622
            SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement;
623
            DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement;
624

625
            for (j = 0; j < PixelsPerLine; j++) {
626

627
                copyValueFn(DestPtr, SourcePtr);
628

629
                SourcePtr += SourceIncrements[0];
630
                DestPtr += DestIncrements[0];
631
            }
632

633
            SourceStrideIncrement += Stride->BytesPerLineIn;
634
            DestStrideIncrement += Stride->BytesPerLineOut;
635
        }
636

637
    }
638
    else { // General case with more than one extra channel
639

640
        cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
641
        cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
642

643
        cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
644
        cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
645

646
        memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
647
        memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
648

649
        // The loop itself
650
        for (i = 0; i < LineCount; i++) {
651

652
            // Prepare pointers for the loop
653
            for (j = 0; j < nExtra; j++) {
654

655
                SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j];
656
                DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j];
657
            }
658

659
            for (j = 0; j < PixelsPerLine; j++) {
660

661
                for (k = 0; k < nExtra; k++) {
662

663
                    copyValueFn(DestPtr[k], SourcePtr[k]);
664

665
                    SourcePtr[k] += SourceIncrements[k];
666
                    DestPtr[k] += DestIncrements[k];
667
                }
668
            }
669

670
            for (j = 0; j < nExtra; j++) {
671

672
                SourceStrideIncrements[j] += Stride->BytesPerLineIn;
673
                DestStrideIncrements[j] += Stride->BytesPerLineOut;
674
            }
675
        }
676
    }
677
}
678

679

680

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.