Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/JAVA/Openjdk/src/java.desktop/share/native/liblcms/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 126 kB image not shown  

Quelle  cmspack.c   Sprache: C

 
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


// This file is available under and governed by the GNU General Public
// License version 2 only, as published by the Free Software Foundation.
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
//  Little Color Management System
//  Copyright (c) 1998-2022 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//

#include "lcms2_internal.h"

// This module handles all formats supported by lcms. There are two flavors, 16 bits and
// floating point. Floating point is supported only in a subset, those formats holding
// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component
// as special case)

// ---------------------------------------------------------------------------


// This macro return words stored as big endian
#define CHANGE_ENDIAN(w)    (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))

// These macros handles reversing (negative)
#define REVERSE_FLAVOR_8(x)     ((cmsUInt8Number) (0xff-(x)))
#define REVERSE_FLAVOR_16(x)    ((cmsUInt16Number)(0xffff-(x)))

// * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256
cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x)
{
    int a = (x << 8 | x) >> 8;  // * 257 / 256
    if ( a > 0xffff) return 0xffff;
    return (cmsUInt16Number) a;
}

// * 0xf00 / 0xffff = * 256 / 257
cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)
{
    return (cmsUInt16Number) (((x << 8) + 0x80) / 257);
}


typedef struct {
    cmsUInt32Number Type;
    cmsUInt32Number Mask;
    cmsFormatter16  Frm;

} cmsFormatters16;

typedef struct {
    cmsUInt32Number    Type;
    cmsUInt32Number    Mask;
    cmsFormatterFloat  Frm;

} cmsFormattersFloat;


#define ANYSPACE        COLORSPACE_SH(31)
#define ANYCHANNELS     CHANNELS_SH(15)
#define ANYEXTRA        EXTRA_SH(7)
#define ANYPLANAR       PLANAR_SH(1)
#define ANYENDIAN       ENDIAN16_SH(1)
#define ANYSWAP         DOSWAP_SH(1)
#define ANYSWAPFIRST    SWAPFIRST_SH(1)
#define ANYFLAVOR       FLAVOR_SH(1)
#define ANYPREMUL       PREMUL_SH(1)


// Suppress waning about info never being used

#ifdef _MSC_VER
#pragma warning(disable : 4100)
#endif

// Unpacking routines (16 bits) ----------------------------------------------------------------------------------------


// Does almost everything but is slow
static
cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
                                  CMSREGISTER cmsUInt16Number wIn[],
                                  CMSREGISTER cmsUInt8Number* accum,
                                  CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
    cmsUInt32Number Premul     = T_PREMUL(info->InputFormat);

    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number v;
    cmsUInt32Number i;
    cmsUInt32Number alpha_factor = 1;

    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));

        accum += Extra;
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan]));
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        v = FROM_8_TO_16(*accum);
        v = Reverse ? REVERSE_FLAVOR_16(v) : v;

        if (Premul && alpha_factor > 0)
        {
            v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
            if (v > 0xffff) v = 0xffff;
        }

        wIn[index] = (cmsUInt16Number) v;
        accum++;
    }

    if (!ExtraFirst) {
        accum += Extra;
    }

    if (Extra == 0 && SwapFirst) {
        cmsUInt16Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
        wIn[nChan-1] = tmp;
    }

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);

}


// Extra channels are just ignored because come in the next planes
static
cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
                                  CMSREGISTER cmsUInt16Number wIn[],
                                  CMSREGISTER cmsUInt8Number* accum,
                                  CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan     = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap    = T_DOSWAP(info ->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
    cmsUInt32Number Reverse   = T_FLAVOR(info ->InputFormat);
    cmsUInt32Number i;
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
    cmsUInt8Number* Init = accum;
    cmsUInt32Number alpha_factor = 1;

    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));


        accum += Extra * Stride;
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt32Number v = FROM_8_TO_16(*accum);

        v = Reverse ? REVERSE_FLAVOR_16(v) : v;

        if (Premul && alpha_factor > 0)
        {
            v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
            if (v > 0xffff) v = 0xffff;
        }

        wIn[index] = (cmsUInt16Number) v;
        accum += Stride;
    }

    return (Init + 1);
}


// Special cases, provided for performance
static
cmsUInt8Number* Unroll4Bytes(CMSREGISTER _cmsTRANSFORM* info,
                             CMSREGISTER cmsUInt16Number wIn[],
                             CMSREGISTER cmsUInt8Number* accum,
                             CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
    wIn[3] = FROM_8_TO_16(*accum); accum++; // K

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
    wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
    wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
    wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                      CMSREGISTER cmsUInt16Number wIn[],
                                      CMSREGISTER cmsUInt8Number* accum,
                                      CMSREGISTER cmsUInt32Number Stride)
{
    wIn[3] = FROM_8_TO_16(*accum); accum++; // K
    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// KYMC
static
cmsUInt8Number* Unroll4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[3] = FROM_8_TO_16(*accum); accum++;  // K
    wIn[2] = FROM_8_TO_16(*accum); accum++;  // Y
    wIn[1] = FROM_8_TO_16(*accum); accum++;  // M
    wIn[0] = FROM_8_TO_16(*accum); accum++;  // C

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                          CMSREGISTER cmsUInt16Number wIn[],
                                          CMSREGISTER cmsUInt8Number* accum,
                                          CMSREGISTER cmsUInt32Number Stride)
{
    wIn[2] = FROM_8_TO_16(*accum); accum++;  // K
    wIn[1] = FROM_8_TO_16(*accum); accum++;  // Y
    wIn[0] = FROM_8_TO_16(*accum); accum++;  // M
    wIn[3] = FROM_8_TO_16(*accum); accum++;  // C

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3Bytes(CMSREGISTER _cmsTRANSFORM* info,
                             CMSREGISTER cmsUInt16Number wIn[],
                             CMSREGISTER cmsUInt8Number* accum,
                             CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3BytesSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
                                      CMSREGISTER cmsUInt16Number wIn[],
                                      CMSREGISTER cmsUInt8Number* accum,
                                      CMSREGISTER cmsUInt32Number Stride)
{
    accum++; // A
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                              CMSREGISTER cmsUInt16Number wIn[],
                                              CMSREGISTER cmsUInt8Number* accum,
                                              CMSREGISTER cmsUInt32Number Stride)
{
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
    accum++; // A

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3BytesSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                           CMSREGISTER cmsUInt16Number wIn[],
                                           CMSREGISTER cmsUInt8Number* accum,
                                           CMSREGISTER cmsUInt32Number Stride)
{
    accum++; // A
    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
    wIn[2] = FROM_8_TO_16(*accum); accum++; // B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


// BRG
static
cmsUInt8Number* Unroll3BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* UnrollLabV2_8(CMSREGISTER _cmsTRANSFORM* info,
                              CMSREGISTER cmsUInt16Number wIn[],
                              CMSREGISTER cmsUInt8Number* accum,
                              CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* UnrollALabV2_8(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wIn[],
                               CMSREGISTER cmsUInt8Number* accum,
                               CMSREGISTER cmsUInt32Number Stride)
{
    accum++;  // A
    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* UnrollLabV2_16(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wIn[],
                               CMSREGISTER cmsUInt8Number* accum,
                               CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
    wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
    wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// for duplex
static
cmsUInt8Number* Unroll2Bytes(CMSREGISTER _cmsTRANSFORM* info,
                                     CMSREGISTER cmsUInt16Number wIn[],
                                     CMSREGISTER cmsUInt8Number* accum,
                                     CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = FROM_8_TO_16(*accum); accum++;     // ch1
    wIn[1] = FROM_8_TO_16(*accum); accum++;     // ch2

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}




// Monochrome duplicates L into RGB for null-transforms
static
cmsUInt8Number* Unroll1Byte(CMSREGISTER _cmsTRANSFORM* info,
                            CMSREGISTER cmsUInt16Number wIn[],
                            CMSREGISTER cmsUInt8Number* accum,
                            CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* Unroll1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
    accum += 1;

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll1ByteSkip2(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
    accum += 2;

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll1ByteReversed(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++;     // L

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* UnrollAnyWords(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wIn[],
                               CMSREGISTER cmsUInt8Number* accum,
                               CMSREGISTER cmsUInt32Number Stride)
{
   cmsUInt32Number nChan       = T_CHANNELS(info -> InputFormat);
   cmsUInt32Number SwapEndian  = T_ENDIAN16(info -> InputFormat);
   cmsUInt32Number DoSwap      = T_DOSWAP(info ->InputFormat);
   cmsUInt32Number Reverse     = T_FLAVOR(info ->InputFormat);
   cmsUInt32Number SwapFirst   = T_SWAPFIRST(info -> InputFormat);
   cmsUInt32Number Extra       = T_EXTRA(info -> InputFormat);
   cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
   cmsUInt32Number i;

    if (ExtraFirst) {
        accum += Extra * sizeof(cmsUInt16Number);
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt16Number v = *(cmsUInt16Number*) accum;

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;

        accum += sizeof(cmsUInt16Number);
    }

    if (!ExtraFirst) {
        accum += Extra * sizeof(cmsUInt16Number);
    }

    if (Extra == 0 && SwapFirst) {

        cmsUInt16Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
        wIn[nChan-1] = tmp;
    }

    return accum;

    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* UnrollAnyWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
                                     CMSREGISTER cmsUInt16Number wIn[],
                                     CMSREGISTER cmsUInt8Number* accum,
                                     CMSREGISTER cmsUInt32Number Stride)
{
   cmsUInt32Number nChan       = T_CHANNELS(info -> InputFormat);
   cmsUInt32Number SwapEndian  = T_ENDIAN16(info -> InputFormat);
   cmsUInt32Number DoSwap      = T_DOSWAP(info ->InputFormat);
   cmsUInt32Number Reverse     = T_FLAVOR(info ->InputFormat);
   cmsUInt32Number SwapFirst   = T_SWAPFIRST(info -> InputFormat);
   cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
   cmsUInt32Number i;

   cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
   cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));

    if (ExtraFirst) {
        accum += sizeof(cmsUInt16Number);
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt32Number v = *(cmsUInt16Number*) accum;

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        if (alpha_factor > 0) {

            v = (v << 16) / alpha_factor;
            if (v > 0xffff) v = 0xffff;
        }

        wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);

        accum += sizeof(cmsUInt16Number);
    }

    if (!ExtraFirst) {
        accum += sizeof(cmsUInt16Number);
    }

    return accum;

    cmsUNUSED_PARAMETER(Stride);
}



static
cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
                                  CMSREGISTER cmsUInt16Number wIn[],
                                  CMSREGISTER cmsUInt8Number* accum,
                                  CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
    cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
    cmsUInt32Number i;
    cmsUInt8Number* Init = accum;

    if (DoSwap) {
        accum += T_EXTRA(info -> InputFormat) * Stride;
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt16Number v = *(cmsUInt16Number*) accum;

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;

        accum +=  Stride;
    }

    return (Init + sizeof(cmsUInt16Number));
}

static
cmsUInt8Number* UnrollPlanarWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
                                        CMSREGISTER cmsUInt16Number wIn[],
                                        CMSREGISTER cmsUInt8Number* accum,
                                        CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
    cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
    cmsUInt32Number i;
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt8Number* Init = accum;

    cmsUInt16Number  alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
    cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));

    if (ExtraFirst) {
        accum += Stride;
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt32Number v = (cmsUInt32Number) *(cmsUInt16Number*) accum;

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        if (alpha_factor > 0) {

            v = (v << 16) / alpha_factor;
            if (v > 0xffff) v = 0xffff;
        }

        wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);

        accum +=  Stride;
    }

    return (Init + sizeof(cmsUInt16Number));
}

static
cmsUInt8Number* Unroll4Words(CMSREGISTER _cmsTRANSFORM* info,
                             CMSREGISTER cmsUInt16Number wIn[],
                             CMSREGISTER cmsUInt8Number* accum,
                             CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4WordsReverse(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C
    wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M
    wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y
    wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4WordsSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                      CMSREGISTER cmsUInt16Number wIn[],
                                      CMSREGISTER cmsUInt8Number* accum,
                                      CMSREGISTER cmsUInt32Number Stride)
{
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// KYMC
static
cmsUInt8Number* Unroll4WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll4WordsSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                          CMSREGISTER cmsUInt16Number wIn[],
                                          CMSREGISTER cmsUInt8Number* accum,
                                          CMSREGISTER cmsUInt32Number Stride)
{
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M
    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3Words(CMSREGISTER _cmsTRANSFORM* info,
                             CMSREGISTER cmsUInt16Number wIn[],
                             CMSREGISTER cmsUInt8Number* accum,
                             CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3WordsSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,
                                      CMSREGISTER cmsUInt16Number wIn[],
                                      CMSREGISTER cmsUInt8Number* accum,
                                      CMSREGISTER cmsUInt32Number Stride)
{
    accum += 2; // A
    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll3WordsSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                           CMSREGISTER cmsUInt16Number wIn[],
                                           CMSREGISTER cmsUInt8Number* accum,
                                           CMSREGISTER cmsUInt32Number Stride)
{
    accum += 2; // A
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll1Word(CMSREGISTER _cmsTRANSFORM* info,
                            CMSREGISTER cmsUInt16Number wIn[],
                            CMSREGISTER cmsUInt8Number* accum,
                            CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;   // L

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll1WordReversed(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll1WordSkip3(CMSREGISTER _cmsTRANSFORM* info,
                                 CMSREGISTER cmsUInt16Number wIn[],
                                 CMSREGISTER cmsUInt8Number* accum,
                                 CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;

    accum += 8;

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Unroll2Words(CMSREGISTER _cmsTRANSFORM* info,
                                     CMSREGISTER cmsUInt16Number wIn[],
                                     CMSREGISTER cmsUInt8Number* accum,
                                     CMSREGISTER cmsUInt32Number Stride)
{
    wIn[0] = *(cmsUInt16Number*) accum; accum += 2;    // ch1
    wIn[1] = *(cmsUInt16Number*) accum; accum += 2;    // ch2

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


// This is a conversion of Lab double to 16 bits
static
cmsUInt8Number* UnrollLabDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number  Stride)
{
    if (T_PLANAR(info -> InputFormat)) {

        cmsCIELab Lab;
        cmsUInt8Number* pos_L;
        cmsUInt8Number* pos_a;
        cmsUInt8Number* pos_b;

        pos_L = accum;
        pos_a = accum + Stride;
        pos_b = accum + Stride * 2;

        Lab.L = *(cmsFloat64Number*) pos_L;
        Lab.a = *(cmsFloat64Number*) pos_a;
        Lab.b = *(cmsFloat64Number*) pos_b;

        cmsFloat2LabEncoded(wIn, &Lab);
        return accum + sizeof(cmsFloat64Number);
    }
    else {

        cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum);
        accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);
        return accum;
    }
}


// This is a conversion of Lab float to 16 bits
static
cmsUInt8Number* UnrollLabFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number  Stride)
{
    cmsCIELab Lab;

    if (T_PLANAR(info -> InputFormat)) {

        cmsUInt8Number* pos_L;
        cmsUInt8Number* pos_a;
        cmsUInt8Number* pos_b;

        pos_L = accum;
        pos_a = accum + Stride;
        pos_b = accum + Stride * 2;

        Lab.L = *(cmsFloat32Number*)pos_L;
        Lab.a = *(cmsFloat32Number*)pos_a;
        Lab.b = *(cmsFloat32Number*)pos_b;

        cmsFloat2LabEncoded(wIn, &Lab);
        return accum + sizeof(cmsFloat32Number);
    }
    else {

        Lab.L = ((cmsFloat32Number*) accum)[0];
        Lab.a = ((cmsFloat32Number*) accum)[1];
        Lab.b = ((cmsFloat32Number*) accum)[2];

        cmsFloat2LabEncoded(wIn, &Lab);
        accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
        return accum;
    }
}

// This is a conversion of XYZ double to 16 bits
static
cmsUInt8Number* UnrollXYZDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wIn[],
                                    CMSREGISTER cmsUInt8Number* accum,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    if (T_PLANAR(info -> InputFormat)) {

        cmsCIEXYZ XYZ;
        cmsUInt8Number* pos_X;
        cmsUInt8Number* pos_Y;
        cmsUInt8Number* pos_Z;

        pos_X = accum;
        pos_Y = accum + Stride;
        pos_Z = accum + Stride * 2;

        XYZ.X = *(cmsFloat64Number*)pos_X;
        XYZ.Y = *(cmsFloat64Number*)pos_Y;
        XYZ.Z = *(cmsFloat64Number*)pos_Z;

        cmsFloat2XYZEncoded(wIn, &XYZ);

        return accum + sizeof(cmsFloat64Number);

    }

    else {
        cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum);
        accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);

        return accum;
    }
}

// This is a conversion of XYZ float to 16 bits
static
cmsUInt8Number* UnrollXYZFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
                                   CMSREGISTER cmsUInt16Number wIn[],
                                   CMSREGISTER cmsUInt8Number* accum,
                                   CMSREGISTER cmsUInt32Number Stride)
{
    if (T_PLANAR(info -> InputFormat)) {

        cmsCIEXYZ XYZ;
        cmsUInt8Number* pos_X;
        cmsUInt8Number* pos_Y;
        cmsUInt8Number* pos_Z;

        pos_X = accum;
        pos_Y = accum + Stride;
        pos_Z = accum + Stride * 2;

        XYZ.X = *(cmsFloat32Number*)pos_X;
        XYZ.Y = *(cmsFloat32Number*)pos_Y;
        XYZ.Z = *(cmsFloat32Number*)pos_Z;

        cmsFloat2XYZEncoded(wIn, &XYZ);

        return accum + sizeof(cmsFloat32Number);

    }

    else {
        cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
        cmsCIEXYZ XYZ;

        XYZ.X = Pt[0];
        XYZ.Y = Pt[1];
        XYZ.Z = Pt[2];
        cmsFloat2XYZEncoded(wIn, &XYZ);

        accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number);

        return accum;
    }
}

// Check if space is marked as ink
cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
{
    switch (T_COLORSPACE(Type)) {

     case PT_CMY:
     case PT_CMYK:
     case PT_MCH5:
     case PT_MCH6:
     case PT_MCH7:
     case PT_MCH8:
     case PT_MCH9:
     case PT_MCH10:
     case PT_MCH11:
     case PT_MCH12:
     case PT_MCH13:
     case PT_MCH14:
     case PT_MCH15: return TRUE;

     defaultreturn FALSE;
    }
}

// Return the size in bytes of a given formatter
static
cmsUInt32Number PixelSize(cmsUInt32Number Format)
{
    cmsUInt32Number fmt_bytes = T_BYTES(Format);

    // For double, the T_BYTES field is zero
    if (fmt_bytes == 0)
        return sizeof(cmsUInt64Number);

    // Otherwise, it is already correct for all formats
    return fmt_bytes;
}

// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
static
cmsUInt8Number* UnrollDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wIn[],
                                CMSREGISTER cmsUInt8Number* accum,
                                CMSREGISTER cmsUInt32Number Stride)
{

    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
    cmsFloat64Number v;
    cmsUInt16Number  vi;
    cmsUInt32Number i, start = 0;
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;


    Stride /= PixelSize(info->InputFormat);

    if (ExtraFirst)
            start = Extra;

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
        else
            v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start];

        vi = _cmsQuickSaturateWord(v * maximum);

        if (Reverse)
            vi = REVERSE_FLAVOR_16(vi);

        wIn[index] = vi;
    }


    if (Extra == 0 && SwapFirst) {
        cmsUInt16Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
        wIn[nChan-1] = tmp;
    }

    if (T_PLANAR(info -> InputFormat))
        return accum + sizeof(cmsFloat64Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
}



static
cmsUInt8Number* UnrollFloatTo16(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wIn[],
                                CMSREGISTER cmsUInt8Number* accum,
                                CMSREGISTER cmsUInt32Number Stride)
{

    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
    cmsFloat32Number v;
    cmsUInt16Number  vi;
    cmsUInt32Number i, start = 0;
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;

    Stride /= PixelSize(info->InputFormat);

    if (ExtraFirst)
            start = Extra;

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
        else
            v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];

        vi = _cmsQuickSaturateWord(v * maximum);

        if (Reverse)
            vi = REVERSE_FLAVOR_16(vi);

        wIn[index] = vi;
    }


    if (Extra == 0 && SwapFirst) {
        cmsUInt16Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
        wIn[nChan-1] = tmp;
    }

    if (T_PLANAR(info -> InputFormat))
        return accum + sizeof(cmsFloat32Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
}




// For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
static
cmsUInt8Number* UnrollDouble1Chan(CMSREGISTER _cmsTRANSFORM* info,
                                  CMSREGISTER cmsUInt16Number wIn[],
                                  CMSREGISTER cmsUInt8Number* accum,
                                  CMSREGISTER cmsUInt32Number Stride)
{
    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;

    wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);

    return accum + sizeof(cmsFloat64Number);

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

//-------------------------------------------------------------------------------------------------------------------

// For anything going from cmsUInt8Number
static
cmsUInt8Number* Unroll8ToFloat(_cmsTRANSFORM* info,
                               cmsFloat32Number wIn[],
                               cmsUInt8Number* accum,
                               cmsUInt32Number Stride)
{

    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
    cmsFloat32Number v;
    cmsUInt32Number i, start = 0;

    Stride /= PixelSize(info->InputFormat);

    if (ExtraFirst)
        start = Extra;

    for (i = 0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[(i + start) * Stride];
        else
            v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[i + start];

        v /= 255.0F;

        wIn[index] = Reverse ? 1 - v : v;
    }


    if (Extra == 0 && SwapFirst) {
        cmsFloat32Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
        wIn[nChan - 1] = tmp;
    }

    if (T_PLANAR(info->InputFormat))
        return accum + sizeof(cmsUInt8Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsUInt8Number);
}


// For anything going from cmsUInt16Number
static
cmsUInt8Number* Unroll16ToFloat(_cmsTRANSFORM* info,
                                cmsFloat32Number wIn[],
                                cmsUInt8Number* accum,
                                cmsUInt32Number Stride)
{

    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
    cmsFloat32Number v;
    cmsUInt32Number i, start = 0;

    Stride /= PixelSize(info->InputFormat);

    if (ExtraFirst)
        start = Extra;

    for (i = 0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[(i + start) * Stride];
        else
            v = (cmsFloat32Number)((cmsUInt16Number*)accum)[i + start];

        v /= 65535.0F;

        wIn[index] = Reverse ? 1 - v : v;
    }


    if (Extra == 0 && SwapFirst) {
        cmsFloat32Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
        wIn[nChan - 1] = tmp;
    }

    if (T_PLANAR(info->InputFormat))
        return accum + sizeof(cmsUInt16Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
}


// For anything going from cmsFloat32Number
static
cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
                                    cmsFloat32Number wIn[],
                                    cmsUInt8Number* accum,
                                    cmsUInt32Number Stride)
{

    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
    cmsFloat32Number v;
    cmsUInt32Number i, start = 0;
    cmsFloat32Number maximum = IsInkSpace(info->InputFormat) ? 100.0F : 1.0F;
    cmsFloat32Number alpha_factor = 1.0f;
    cmsFloat32Number* ptr = (cmsFloat32Number*)accum;

    Stride /= PixelSize(info->InputFormat);

    if (Premul && Extra)
    {
        if (Planar)
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
        else
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
    }

    if (ExtraFirst)
            start = Extra;

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = ptr[(i + start) * Stride];
        else
            v = ptr[i + start];

        if (Premul && alpha_factor > 0)
            v /= alpha_factor;

        v /= maximum;

        wIn[index] = Reverse ? 1 - v : v;
    }


    if (Extra == 0 && SwapFirst) {
        cmsFloat32Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
        wIn[nChan-1] = tmp;
    }

    if (T_PLANAR(info -> InputFormat))
        return accum + sizeof(cmsFloat32Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsFloat32Number);
}

// For anything going from double

static
cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
                                    cmsFloat32Number wIn[],
                                    cmsUInt8Number* accum,
                                    cmsUInt32Number Stride)
{

    cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
    cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
    cmsFloat64Number v;
    cmsUInt32Number i, start = 0;
    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
    cmsFloat64Number alpha_factor = 1.0;
    cmsFloat64Number* ptr = (cmsFloat64Number*)accum;

    Stride /= PixelSize(info->InputFormat);

    if (Premul && Extra)
    {
        if (Planar)
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
        else
            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
    }

    if (ExtraFirst)
            start = Extra;

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        if (Planar)
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start)  * Stride];
        else
            v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];


        if (Premul && alpha_factor > 0)
            v /= alpha_factor;

        v /= maximum;

        wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);
    }


    if (Extra == 0 && SwapFirst) {
        cmsFloat32Number tmp = wIn[0];

        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));
        wIn[nChan-1] = tmp;
    }

    if (T_PLANAR(info -> InputFormat))
        return accum + sizeof(cmsFloat64Number);
    else
        return accum + (nChan + Extra) * sizeof(cmsFloat64Number);
}



// From Lab double to cmsFloat32Number
static
cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info,
                                       cmsFloat32Number wIn[],
                                       cmsUInt8Number* accum,
                                       cmsUInt32Number Stride)
{
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;

    if (T_PLANAR(info -> InputFormat)) {

        Stride /= PixelSize(info->InputFormat);

        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);

        return accum + sizeof(cmsFloat64Number);
    }
    else {

        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);

        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
        return accum;
    }
}

// From Lab double to cmsFloat32Number
static
cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,
                                      cmsFloat32Number wIn[],
                                      cmsUInt8Number* accum,
                                      cmsUInt32Number Stride)
{
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;

    if (T_PLANAR(info -> InputFormat)) {

        Stride /= PixelSize(info->InputFormat);

        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                 // from 0..100 to 0..1
        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);

        return accum + sizeof(cmsFloat32Number);
    }
    else {

        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);            // from 0..100 to 0..1
        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);

        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
        return accum;
    }
}

// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
static
cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,
                                       cmsFloat32Number wIn[],
                                       cmsUInt8Number* accum,
                                       cmsUInt32Number Stride)
{
    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;

    if (T_PLANAR(info -> InputFormat)) {

        Stride /= PixelSize(info->InputFormat);

        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);

        return accum + sizeof(cmsFloat64Number);
    }
    else {

        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);

        accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));
        return accum;
    }
}

static
cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,
                                      cmsFloat32Number wIn[],
                                      cmsUInt8Number* accum,
                                      cmsUInt32Number Stride)
{
    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;

    if (T_PLANAR(info -> InputFormat)) {

        Stride /= PixelSize(info->InputFormat);

        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);

        return accum + sizeof(cmsFloat32Number);
    }
    else {

        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);

        accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));
        return accum;
    }
}


cmsINLINE void lab4toFloat(cmsFloat32Number wIn[], cmsUInt16Number lab4[3])
{
    cmsFloat32Number L = (cmsFloat32Number) lab4[0] / 655.35F;
    cmsFloat32Number a = ((cmsFloat32Number) lab4[1] / 257.0F) - 128.0F;
    cmsFloat32Number b = ((cmsFloat32Number) lab4[2] / 257.0F) - 128.0F;

    wIn[0] = (L / 100.0F);                    // from 0..100 to 0..1
    wIn[1] = ((a + 128.0F) / 255.0F);         // form -128..+127 to 0..1
    wIn[2] = ((b + 128.0F) / 255.0F);

}

static
cmsUInt8Number* UnrollLabV2_8ToFloat(_cmsTRANSFORM* info,
                                      cmsFloat32Number wIn[],
                                      cmsUInt8Number* accum,
                                      cmsUInt32Number Stride)
{
    cmsUInt16Number lab4[3];

    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b

    lab4toFloat(wIn, lab4);

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* UnrollALabV2_8ToFloat(_cmsTRANSFORM* info,
                                      cmsFloat32Number wIn[],
                                      cmsUInt8Number* accum,
                                      cmsUInt32Number Stride)
{
    cmsUInt16Number lab4[3];

    accum++;  // A
    lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
    lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
    lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b

    lab4toFloat(wIn, lab4);

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* UnrollLabV2_16ToFloat(_cmsTRANSFORM* info,
                                      cmsFloat32Number wIn[],
                                      cmsUInt8Number* accum,
                                      cmsUInt32Number Stride)
{
    cmsUInt16Number lab4[3];

    lab4[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
    lab4[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
    lab4[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b

    lab4toFloat(wIn, lab4);

    return accum;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


// Packing routines -----------------------------------------------------------------------------------------------------------


// Generic chunky for byte
static
cmsUInt8Number* PackChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wOut[],
                                CMSREGISTER cmsUInt8Number* output,
                                CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt8Number* swap1;
    cmsUInt16Number v = 0;
    cmsUInt32Number i;
    cmsUInt32Number alpha_factor = 0;

    swap1 = output;

    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));

        output += Extra;
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan]));
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        v = wOut[index];

        if (Reverse)
            v = REVERSE_FLAVOR_16(v);

        if (Premul && alpha_factor != 0)
        {
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
        }

        *output++ = FROM_16_TO_8(v);
    }

    if (!ExtraFirst) {
        output += Extra;
    }

    if (Extra == 0 && SwapFirst) {

        memmove(swap1 + 1, swap1, nChan-1);
        *swap1 = FROM_16_TO_8(v);
    }

    return output;

    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* PackChunkyWords(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wOut[],
                                CMSREGISTER cmsUInt8Number* output,
                                CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt16Number* swap1;
    cmsUInt16Number v = 0;
    cmsUInt32Number i;
    cmsUInt32Number alpha_factor = 0;

    swap1 = (cmsUInt16Number*) output;

    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(*(cmsUInt16Number*) output);

        output += Extra * sizeof(cmsUInt16Number);
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[nChan]);
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        v = wOut[index];

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        if (Reverse)
            v = REVERSE_FLAVOR_16(v);

        if (Premul && alpha_factor != 0)
        {
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
        }

        *(cmsUInt16Number*) output = v;

        output += sizeof(cmsUInt16Number);
    }

    if (!ExtraFirst) {
        output += Extra * sizeof(cmsUInt16Number);
    }

    if (Extra == 0 && SwapFirst) {

        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
        *swap1 = v;
    }

    return output;

    cmsUNUSED_PARAMETER(Stride);
}



static
cmsUInt8Number* PackPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wOut[],
                                CMSREGISTER cmsUInt8Number* output,
                                CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
    cmsUInt32Number i;
    cmsUInt8Number* Init = output;
    cmsUInt32Number alpha_factor = 0;


    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));

        output += Extra * Stride;
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan * Stride]));
    }


    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
        cmsUInt16Number v = wOut[index];

        if (Reverse)
            v = REVERSE_FLAVOR_16(v);

        if (Premul && alpha_factor != 0)
        {
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
        }

        *(cmsUInt8Number*)output = FROM_16_TO_8(v);

        output += Stride;
    }

    return (Init + 1);

    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
                                CMSREGISTER cmsUInt16Number wOut[],
                                CMSREGISTER cmsUInt8Number* output,
                                CMSREGISTER cmsUInt32Number Stride)
{
    cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
    cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
    cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
    cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
    cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
    cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
    cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
    cmsUInt32Number i;
    cmsUInt8Number* Init = output;
    cmsUInt16Number v;
    cmsUInt32Number alpha_factor = 0;

    if (ExtraFirst) {

        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[0]);

        output += Extra * Stride;
    }
    else
    {
        if (Premul && Extra)
            alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*)output)[nChan * Stride]);
    }

    for (i=0; i < nChan; i++) {

        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;

        v = wOut[index];

        if (SwapEndian)
            v = CHANGE_ENDIAN(v);

        if (Reverse)
            v =  REVERSE_FLAVOR_16(v);

        if (Premul && alpha_factor != 0)
        {
            v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
        }

        *(cmsUInt16Number*) output = v;
        output += Stride;
    }

    return (Init + sizeof(cmsUInt16Number));
}

// CMYKcm (unrolled for speed)

static
cmsUInt8Number* Pack6Bytes(CMSREGISTER _cmsTRANSFORM* info,
                           CMSREGISTER cmsUInt16Number wOut[],
                           CMSREGISTER cmsUInt8Number* output,
                           CMSREGISTER cmsUInt32Number Stride)
{
    *output++ = FROM_16_TO_8(wOut[0]);
    *output++ = FROM_16_TO_8(wOut[1]);
    *output++ = FROM_16_TO_8(wOut[2]);
    *output++ = FROM_16_TO_8(wOut[3]);
    *output++ = FROM_16_TO_8(wOut[4]);
    *output++ = FROM_16_TO_8(wOut[5]);

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// KCMYcm

static
cmsUInt8Number* Pack6BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wOut[],
                               CMSREGISTER cmsUInt8Number* output,
                               CMSREGISTER cmsUInt32Number Stride)
{
    *output++ = FROM_16_TO_8(wOut[5]);
    *output++ = FROM_16_TO_8(wOut[4]);
    *output++ = FROM_16_TO_8(wOut[3]);
    *output++ = FROM_16_TO_8(wOut[2]);
    *output++ = FROM_16_TO_8(wOut[1]);
    *output++ = FROM_16_TO_8(wOut[0]);

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// CMYKcm
static
cmsUInt8Number* Pack6Words(CMSREGISTER _cmsTRANSFORM* info,
                           CMSREGISTER cmsUInt16Number wOut[],
                           CMSREGISTER cmsUInt8Number* output,
                           CMSREGISTER cmsUInt32Number Stride)
{
    *(cmsUInt16Number*) output = wOut[0];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[1];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[2];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[3];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[4];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[5];
    output+= 2;

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// KCMYcm
static
cmsUInt8Number* Pack6WordsSwap(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wOut[],
                               CMSREGISTER cmsUInt8Number* output,
                               CMSREGISTER cmsUInt32Number Stride)
{
    *(cmsUInt16Number*) output = wOut[5];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[4];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[3];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[2];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[1];
    output+= 2;
    *(cmsUInt16Number*) output = wOut[0];
    output+= 2;

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* Pack4Bytes(CMSREGISTER _cmsTRANSFORM* info,
                           CMSREGISTER cmsUInt16Number wOut[],
                           CMSREGISTER cmsUInt8Number* output,
                           CMSREGISTER cmsUInt32Number Stride)
{
    *output++ = FROM_16_TO_8(wOut[0]);
    *output++ = FROM_16_TO_8(wOut[1]);
    *output++ = FROM_16_TO_8(wOut[2]);
    *output++ = FROM_16_TO_8(wOut[3]);

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

static
cmsUInt8Number* Pack4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,
                                  CMSREGISTER cmsUInt16Number wOut[],
                                  CMSREGISTER cmsUInt8Number* output,
                                  CMSREGISTER cmsUInt32Number Stride)
{
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}


static
cmsUInt8Number* Pack4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,
                                    CMSREGISTER cmsUInt16Number wOut[],
                                    CMSREGISTER cmsUInt8Number* output,
                                    CMSREGISTER cmsUInt32Number Stride)
{
    *output++ = FROM_16_TO_8(wOut[3]);
    *output++ = FROM_16_TO_8(wOut[0]);
    *output++ = FROM_16_TO_8(wOut[1]);
    *output++ = FROM_16_TO_8(wOut[2]);

    return output;

    cmsUNUSED_PARAMETER(info);
    cmsUNUSED_PARAMETER(Stride);
}

// ABGR
static
cmsUInt8Number* Pack4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,
                               CMSREGISTER cmsUInt16Number wOut[],
                               CMSREGISTER cmsUInt8Number* output,
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=93 H=92 G=92

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.