Path: blob/master/src/java.desktop/share/native/liblcms/cmspack.c
41149 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324// This file is available under and governed by the GNU General Public25// License version 2 only, as published by the Free Software Foundation.26// However, the following notice accompanied the original version of this27// file:28//29//---------------------------------------------------------------------------------30//31// Little Color Management System32// Copyright (c) 1998-2020 Marti Maria Saguer33//34// Permission is hereby granted, free of charge, to any person obtaining35// a copy of this software and associated documentation files (the "Software"),36// to deal in the Software without restriction, including without limitation37// the rights to use, copy, modify, merge, publish, distribute, sublicense,38// and/or sell copies of the Software, and to permit persons to whom the Software39// is furnished to do so, subject to the following conditions:40//41// The above copyright notice and this permission notice shall be included in42// all copies or substantial portions of the Software.43//44// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,45// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO46// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND47// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE48// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION49// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION50// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.51//52//---------------------------------------------------------------------------------53//5455#include "lcms2_internal.h"5657// This module handles all formats supported by lcms. There are two flavors, 16 bits and58// floating point. Floating point is supported only in a subset, those formats holding59// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component60// as special case)6162// ---------------------------------------------------------------------------636465// This macro return words stored as big endian66#define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))6768// These macros handles reversing (negative)69#define REVERSE_FLAVOR_8(x) ((cmsUInt8Number) (0xff-(x)))70#define REVERSE_FLAVOR_16(x) ((cmsUInt16Number)(0xffff-(x)))7172// * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 25673cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x)74{75int a = (x << 8 | x) >> 8; // * 257 / 25676if ( a > 0xffff) return 0xffff;77return (cmsUInt16Number) a;78}7980// * 0xf00 / 0xffff = * 256 / 25781cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)82{83return (cmsUInt16Number) (((x << 8) + 0x80) / 257);84}858687typedef struct {88cmsUInt32Number Type;89cmsUInt32Number Mask;90cmsFormatter16 Frm;9192} cmsFormatters16;9394typedef struct {95cmsUInt32Number Type;96cmsUInt32Number Mask;97cmsFormatterFloat Frm;9899} cmsFormattersFloat;100101102#define ANYSPACE COLORSPACE_SH(31)103#define ANYCHANNELS CHANNELS_SH(15)104#define ANYEXTRA EXTRA_SH(7)105#define ANYPLANAR PLANAR_SH(1)106#define ANYENDIAN ENDIAN16_SH(1)107#define ANYSWAP DOSWAP_SH(1)108#define ANYSWAPFIRST SWAPFIRST_SH(1)109#define ANYFLAVOR FLAVOR_SH(1)110111112// Suppress waning about info never being used113114#ifdef _MSC_VER115#pragma warning(disable : 4100)116#endif117118// Unpacking routines (16 bits) ----------------------------------------------------------------------------------------119120121// Does almost everything but is slow122static123cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,124CMSREGISTER cmsUInt16Number wIn[],125CMSREGISTER cmsUInt8Number* accum,126CMSREGISTER cmsUInt32Number Stride)127{128cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);129cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);130cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);131cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);132cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);133cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;134cmsUInt16Number v;135cmsUInt32Number i;136137if (ExtraFirst) {138accum += Extra;139}140141for (i=0; i < nChan; i++) {142cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;143144v = FROM_8_TO_16(*accum);145v = Reverse ? REVERSE_FLAVOR_16(v) : v;146wIn[index] = v;147accum++;148}149150if (!ExtraFirst) {151accum += Extra;152}153154if (Extra == 0 && SwapFirst) {155cmsUInt16Number tmp = wIn[0];156157memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));158wIn[nChan-1] = tmp;159}160161return accum;162163cmsUNUSED_PARAMETER(info);164cmsUNUSED_PARAMETER(Stride);165166}167168// Extra channels are just ignored because come in the next planes169static170cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,171CMSREGISTER cmsUInt16Number wIn[],172CMSREGISTER cmsUInt8Number* accum,173CMSREGISTER cmsUInt32Number Stride)174{175cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);176cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);177cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);178cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);179cmsUInt32Number i;180cmsUInt8Number* Init = accum;181182if (DoSwap ^ SwapFirst) {183accum += T_EXTRA(info -> InputFormat) * Stride;184}185186for (i=0; i < nChan; i++) {187188cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;189cmsUInt16Number v = FROM_8_TO_16(*accum);190191wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;192accum += Stride;193}194195return (Init + 1);196}197198// Special cases, provided for performance199static200cmsUInt8Number* Unroll4Bytes(CMSREGISTER _cmsTRANSFORM* info,201CMSREGISTER cmsUInt16Number wIn[],202CMSREGISTER cmsUInt8Number* accum,203CMSREGISTER cmsUInt32Number Stride)204{205wIn[0] = FROM_8_TO_16(*accum); accum++; // C206wIn[1] = FROM_8_TO_16(*accum); accum++; // M207wIn[2] = FROM_8_TO_16(*accum); accum++; // Y208wIn[3] = FROM_8_TO_16(*accum); accum++; // K209210return accum;211212cmsUNUSED_PARAMETER(info);213cmsUNUSED_PARAMETER(Stride);214}215216static217cmsUInt8Number* Unroll4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,218CMSREGISTER cmsUInt16Number wIn[],219CMSREGISTER cmsUInt8Number* accum,220CMSREGISTER cmsUInt32Number Stride)221{222wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C223wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M224wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y225wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K226227return accum;228229cmsUNUSED_PARAMETER(info);230cmsUNUSED_PARAMETER(Stride);231}232233static234cmsUInt8Number* Unroll4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,235CMSREGISTER cmsUInt16Number wIn[],236CMSREGISTER cmsUInt8Number* accum,237CMSREGISTER cmsUInt32Number Stride)238{239wIn[3] = FROM_8_TO_16(*accum); accum++; // K240wIn[0] = FROM_8_TO_16(*accum); accum++; // C241wIn[1] = FROM_8_TO_16(*accum); accum++; // M242wIn[2] = FROM_8_TO_16(*accum); accum++; // Y243244return accum;245246cmsUNUSED_PARAMETER(info);247cmsUNUSED_PARAMETER(Stride);248}249250// KYMC251static252cmsUInt8Number* Unroll4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,253CMSREGISTER cmsUInt16Number wIn[],254CMSREGISTER cmsUInt8Number* accum,255CMSREGISTER cmsUInt32Number Stride)256{257wIn[3] = FROM_8_TO_16(*accum); accum++; // K258wIn[2] = FROM_8_TO_16(*accum); accum++; // Y259wIn[1] = FROM_8_TO_16(*accum); accum++; // M260wIn[0] = FROM_8_TO_16(*accum); accum++; // C261262return accum;263264cmsUNUSED_PARAMETER(info);265cmsUNUSED_PARAMETER(Stride);266}267268static269cmsUInt8Number* Unroll4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,270CMSREGISTER cmsUInt16Number wIn[],271CMSREGISTER cmsUInt8Number* accum,272CMSREGISTER cmsUInt32Number Stride)273{274wIn[2] = FROM_8_TO_16(*accum); accum++; // K275wIn[1] = FROM_8_TO_16(*accum); accum++; // Y276wIn[0] = FROM_8_TO_16(*accum); accum++; // M277wIn[3] = FROM_8_TO_16(*accum); accum++; // C278279return accum;280281cmsUNUSED_PARAMETER(info);282cmsUNUSED_PARAMETER(Stride);283}284285static286cmsUInt8Number* Unroll3Bytes(CMSREGISTER _cmsTRANSFORM* info,287CMSREGISTER cmsUInt16Number wIn[],288CMSREGISTER cmsUInt8Number* accum,289CMSREGISTER cmsUInt32Number Stride)290{291wIn[0] = FROM_8_TO_16(*accum); accum++; // R292wIn[1] = FROM_8_TO_16(*accum); accum++; // G293wIn[2] = FROM_8_TO_16(*accum); accum++; // B294295return accum;296297cmsUNUSED_PARAMETER(info);298cmsUNUSED_PARAMETER(Stride);299}300301static302cmsUInt8Number* Unroll3BytesSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,303CMSREGISTER cmsUInt16Number wIn[],304CMSREGISTER cmsUInt8Number* accum,305CMSREGISTER cmsUInt32Number Stride)306{307accum++; // A308wIn[2] = FROM_8_TO_16(*accum); accum++; // B309wIn[1] = FROM_8_TO_16(*accum); accum++; // G310wIn[0] = FROM_8_TO_16(*accum); accum++; // R311312return accum;313314cmsUNUSED_PARAMETER(info);315cmsUNUSED_PARAMETER(Stride);316}317318static319cmsUInt8Number* Unroll3BytesSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,320CMSREGISTER cmsUInt16Number wIn[],321CMSREGISTER cmsUInt8Number* accum,322CMSREGISTER cmsUInt32Number Stride)323{324wIn[2] = FROM_8_TO_16(*accum); accum++; // B325wIn[1] = FROM_8_TO_16(*accum); accum++; // G326wIn[0] = FROM_8_TO_16(*accum); accum++; // R327accum++; // A328329return accum;330331cmsUNUSED_PARAMETER(info);332cmsUNUSED_PARAMETER(Stride);333}334335static336cmsUInt8Number* Unroll3BytesSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,337CMSREGISTER cmsUInt16Number wIn[],338CMSREGISTER cmsUInt8Number* accum,339CMSREGISTER cmsUInt32Number Stride)340{341accum++; // A342wIn[0] = FROM_8_TO_16(*accum); accum++; // R343wIn[1] = FROM_8_TO_16(*accum); accum++; // G344wIn[2] = FROM_8_TO_16(*accum); accum++; // B345346return accum;347348cmsUNUSED_PARAMETER(info);349cmsUNUSED_PARAMETER(Stride);350}351352353// BRG354static355cmsUInt8Number* Unroll3BytesSwap(CMSREGISTER _cmsTRANSFORM* info,356CMSREGISTER cmsUInt16Number wIn[],357CMSREGISTER cmsUInt8Number* accum,358CMSREGISTER cmsUInt32Number Stride)359{360wIn[2] = FROM_8_TO_16(*accum); accum++; // B361wIn[1] = FROM_8_TO_16(*accum); accum++; // G362wIn[0] = FROM_8_TO_16(*accum); accum++; // R363364return accum;365366cmsUNUSED_PARAMETER(info);367cmsUNUSED_PARAMETER(Stride);368}369370static371cmsUInt8Number* UnrollLabV2_8(CMSREGISTER _cmsTRANSFORM* info,372CMSREGISTER cmsUInt16Number wIn[],373CMSREGISTER cmsUInt8Number* accum,374CMSREGISTER cmsUInt32Number Stride)375{376wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L377wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a378wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b379380return accum;381382cmsUNUSED_PARAMETER(info);383cmsUNUSED_PARAMETER(Stride);384}385386static387cmsUInt8Number* UnrollALabV2_8(CMSREGISTER _cmsTRANSFORM* info,388CMSREGISTER cmsUInt16Number wIn[],389CMSREGISTER cmsUInt8Number* accum,390CMSREGISTER cmsUInt32Number Stride)391{392accum++; // A393wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L394wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a395wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b396397return accum;398399cmsUNUSED_PARAMETER(info);400cmsUNUSED_PARAMETER(Stride);401}402403static404cmsUInt8Number* UnrollLabV2_16(CMSREGISTER _cmsTRANSFORM* info,405CMSREGISTER cmsUInt16Number wIn[],406CMSREGISTER cmsUInt8Number* accum,407CMSREGISTER cmsUInt32Number Stride)408{409wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L410wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a411wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b412413return accum;414415cmsUNUSED_PARAMETER(info);416cmsUNUSED_PARAMETER(Stride);417}418419// for duplex420static421cmsUInt8Number* Unroll2Bytes(CMSREGISTER _cmsTRANSFORM* info,422CMSREGISTER cmsUInt16Number wIn[],423CMSREGISTER cmsUInt8Number* accum,424CMSREGISTER cmsUInt32Number Stride)425{426wIn[0] = FROM_8_TO_16(*accum); accum++; // ch1427wIn[1] = FROM_8_TO_16(*accum); accum++; // ch2428429return accum;430431cmsUNUSED_PARAMETER(info);432cmsUNUSED_PARAMETER(Stride);433}434435436437438// Monochrome duplicates L into RGB for null-transforms439static440cmsUInt8Number* Unroll1Byte(CMSREGISTER _cmsTRANSFORM* info,441CMSREGISTER cmsUInt16Number wIn[],442CMSREGISTER cmsUInt8Number* accum,443CMSREGISTER cmsUInt32Number Stride)444{445wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L446447return accum;448449cmsUNUSED_PARAMETER(info);450cmsUNUSED_PARAMETER(Stride);451}452453454static455cmsUInt8Number* Unroll1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info,456CMSREGISTER cmsUInt16Number wIn[],457CMSREGISTER cmsUInt8Number* accum,458CMSREGISTER cmsUInt32Number Stride)459{460wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L461accum += 1;462463return accum;464465cmsUNUSED_PARAMETER(info);466cmsUNUSED_PARAMETER(Stride);467}468469static470cmsUInt8Number* Unroll1ByteSkip2(CMSREGISTER _cmsTRANSFORM* info,471CMSREGISTER cmsUInt16Number wIn[],472CMSREGISTER cmsUInt8Number* accum,473CMSREGISTER cmsUInt32Number Stride)474{475wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++; // L476accum += 2;477478return accum;479480cmsUNUSED_PARAMETER(info);481cmsUNUSED_PARAMETER(Stride);482}483484static485cmsUInt8Number* Unroll1ByteReversed(CMSREGISTER _cmsTRANSFORM* info,486CMSREGISTER cmsUInt16Number wIn[],487CMSREGISTER cmsUInt8Number* accum,488CMSREGISTER cmsUInt32Number Stride)489{490wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++; // L491492return accum;493494cmsUNUSED_PARAMETER(info);495cmsUNUSED_PARAMETER(Stride);496}497498499static500cmsUInt8Number* UnrollAnyWords(CMSREGISTER _cmsTRANSFORM* info,501CMSREGISTER cmsUInt16Number wIn[],502CMSREGISTER cmsUInt8Number* accum,503CMSREGISTER cmsUInt32Number Stride)504{505cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);506cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);507cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);508cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);509cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);510cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);511cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;512cmsUInt32Number i;513514if (ExtraFirst) {515accum += Extra * sizeof(cmsUInt16Number);516}517518for (i=0; i < nChan; i++) {519520cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;521cmsUInt16Number v = *(cmsUInt16Number*) accum;522523if (SwapEndian)524v = CHANGE_ENDIAN(v);525526wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;527528accum += sizeof(cmsUInt16Number);529}530531if (!ExtraFirst) {532accum += Extra * sizeof(cmsUInt16Number);533}534535if (Extra == 0 && SwapFirst) {536537cmsUInt16Number tmp = wIn[0];538539memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));540wIn[nChan-1] = tmp;541}542543return accum;544545cmsUNUSED_PARAMETER(Stride);546}547548static549cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info,550CMSREGISTER cmsUInt16Number wIn[],551CMSREGISTER cmsUInt8Number* accum,552CMSREGISTER cmsUInt32Number Stride)553{554cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);555cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);556cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);557cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);558cmsUInt32Number i;559cmsUInt8Number* Init = accum;560561if (DoSwap) {562accum += T_EXTRA(info -> InputFormat) * Stride;563}564565for (i=0; i < nChan; i++) {566567cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;568cmsUInt16Number v = *(cmsUInt16Number*) accum;569570if (SwapEndian)571v = CHANGE_ENDIAN(v);572573wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;574575accum += Stride;576}577578return (Init + sizeof(cmsUInt16Number));579}580581582static583cmsUInt8Number* Unroll4Words(CMSREGISTER _cmsTRANSFORM* info,584CMSREGISTER cmsUInt16Number wIn[],585CMSREGISTER cmsUInt8Number* accum,586CMSREGISTER cmsUInt32Number Stride)587{588wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C589wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M590wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y591wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K592593return accum;594595cmsUNUSED_PARAMETER(info);596cmsUNUSED_PARAMETER(Stride);597}598599static600cmsUInt8Number* Unroll4WordsReverse(CMSREGISTER _cmsTRANSFORM* info,601CMSREGISTER cmsUInt16Number wIn[],602CMSREGISTER cmsUInt8Number* accum,603CMSREGISTER cmsUInt32Number Stride)604{605wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C606wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M607wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y608wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K609610return accum;611612cmsUNUSED_PARAMETER(info);613cmsUNUSED_PARAMETER(Stride);614}615616static617cmsUInt8Number* Unroll4WordsSwapFirst(CMSREGISTER _cmsTRANSFORM* info,618CMSREGISTER cmsUInt16Number wIn[],619CMSREGISTER cmsUInt8Number* accum,620CMSREGISTER cmsUInt32Number Stride)621{622wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K623wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C624wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M625wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y626627return accum;628629cmsUNUSED_PARAMETER(info);630cmsUNUSED_PARAMETER(Stride);631}632633// KYMC634static635cmsUInt8Number* Unroll4WordsSwap(CMSREGISTER _cmsTRANSFORM* info,636CMSREGISTER cmsUInt16Number wIn[],637CMSREGISTER cmsUInt8Number* accum,638CMSREGISTER cmsUInt32Number Stride)639{640wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K641wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y642wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M643wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C644645return accum;646647cmsUNUSED_PARAMETER(info);648cmsUNUSED_PARAMETER(Stride);649}650651static652cmsUInt8Number* Unroll4WordsSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,653CMSREGISTER cmsUInt16Number wIn[],654CMSREGISTER cmsUInt8Number* accum,655CMSREGISTER cmsUInt32Number Stride)656{657wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K658wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y659wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M660wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C661662return accum;663664cmsUNUSED_PARAMETER(info);665cmsUNUSED_PARAMETER(Stride);666}667668static669cmsUInt8Number* Unroll3Words(CMSREGISTER _cmsTRANSFORM* info,670CMSREGISTER cmsUInt16Number wIn[],671CMSREGISTER cmsUInt8Number* accum,672CMSREGISTER cmsUInt32Number Stride)673{674wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C R675wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G676wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y B677678return accum;679680cmsUNUSED_PARAMETER(info);681cmsUNUSED_PARAMETER(Stride);682}683684static685cmsUInt8Number* Unroll3WordsSwap(CMSREGISTER _cmsTRANSFORM* info,686CMSREGISTER cmsUInt16Number wIn[],687CMSREGISTER cmsUInt8Number* accum,688CMSREGISTER cmsUInt32Number Stride)689{690wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // C R691wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M G692wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // Y B693694return accum;695696cmsUNUSED_PARAMETER(info);697cmsUNUSED_PARAMETER(Stride);698}699700static701cmsUInt8Number* Unroll3WordsSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,702CMSREGISTER cmsUInt16Number wIn[],703CMSREGISTER cmsUInt8Number* accum,704CMSREGISTER cmsUInt32Number Stride)705{706accum += 2; // A707wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R708wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G709wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B710711return accum;712713cmsUNUSED_PARAMETER(info);714cmsUNUSED_PARAMETER(Stride);715}716717static718cmsUInt8Number* Unroll3WordsSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,719CMSREGISTER cmsUInt16Number wIn[],720CMSREGISTER cmsUInt8Number* accum,721CMSREGISTER cmsUInt32Number Stride)722{723accum += 2; // A724wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R725wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G726wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B727728return accum;729730cmsUNUSED_PARAMETER(info);731cmsUNUSED_PARAMETER(Stride);732}733734static735cmsUInt8Number* Unroll1Word(CMSREGISTER _cmsTRANSFORM* info,736CMSREGISTER cmsUInt16Number wIn[],737CMSREGISTER cmsUInt8Number* accum,738CMSREGISTER cmsUInt32Number Stride)739{740wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // L741742return accum;743744cmsUNUSED_PARAMETER(info);745cmsUNUSED_PARAMETER(Stride);746}747748static749cmsUInt8Number* Unroll1WordReversed(CMSREGISTER _cmsTRANSFORM* info,750CMSREGISTER cmsUInt16Number wIn[],751CMSREGISTER cmsUInt8Number* accum,752CMSREGISTER cmsUInt32Number Stride)753{754wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;755756return accum;757758cmsUNUSED_PARAMETER(info);759cmsUNUSED_PARAMETER(Stride);760}761762static763cmsUInt8Number* Unroll1WordSkip3(CMSREGISTER _cmsTRANSFORM* info,764CMSREGISTER cmsUInt16Number wIn[],765CMSREGISTER cmsUInt8Number* accum,766CMSREGISTER cmsUInt32Number Stride)767{768wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;769770accum += 8;771772return accum;773774cmsUNUSED_PARAMETER(info);775cmsUNUSED_PARAMETER(Stride);776}777778static779cmsUInt8Number* Unroll2Words(CMSREGISTER _cmsTRANSFORM* info,780CMSREGISTER cmsUInt16Number wIn[],781CMSREGISTER cmsUInt8Number* accum,782CMSREGISTER cmsUInt32Number Stride)783{784wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // ch1785wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // ch2786787return accum;788789cmsUNUSED_PARAMETER(info);790cmsUNUSED_PARAMETER(Stride);791}792793794// This is a conversion of Lab double to 16 bits795static796cmsUInt8Number* UnrollLabDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,797CMSREGISTER cmsUInt16Number wIn[],798CMSREGISTER cmsUInt8Number* accum,799CMSREGISTER cmsUInt32Number Stride)800{801if (T_PLANAR(info -> InputFormat)) {802803cmsCIELab Lab;804cmsUInt8Number* pos_L;805cmsUInt8Number* pos_a;806cmsUInt8Number* pos_b;807808pos_L = accum;809pos_a = accum + Stride;810pos_b = accum + Stride * 2;811812Lab.L = *(cmsFloat64Number*) pos_L;813Lab.a = *(cmsFloat64Number*) pos_a;814Lab.b = *(cmsFloat64Number*) pos_b;815816cmsFloat2LabEncoded(wIn, &Lab);817return accum + sizeof(cmsFloat64Number);818}819else {820821cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum);822accum += sizeof(cmsCIELab) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);823return accum;824}825}826827828// This is a conversion of Lab float to 16 bits829static830cmsUInt8Number* UnrollLabFloatTo16(CMSREGISTER _cmsTRANSFORM* info,831CMSREGISTER cmsUInt16Number wIn[],832CMSREGISTER cmsUInt8Number* accum,833CMSREGISTER cmsUInt32Number Stride)834{835cmsCIELab Lab;836837if (T_PLANAR(info -> InputFormat)) {838839cmsUInt8Number* pos_L;840cmsUInt8Number* pos_a;841cmsUInt8Number* pos_b;842843pos_L = accum;844pos_a = accum + Stride;845pos_b = accum + Stride * 2;846847Lab.L = *(cmsFloat32Number*)pos_L;848Lab.a = *(cmsFloat32Number*)pos_a;849Lab.b = *(cmsFloat32Number*)pos_b;850851cmsFloat2LabEncoded(wIn, &Lab);852return accum + sizeof(cmsFloat32Number);853}854else {855856Lab.L = ((cmsFloat32Number*) accum)[0];857Lab.a = ((cmsFloat32Number*) accum)[1];858Lab.b = ((cmsFloat32Number*) accum)[2];859860cmsFloat2LabEncoded(wIn, &Lab);861accum += (3 + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);862return accum;863}864}865866// This is a conversion of XYZ double to 16 bits867static868cmsUInt8Number* UnrollXYZDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,869CMSREGISTER cmsUInt16Number wIn[],870CMSREGISTER cmsUInt8Number* accum,871CMSREGISTER cmsUInt32Number Stride)872{873if (T_PLANAR(info -> InputFormat)) {874875cmsCIEXYZ XYZ;876cmsUInt8Number* pos_X;877cmsUInt8Number* pos_Y;878cmsUInt8Number* pos_Z;879880pos_X = accum;881pos_Y = accum + Stride;882pos_Z = accum + Stride * 2;883884XYZ.X = *(cmsFloat64Number*)pos_X;885XYZ.Y = *(cmsFloat64Number*)pos_Y;886XYZ.Z = *(cmsFloat64Number*)pos_Z;887888cmsFloat2XYZEncoded(wIn, &XYZ);889890return accum + sizeof(cmsFloat64Number);891892}893894else {895cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum);896accum += sizeof(cmsCIEXYZ) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat64Number);897898return accum;899}900}901902// This is a conversion of XYZ float to 16 bits903static904cmsUInt8Number* UnrollXYZFloatTo16(CMSREGISTER _cmsTRANSFORM* info,905CMSREGISTER cmsUInt16Number wIn[],906CMSREGISTER cmsUInt8Number* accum,907CMSREGISTER cmsUInt32Number Stride)908{909if (T_PLANAR(info -> InputFormat)) {910911cmsCIEXYZ XYZ;912cmsUInt8Number* pos_X;913cmsUInt8Number* pos_Y;914cmsUInt8Number* pos_Z;915916pos_X = accum;917pos_Y = accum + Stride;918pos_Z = accum + Stride * 2;919920XYZ.X = *(cmsFloat32Number*)pos_X;921XYZ.Y = *(cmsFloat32Number*)pos_Y;922XYZ.Z = *(cmsFloat32Number*)pos_Z;923924cmsFloat2XYZEncoded(wIn, &XYZ);925926return accum + sizeof(cmsFloat32Number);927928}929930else {931cmsFloat32Number* Pt = (cmsFloat32Number*) accum;932cmsCIEXYZ XYZ;933934XYZ.X = Pt[0];935XYZ.Y = Pt[1];936XYZ.Z = Pt[2];937cmsFloat2XYZEncoded(wIn, &XYZ);938939accum += 3 * sizeof(cmsFloat32Number) + T_EXTRA(info ->InputFormat) * sizeof(cmsFloat32Number);940941return accum;942}943}944945// Check if space is marked as ink946cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)947{948switch (T_COLORSPACE(Type)) {949950case PT_CMY:951case PT_CMYK:952case PT_MCH5:953case PT_MCH6:954case PT_MCH7:955case PT_MCH8:956case PT_MCH9:957case PT_MCH10:958case PT_MCH11:959case PT_MCH12:960case PT_MCH13:961case PT_MCH14:962case PT_MCH15: return TRUE;963964default: return FALSE;965}966}967968// Return the size in bytes of a given formatter969static970cmsUInt32Number PixelSize(cmsUInt32Number Format)971{972cmsUInt32Number fmt_bytes = T_BYTES(Format);973974// For double, the T_BYTES field is zero975if (fmt_bytes == 0)976return sizeof(cmsUInt64Number);977978// Otherwise, it is already correct for all formats979return fmt_bytes;980}981982// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits983static984cmsUInt8Number* UnrollDoubleTo16(CMSREGISTER _cmsTRANSFORM* info,985CMSREGISTER cmsUInt16Number wIn[],986CMSREGISTER cmsUInt8Number* accum,987CMSREGISTER cmsUInt32Number Stride)988{989990cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);991cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);992cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);993cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);994cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);995cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;996cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);997cmsFloat64Number v;998cmsUInt16Number vi;999cmsUInt32Number i, start = 0;1000cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;100110021003Stride /= PixelSize(info->InputFormat);10041005if (ExtraFirst)1006start = Extra;10071008for (i=0; i < nChan; i++) {10091010cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;10111012if (Planar)1013v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];1014else1015v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[i + start];10161017vi = _cmsQuickSaturateWord(v * maximum);10181019if (Reverse)1020vi = REVERSE_FLAVOR_16(vi);10211022wIn[index] = vi;1023}102410251026if (Extra == 0 && SwapFirst) {1027cmsUInt16Number tmp = wIn[0];10281029memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));1030wIn[nChan-1] = tmp;1031}10321033if (T_PLANAR(info -> InputFormat))1034return accum + sizeof(cmsFloat64Number);1035else1036return accum + (nChan + Extra) * sizeof(cmsFloat64Number);1037}1038103910401041static1042cmsUInt8Number* UnrollFloatTo16(CMSREGISTER _cmsTRANSFORM* info,1043CMSREGISTER cmsUInt16Number wIn[],1044CMSREGISTER cmsUInt8Number* accum,1045CMSREGISTER cmsUInt32Number Stride)1046{10471048cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);1049cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);1050cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);1051cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);1052cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);1053cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;1054cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);1055cmsFloat32Number v;1056cmsUInt16Number vi;1057cmsUInt32Number i, start = 0;1058cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;10591060Stride /= PixelSize(info->InputFormat);10611062if (ExtraFirst)1063start = Extra;10641065for (i=0; i < nChan; i++) {10661067cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;10681069if (Planar)1070v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];1071else1072v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];10731074vi = _cmsQuickSaturateWord(v * maximum);10751076if (Reverse)1077vi = REVERSE_FLAVOR_16(vi);10781079wIn[index] = vi;1080}108110821083if (Extra == 0 && SwapFirst) {1084cmsUInt16Number tmp = wIn[0];10851086memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));1087wIn[nChan-1] = tmp;1088}10891090if (T_PLANAR(info -> InputFormat))1091return accum + sizeof(cmsFloat32Number);1092else1093return accum + (nChan + Extra) * sizeof(cmsFloat32Number);1094}10951096109710981099// For 1 channel, we need to duplicate data (it comes in 0..1.0 range)1100static1101cmsUInt8Number* UnrollDouble1Chan(CMSREGISTER _cmsTRANSFORM* info,1102CMSREGISTER cmsUInt16Number wIn[],1103CMSREGISTER cmsUInt8Number* accum,1104CMSREGISTER cmsUInt32Number Stride)1105{1106cmsFloat64Number* Inks = (cmsFloat64Number*) accum;11071108wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);11091110return accum + sizeof(cmsFloat64Number);11111112cmsUNUSED_PARAMETER(info);1113cmsUNUSED_PARAMETER(Stride);1114}11151116//-------------------------------------------------------------------------------------------------------------------11171118// For anything going from cmsFloat32Number1119static1120cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,1121cmsFloat32Number wIn[],1122cmsUInt8Number* accum,1123cmsUInt32Number Stride)1124{11251126cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);1127cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);1128cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);1129cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);1130cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);1131cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;1132cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);1133cmsFloat32Number v;1134cmsUInt32Number i, start = 0;1135cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;11361137Stride /= PixelSize(info->InputFormat);11381139if (ExtraFirst)1140start = Extra;11411142for (i=0; i < nChan; i++) {11431144cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;11451146if (Planar)1147v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];1148else1149v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];11501151v /= maximum;11521153wIn[index] = Reverse ? 1 - v : v;1154}115511561157if (Extra == 0 && SwapFirst) {1158cmsFloat32Number tmp = wIn[0];11591160memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));1161wIn[nChan-1] = tmp;1162}11631164if (T_PLANAR(info -> InputFormat))1165return accum + sizeof(cmsFloat32Number);1166else1167return accum + (nChan + Extra) * sizeof(cmsFloat32Number);1168}11691170// For anything going from double11711172static1173cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,1174cmsFloat32Number wIn[],1175cmsUInt8Number* accum,1176cmsUInt32Number Stride)1177{11781179cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);1180cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);1181cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);1182cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);1183cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);1184cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;1185cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);1186cmsFloat64Number v;1187cmsUInt32Number i, start = 0;1188cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;11891190Stride /= PixelSize(info->InputFormat);11911192if (ExtraFirst)1193start = Extra;11941195for (i=0; i < nChan; i++) {11961197cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;11981199if (Planar)1200v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];1201else1202v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];12031204v /= maximum;12051206wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);1207}120812091210if (Extra == 0 && SwapFirst) {1211cmsFloat32Number tmp = wIn[0];12121213memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));1214wIn[nChan-1] = tmp;1215}12161217if (T_PLANAR(info -> InputFormat))1218return accum + sizeof(cmsFloat64Number);1219else1220return accum + (nChan + Extra) * sizeof(cmsFloat64Number);1221}1222122312241225// From Lab double to cmsFloat32Number1226static1227cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info,1228cmsFloat32Number wIn[],1229cmsUInt8Number* accum,1230cmsUInt32Number Stride)1231{1232cmsFloat64Number* Pt = (cmsFloat64Number*) accum;12331234if (T_PLANAR(info -> InputFormat)) {12351236Stride /= PixelSize(info->InputFormat);12371238wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..11239wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..11240wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);12411242return accum + sizeof(cmsFloat64Number);1243}1244else {12451246wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..11247wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..11248wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);12491250accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));1251return accum;1252}1253}12541255// From Lab double to cmsFloat32Number1256static1257cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,1258cmsFloat32Number wIn[],1259cmsUInt8Number* accum,1260cmsUInt32Number Stride)1261{1262cmsFloat32Number* Pt = (cmsFloat32Number*) accum;12631264if (T_PLANAR(info -> InputFormat)) {12651266Stride /= PixelSize(info->InputFormat);12671268wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..11269wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0); // form -128..+127 to 0..11270wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);12711272return accum + sizeof(cmsFloat32Number);1273}1274else {12751276wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0); // from 0..100 to 0..11277wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0); // form -128..+127 to 0..11278wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);12791280accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));1281return accum;1282}1283}1284128512861287// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)1288static1289cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,1290cmsFloat32Number wIn[],1291cmsUInt8Number* accum,1292cmsUInt32Number Stride)1293{1294cmsFloat64Number* Pt = (cmsFloat64Number*) accum;12951296if (T_PLANAR(info -> InputFormat)) {12971298Stride /= PixelSize(info->InputFormat);12991300wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);1301wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);1302wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);13031304return accum + sizeof(cmsFloat64Number);1305}1306else {13071308wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);1309wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);1310wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);13111312accum += sizeof(cmsFloat64Number)*(3 + T_EXTRA(info ->InputFormat));1313return accum;1314}1315}13161317static1318cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,1319cmsFloat32Number wIn[],1320cmsUInt8Number* accum,1321cmsUInt32Number Stride)1322{1323cmsFloat32Number* Pt = (cmsFloat32Number*) accum;13241325if (T_PLANAR(info -> InputFormat)) {13261327Stride /= PixelSize(info->InputFormat);13281329wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);1330wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);1331wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);13321333return accum + sizeof(cmsFloat32Number);1334}1335else {13361337wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);1338wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);1339wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);13401341accum += sizeof(cmsFloat32Number)*(3 + T_EXTRA(info ->InputFormat));1342return accum;1343}1344}1345134613471348// Packing routines -----------------------------------------------------------------------------------------------------------134913501351// Generic chunky for byte13521353static1354cmsUInt8Number* PackAnyBytes(CMSREGISTER _cmsTRANSFORM* info,1355CMSREGISTER cmsUInt16Number wOut[],1356CMSREGISTER cmsUInt8Number* output,1357CMSREGISTER cmsUInt32Number Stride)1358{1359cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);1360cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);1361cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);1362cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat);1363cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat);1364cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;1365cmsUInt8Number* swap1;1366cmsUInt8Number v = 0;1367cmsUInt32Number i;13681369swap1 = output;13701371if (ExtraFirst) {1372output += Extra;1373}13741375for (i=0; i < nChan; i++) {13761377cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;13781379v = FROM_16_TO_8(wOut[index]);13801381if (Reverse)1382v = REVERSE_FLAVOR_8(v);13831384*output++ = v;1385}13861387if (!ExtraFirst) {1388output += Extra;1389}13901391if (Extra == 0 && SwapFirst) {13921393memmove(swap1 + 1, swap1, nChan-1);1394*swap1 = v;1395}139613971398return output;13991400cmsUNUSED_PARAMETER(Stride);1401}1402140314041405static1406cmsUInt8Number* PackAnyWords(CMSREGISTER _cmsTRANSFORM* info,1407CMSREGISTER cmsUInt16Number wOut[],1408CMSREGISTER cmsUInt8Number* output,1409CMSREGISTER cmsUInt32Number Stride)1410{1411cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);1412cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat);1413cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);1414cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);1415cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat);1416cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat);1417cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;1418cmsUInt16Number* swap1;1419cmsUInt16Number v = 0;1420cmsUInt32Number i;14211422swap1 = (cmsUInt16Number*) output;14231424if (ExtraFirst) {1425output += Extra * sizeof(cmsUInt16Number);1426}14271428for (i=0; i < nChan; i++) {14291430cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;14311432v = wOut[index];14331434if (SwapEndian)1435v = CHANGE_ENDIAN(v);14361437if (Reverse)1438v = REVERSE_FLAVOR_16(v);14391440*(cmsUInt16Number*) output = v;14411442output += sizeof(cmsUInt16Number);1443}14441445if (!ExtraFirst) {1446output += Extra * sizeof(cmsUInt16Number);1447}14481449if (Extra == 0 && SwapFirst) {14501451memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));1452*swap1 = v;1453}145414551456return output;14571458cmsUNUSED_PARAMETER(Stride);1459}146014611462static1463cmsUInt8Number* PackPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,1464CMSREGISTER cmsUInt16Number wOut[],1465CMSREGISTER cmsUInt8Number* output,1466CMSREGISTER cmsUInt32Number Stride)1467{1468cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);1469cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);1470cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->OutputFormat);1471cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);1472cmsUInt32Number i;1473cmsUInt8Number* Init = output;147414751476if (DoSwap ^ SwapFirst) {1477output += T_EXTRA(info -> OutputFormat) * Stride;1478}147914801481for (i=0; i < nChan; i++) {14821483cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;1484cmsUInt8Number v = FROM_16_TO_8(wOut[index]);14851486*(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v);1487output += Stride;1488}14891490return (Init + 1);14911492cmsUNUSED_PARAMETER(Stride);1493}149414951496static1497cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info,1498CMSREGISTER cmsUInt16Number wOut[],1499CMSREGISTER cmsUInt8Number* output,1500CMSREGISTER cmsUInt32Number Stride)1501{1502cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);1503cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);1504cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);1505cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat);1506cmsUInt32Number i;1507cmsUInt8Number* Init = output;1508cmsUInt16Number v;15091510if (DoSwap) {1511output += T_EXTRA(info -> OutputFormat) * Stride;1512}15131514for (i=0; i < nChan; i++) {15151516cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;15171518v = wOut[index];15191520if (SwapEndian)1521v = CHANGE_ENDIAN(v);15221523if (Reverse)1524v = REVERSE_FLAVOR_16(v);15251526*(cmsUInt16Number*) output = v;1527output += Stride;1528}15291530return (Init + sizeof(cmsUInt16Number));1531}15321533// CMYKcm (unrolled for speed)15341535static1536cmsUInt8Number* Pack6Bytes(CMSREGISTER _cmsTRANSFORM* info,1537CMSREGISTER cmsUInt16Number wOut[],1538CMSREGISTER cmsUInt8Number* output,1539CMSREGISTER cmsUInt32Number Stride)1540{1541*output++ = FROM_16_TO_8(wOut[0]);1542*output++ = FROM_16_TO_8(wOut[1]);1543*output++ = FROM_16_TO_8(wOut[2]);1544*output++ = FROM_16_TO_8(wOut[3]);1545*output++ = FROM_16_TO_8(wOut[4]);1546*output++ = FROM_16_TO_8(wOut[5]);15471548return output;15491550cmsUNUSED_PARAMETER(info);1551cmsUNUSED_PARAMETER(Stride);1552}15531554// KCMYcm15551556static1557cmsUInt8Number* Pack6BytesSwap(CMSREGISTER _cmsTRANSFORM* info,1558CMSREGISTER cmsUInt16Number wOut[],1559CMSREGISTER cmsUInt8Number* output,1560CMSREGISTER cmsUInt32Number Stride)1561{1562*output++ = FROM_16_TO_8(wOut[5]);1563*output++ = FROM_16_TO_8(wOut[4]);1564*output++ = FROM_16_TO_8(wOut[3]);1565*output++ = FROM_16_TO_8(wOut[2]);1566*output++ = FROM_16_TO_8(wOut[1]);1567*output++ = FROM_16_TO_8(wOut[0]);15681569return output;15701571cmsUNUSED_PARAMETER(info);1572cmsUNUSED_PARAMETER(Stride);1573}15741575// CMYKcm1576static1577cmsUInt8Number* Pack6Words(CMSREGISTER _cmsTRANSFORM* info,1578CMSREGISTER cmsUInt16Number wOut[],1579CMSREGISTER cmsUInt8Number* output,1580CMSREGISTER cmsUInt32Number Stride)1581{1582*(cmsUInt16Number*) output = wOut[0];1583output+= 2;1584*(cmsUInt16Number*) output = wOut[1];1585output+= 2;1586*(cmsUInt16Number*) output = wOut[2];1587output+= 2;1588*(cmsUInt16Number*) output = wOut[3];1589output+= 2;1590*(cmsUInt16Number*) output = wOut[4];1591output+= 2;1592*(cmsUInt16Number*) output = wOut[5];1593output+= 2;15941595return output;15961597cmsUNUSED_PARAMETER(info);1598cmsUNUSED_PARAMETER(Stride);1599}16001601// KCMYcm1602static1603cmsUInt8Number* Pack6WordsSwap(CMSREGISTER _cmsTRANSFORM* info,1604CMSREGISTER cmsUInt16Number wOut[],1605CMSREGISTER cmsUInt8Number* output,1606CMSREGISTER cmsUInt32Number Stride)1607{1608*(cmsUInt16Number*) output = wOut[5];1609output+= 2;1610*(cmsUInt16Number*) output = wOut[4];1611output+= 2;1612*(cmsUInt16Number*) output = wOut[3];1613output+= 2;1614*(cmsUInt16Number*) output = wOut[2];1615output+= 2;1616*(cmsUInt16Number*) output = wOut[1];1617output+= 2;1618*(cmsUInt16Number*) output = wOut[0];1619output+= 2;16201621return output;16221623cmsUNUSED_PARAMETER(info);1624cmsUNUSED_PARAMETER(Stride);1625}162616271628static1629cmsUInt8Number* Pack4Bytes(CMSREGISTER _cmsTRANSFORM* info,1630CMSREGISTER cmsUInt16Number wOut[],1631CMSREGISTER cmsUInt8Number* output,1632CMSREGISTER cmsUInt32Number Stride)1633{1634*output++ = FROM_16_TO_8(wOut[0]);1635*output++ = FROM_16_TO_8(wOut[1]);1636*output++ = FROM_16_TO_8(wOut[2]);1637*output++ = FROM_16_TO_8(wOut[3]);16381639return output;16401641cmsUNUSED_PARAMETER(info);1642cmsUNUSED_PARAMETER(Stride);1643}16441645static1646cmsUInt8Number* Pack4BytesReverse(CMSREGISTER _cmsTRANSFORM* info,1647CMSREGISTER cmsUInt16Number wOut[],1648CMSREGISTER cmsUInt8Number* output,1649CMSREGISTER cmsUInt32Number Stride)1650{1651*output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));1652*output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));1653*output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));1654*output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));16551656return output;16571658cmsUNUSED_PARAMETER(info);1659cmsUNUSED_PARAMETER(Stride);1660}166116621663static1664cmsUInt8Number* Pack4BytesSwapFirst(CMSREGISTER _cmsTRANSFORM* info,1665CMSREGISTER cmsUInt16Number wOut[],1666CMSREGISTER cmsUInt8Number* output,1667CMSREGISTER cmsUInt32Number Stride)1668{1669*output++ = FROM_16_TO_8(wOut[3]);1670*output++ = FROM_16_TO_8(wOut[0]);1671*output++ = FROM_16_TO_8(wOut[1]);1672*output++ = FROM_16_TO_8(wOut[2]);16731674return output;16751676cmsUNUSED_PARAMETER(info);1677cmsUNUSED_PARAMETER(Stride);1678}16791680// ABGR1681static1682cmsUInt8Number* Pack4BytesSwap(CMSREGISTER _cmsTRANSFORM* info,1683CMSREGISTER cmsUInt16Number wOut[],1684CMSREGISTER cmsUInt8Number* output,1685CMSREGISTER cmsUInt32Number Stride)1686{1687*output++ = FROM_16_TO_8(wOut[3]);1688*output++ = FROM_16_TO_8(wOut[2]);1689*output++ = FROM_16_TO_8(wOut[1]);1690*output++ = FROM_16_TO_8(wOut[0]);16911692return output;16931694cmsUNUSED_PARAMETER(info);1695cmsUNUSED_PARAMETER(Stride);1696}16971698static1699cmsUInt8Number* Pack4BytesSwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,1700CMSREGISTER cmsUInt16Number wOut[],1701CMSREGISTER cmsUInt8Number* output,1702CMSREGISTER cmsUInt32Number Stride)1703{1704*output++ = FROM_16_TO_8(wOut[2]);1705*output++ = FROM_16_TO_8(wOut[1]);1706*output++ = FROM_16_TO_8(wOut[0]);1707*output++ = FROM_16_TO_8(wOut[3]);17081709return output;17101711cmsUNUSED_PARAMETER(info);1712cmsUNUSED_PARAMETER(Stride);1713}17141715static1716cmsUInt8Number* Pack4Words(CMSREGISTER _cmsTRANSFORM* info,1717CMSREGISTER cmsUInt16Number wOut[],1718CMSREGISTER cmsUInt8Number* output,1719CMSREGISTER cmsUInt32Number Stride)1720{1721*(cmsUInt16Number*) output = wOut[0];1722output+= 2;1723*(cmsUInt16Number*) output = wOut[1];1724output+= 2;1725*(cmsUInt16Number*) output = wOut[2];1726output+= 2;1727*(cmsUInt16Number*) output = wOut[3];1728output+= 2;17291730return output;17311732cmsUNUSED_PARAMETER(info);1733cmsUNUSED_PARAMETER(Stride);1734}17351736static1737cmsUInt8Number* Pack4WordsReverse(CMSREGISTER _cmsTRANSFORM* info,1738CMSREGISTER cmsUInt16Number wOut[],1739CMSREGISTER cmsUInt8Number* output,1740CMSREGISTER cmsUInt32Number Stride)1741{1742*(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);1743output+= 2;1744*(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);1745output+= 2;1746*(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);1747output+= 2;1748*(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);1749output+= 2;17501751return output;17521753cmsUNUSED_PARAMETER(info);1754cmsUNUSED_PARAMETER(Stride);1755}17561757// ABGR1758static1759cmsUInt8Number* Pack4WordsSwap(CMSREGISTER _cmsTRANSFORM* info,1760CMSREGISTER cmsUInt16Number wOut[],1761CMSREGISTER cmsUInt8Number* output,1762CMSREGISTER cmsUInt32Number Stride)1763{1764*(cmsUInt16Number*) output = wOut[3];1765output+= 2;1766*(cmsUInt16Number*) output = wOut[2];1767output+= 2;1768*(cmsUInt16Number*) output = wOut[1];1769output+= 2;1770*(cmsUInt16Number*) output = wOut[0];1771output+= 2;17721773return output;17741775cmsUNUSED_PARAMETER(info);1776cmsUNUSED_PARAMETER(Stride);1777}17781779// CMYK1780static1781cmsUInt8Number* Pack4WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info,1782CMSREGISTER cmsUInt16Number wOut[],1783CMSREGISTER cmsUInt8Number* output,1784CMSREGISTER cmsUInt32Number Stride)1785{1786*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);1787output+= 2;1788*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);1789output+= 2;1790*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);1791output+= 2;1792*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);1793output+= 2;17941795return output;17961797cmsUNUSED_PARAMETER(info);1798cmsUNUSED_PARAMETER(Stride);1799}180018011802static1803cmsUInt8Number* PackLabV2_8(CMSREGISTER _cmsTRANSFORM* info,1804CMSREGISTER cmsUInt16Number wOut[],1805CMSREGISTER cmsUInt8Number* output,1806CMSREGISTER cmsUInt32Number Stride)1807{1808*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));1809*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));1810*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));18111812return output;18131814cmsUNUSED_PARAMETER(info);1815cmsUNUSED_PARAMETER(Stride);1816}18171818static1819cmsUInt8Number* PackALabV2_8(CMSREGISTER _cmsTRANSFORM* info,1820CMSREGISTER cmsUInt16Number wOut[],1821CMSREGISTER cmsUInt8Number* output,1822CMSREGISTER cmsUInt32Number Stride)1823{1824output++;1825*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));1826*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));1827*output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));18281829return output;18301831cmsUNUSED_PARAMETER(info);1832cmsUNUSED_PARAMETER(Stride);1833}18341835static1836cmsUInt8Number* PackLabV2_16(CMSREGISTER _cmsTRANSFORM* info,1837CMSREGISTER cmsUInt16Number wOut[],1838CMSREGISTER cmsUInt8Number* output,1839CMSREGISTER cmsUInt32Number Stride)1840{1841*(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);1842output += 2;1843*(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);1844output += 2;1845*(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);1846output += 2;18471848return output;18491850cmsUNUSED_PARAMETER(info);1851cmsUNUSED_PARAMETER(Stride);1852}18531854static1855cmsUInt8Number* Pack3Bytes(CMSREGISTER _cmsTRANSFORM* info,1856CMSREGISTER cmsUInt16Number wOut[],1857CMSREGISTER cmsUInt8Number* output,1858CMSREGISTER cmsUInt32Number Stride)1859{1860*output++ = FROM_16_TO_8(wOut[0]);1861*output++ = FROM_16_TO_8(wOut[1]);1862*output++ = FROM_16_TO_8(wOut[2]);18631864return output;18651866cmsUNUSED_PARAMETER(info);1867cmsUNUSED_PARAMETER(Stride);1868}18691870static1871cmsUInt8Number* Pack3BytesOptimized(CMSREGISTER _cmsTRANSFORM* info,1872CMSREGISTER cmsUInt16Number wOut[],1873CMSREGISTER cmsUInt8Number* output,1874CMSREGISTER cmsUInt32Number Stride)1875{1876*output++ = (wOut[0] & 0xFFU);1877*output++ = (wOut[1] & 0xFFU);1878*output++ = (wOut[2] & 0xFFU);18791880return output;18811882cmsUNUSED_PARAMETER(info);1883cmsUNUSED_PARAMETER(Stride);1884}18851886static1887cmsUInt8Number* Pack3BytesSwap(CMSREGISTER _cmsTRANSFORM* info,1888CMSREGISTER cmsUInt16Number wOut[],1889CMSREGISTER cmsUInt8Number* output,1890CMSREGISTER cmsUInt32Number Stride)1891{1892*output++ = FROM_16_TO_8(wOut[2]);1893*output++ = FROM_16_TO_8(wOut[1]);1894*output++ = FROM_16_TO_8(wOut[0]);18951896return output;18971898cmsUNUSED_PARAMETER(info);1899cmsUNUSED_PARAMETER(Stride);1900}19011902static1903cmsUInt8Number* Pack3BytesSwapOptimized(CMSREGISTER _cmsTRANSFORM* info,1904CMSREGISTER cmsUInt16Number wOut[],1905CMSREGISTER cmsUInt8Number* output,1906CMSREGISTER cmsUInt32Number Stride)1907{1908*output++ = (wOut[2] & 0xFFU);1909*output++ = (wOut[1] & 0xFFU);1910*output++ = (wOut[0] & 0xFFU);19111912return output;19131914cmsUNUSED_PARAMETER(info);1915cmsUNUSED_PARAMETER(Stride);1916}191719181919static1920cmsUInt8Number* Pack3Words(CMSREGISTER _cmsTRANSFORM* info,1921CMSREGISTER cmsUInt16Number wOut[],1922CMSREGISTER cmsUInt8Number* output,1923CMSREGISTER cmsUInt32Number Stride)1924{1925*(cmsUInt16Number*) output = wOut[0];1926output+= 2;1927*(cmsUInt16Number*) output = wOut[1];1928output+= 2;1929*(cmsUInt16Number*) output = wOut[2];1930output+= 2;19311932return output;19331934cmsUNUSED_PARAMETER(info);1935cmsUNUSED_PARAMETER(Stride);1936}19371938static1939cmsUInt8Number* Pack3WordsSwap(CMSREGISTER _cmsTRANSFORM* info,1940CMSREGISTER cmsUInt16Number wOut[],1941CMSREGISTER cmsUInt8Number* output,1942CMSREGISTER cmsUInt32Number Stride)1943{1944*(cmsUInt16Number*) output = wOut[2];1945output+= 2;1946*(cmsUInt16Number*) output = wOut[1];1947output+= 2;1948*(cmsUInt16Number*) output = wOut[0];1949output+= 2;19501951return output;19521953cmsUNUSED_PARAMETER(info);1954cmsUNUSED_PARAMETER(Stride);1955}19561957static1958cmsUInt8Number* Pack3WordsBigEndian(CMSREGISTER _cmsTRANSFORM* info,1959CMSREGISTER cmsUInt16Number wOut[],1960CMSREGISTER cmsUInt8Number* output,1961CMSREGISTER cmsUInt32Number Stride)1962{1963*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);1964output+= 2;1965*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);1966output+= 2;1967*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);1968output+= 2;19691970return output;19711972cmsUNUSED_PARAMETER(info);1973cmsUNUSED_PARAMETER(Stride);1974}19751976static1977cmsUInt8Number* Pack3BytesAndSkip1(CMSREGISTER _cmsTRANSFORM* info,1978CMSREGISTER cmsUInt16Number wOut[],1979CMSREGISTER cmsUInt8Number* output,1980CMSREGISTER cmsUInt32Number Stride)1981{1982*output++ = FROM_16_TO_8(wOut[0]);1983*output++ = FROM_16_TO_8(wOut[1]);1984*output++ = FROM_16_TO_8(wOut[2]);1985output++;19861987return output;19881989cmsUNUSED_PARAMETER(info);1990cmsUNUSED_PARAMETER(Stride);1991}19921993static1994cmsUInt8Number* Pack3BytesAndSkip1Optimized(CMSREGISTER _cmsTRANSFORM* info,1995CMSREGISTER cmsUInt16Number wOut[],1996CMSREGISTER cmsUInt8Number* output,1997CMSREGISTER cmsUInt32Number Stride)1998{1999*output++ = (wOut[0] & 0xFFU);2000*output++ = (wOut[1] & 0xFFU);2001*output++ = (wOut[2] & 0xFFU);2002output++;20032004return output;20052006cmsUNUSED_PARAMETER(info);2007cmsUNUSED_PARAMETER(Stride);2008}200920102011static2012cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,2013CMSREGISTER cmsUInt16Number wOut[],2014CMSREGISTER cmsUInt8Number* output,2015CMSREGISTER cmsUInt32Number Stride)2016{2017output++;2018*output++ = FROM_16_TO_8(wOut[0]);2019*output++ = FROM_16_TO_8(wOut[1]);2020*output++ = FROM_16_TO_8(wOut[2]);20212022return output;20232024cmsUNUSED_PARAMETER(info);2025cmsUNUSED_PARAMETER(Stride);2026}20272028static2029cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info,2030CMSREGISTER cmsUInt16Number wOut[],2031CMSREGISTER cmsUInt8Number* output,2032CMSREGISTER cmsUInt32Number Stride)2033{2034output++;2035*output++ = (wOut[0] & 0xFFU);2036*output++ = (wOut[1] & 0xFFU);2037*output++ = (wOut[2] & 0xFFU);20382039return output;20402041cmsUNUSED_PARAMETER(info);2042cmsUNUSED_PARAMETER(Stride);2043}20442045static2046cmsUInt8Number* Pack3BytesAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,2047CMSREGISTER cmsUInt16Number wOut[],2048CMSREGISTER cmsUInt8Number* output,2049CMSREGISTER cmsUInt32Number Stride)2050{2051output++;2052*output++ = FROM_16_TO_8(wOut[2]);2053*output++ = FROM_16_TO_8(wOut[1]);2054*output++ = FROM_16_TO_8(wOut[0]);20552056return output;20572058cmsUNUSED_PARAMETER(info);2059cmsUNUSED_PARAMETER(Stride);2060}20612062static2063cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(CMSREGISTER _cmsTRANSFORM* info,2064CMSREGISTER cmsUInt16Number wOut[],2065CMSREGISTER cmsUInt8Number* output,2066CMSREGISTER cmsUInt32Number Stride)2067{2068output++;2069*output++ = (wOut[2] & 0xFFU);2070*output++ = (wOut[1] & 0xFFU);2071*output++ = (wOut[0] & 0xFFU);20722073return output;20742075cmsUNUSED_PARAMETER(info);2076cmsUNUSED_PARAMETER(Stride);2077}207820792080static2081cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,2082CMSREGISTER cmsUInt16Number wOut[],2083CMSREGISTER cmsUInt8Number* output,2084CMSREGISTER cmsUInt32Number Stride)2085{2086*output++ = FROM_16_TO_8(wOut[2]);2087*output++ = FROM_16_TO_8(wOut[1]);2088*output++ = FROM_16_TO_8(wOut[0]);2089output++;20902091return output;20922093cmsUNUSED_PARAMETER(info);2094cmsUNUSED_PARAMETER(Stride);2095}20962097static2098cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(CMSREGISTER _cmsTRANSFORM* info,2099CMSREGISTER cmsUInt16Number wOut[],2100CMSREGISTER cmsUInt8Number* output,2101CMSREGISTER cmsUInt32Number Stride)2102{2103*output++ = (wOut[2] & 0xFFU);2104*output++ = (wOut[1] & 0xFFU);2105*output++ = (wOut[0] & 0xFFU);2106output++;21072108return output;21092110cmsUNUSED_PARAMETER(info);2111cmsUNUSED_PARAMETER(Stride);2112}21132114static2115cmsUInt8Number* Pack3WordsAndSkip1(CMSREGISTER _cmsTRANSFORM* info,2116CMSREGISTER cmsUInt16Number wOut[],2117CMSREGISTER cmsUInt8Number* output,2118CMSREGISTER cmsUInt32Number Stride)2119{2120*(cmsUInt16Number*) output = wOut[0];2121output+= 2;2122*(cmsUInt16Number*) output = wOut[1];2123output+= 2;2124*(cmsUInt16Number*) output = wOut[2];2125output+= 2;2126output+= 2;21272128return output;21292130cmsUNUSED_PARAMETER(info);2131cmsUNUSED_PARAMETER(Stride);2132}21332134static2135cmsUInt8Number* Pack3WordsAndSkip1Swap(CMSREGISTER _cmsTRANSFORM* info,2136CMSREGISTER cmsUInt16Number wOut[],2137CMSREGISTER cmsUInt8Number* output,2138CMSREGISTER cmsUInt32Number Stride)2139{2140output+= 2;2141*(cmsUInt16Number*) output = wOut[2];2142output+= 2;2143*(cmsUInt16Number*) output = wOut[1];2144output+= 2;2145*(cmsUInt16Number*) output = wOut[0];2146output+= 2;21472148return output;21492150cmsUNUSED_PARAMETER(info);2151cmsUNUSED_PARAMETER(Stride);2152}215321542155static2156cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,2157CMSREGISTER cmsUInt16Number wOut[],2158CMSREGISTER cmsUInt8Number* output,2159CMSREGISTER cmsUInt32Number Stride)2160{2161output+= 2;2162*(cmsUInt16Number*) output = wOut[0];2163output+= 2;2164*(cmsUInt16Number*) output = wOut[1];2165output+= 2;2166*(cmsUInt16Number*) output = wOut[2];2167output+= 2;21682169return output;21702171cmsUNUSED_PARAMETER(info);2172cmsUNUSED_PARAMETER(Stride);2173}217421752176static2177cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(CMSREGISTER _cmsTRANSFORM* info,2178CMSREGISTER cmsUInt16Number wOut[],2179CMSREGISTER cmsUInt8Number* output,2180CMSREGISTER cmsUInt32Number Stride)2181{2182*(cmsUInt16Number*) output = wOut[2];2183output+= 2;2184*(cmsUInt16Number*) output = wOut[1];2185output+= 2;2186*(cmsUInt16Number*) output = wOut[0];2187output+= 2;2188output+= 2;21892190return output;21912192cmsUNUSED_PARAMETER(info);2193cmsUNUSED_PARAMETER(Stride);2194}2195219621972198static2199cmsUInt8Number* Pack1Byte(CMSREGISTER _cmsTRANSFORM* info,2200CMSREGISTER cmsUInt16Number wOut[],2201CMSREGISTER cmsUInt8Number* output,2202CMSREGISTER cmsUInt32Number Stride)2203{2204*output++ = FROM_16_TO_8(wOut[0]);22052206return output;22072208cmsUNUSED_PARAMETER(info);2209cmsUNUSED_PARAMETER(Stride);2210}221122122213static2214cmsUInt8Number* Pack1ByteReversed(CMSREGISTER _cmsTRANSFORM* info,2215CMSREGISTER cmsUInt16Number wOut[],2216CMSREGISTER cmsUInt8Number* output,2217CMSREGISTER cmsUInt32Number Stride)2218{2219*output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));22202221return output;22222223cmsUNUSED_PARAMETER(info);2224cmsUNUSED_PARAMETER(Stride);2225}222622272228static2229cmsUInt8Number* Pack1ByteSkip1(CMSREGISTER _cmsTRANSFORM* info,2230CMSREGISTER cmsUInt16Number wOut[],2231CMSREGISTER cmsUInt8Number* output,2232CMSREGISTER cmsUInt32Number Stride)2233{2234*output++ = FROM_16_TO_8(wOut[0]);2235output++;22362237return output;22382239cmsUNUSED_PARAMETER(info);2240cmsUNUSED_PARAMETER(Stride);2241}224222432244static2245cmsUInt8Number* Pack1ByteSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,2246CMSREGISTER cmsUInt16Number wOut[],2247CMSREGISTER cmsUInt8Number* output,2248CMSREGISTER cmsUInt32Number Stride)2249{2250output++;2251*output++ = FROM_16_TO_8(wOut[0]);22522253return output;22542255cmsUNUSED_PARAMETER(info);2256cmsUNUSED_PARAMETER(Stride);2257}22582259static2260cmsUInt8Number* Pack1Word(CMSREGISTER _cmsTRANSFORM* info,2261CMSREGISTER cmsUInt16Number wOut[],2262CMSREGISTER cmsUInt8Number* output,2263CMSREGISTER cmsUInt32Number Stride)2264{2265*(cmsUInt16Number*) output = wOut[0];2266output+= 2;22672268return output;22692270cmsUNUSED_PARAMETER(info);2271cmsUNUSED_PARAMETER(Stride);2272}227322742275static2276cmsUInt8Number* Pack1WordReversed(CMSREGISTER _cmsTRANSFORM* info,2277CMSREGISTER cmsUInt16Number wOut[],2278CMSREGISTER cmsUInt8Number* output,2279CMSREGISTER cmsUInt32Number Stride)2280{2281*(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);2282output+= 2;22832284return output;22852286cmsUNUSED_PARAMETER(info);2287cmsUNUSED_PARAMETER(Stride);2288}22892290static2291cmsUInt8Number* Pack1WordBigEndian(CMSREGISTER _cmsTRANSFORM* info,2292CMSREGISTER cmsUInt16Number wOut[],2293CMSREGISTER cmsUInt8Number* output,2294CMSREGISTER cmsUInt32Number Stride)2295{2296*(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);2297output+= 2;22982299return output;23002301cmsUNUSED_PARAMETER(info);2302cmsUNUSED_PARAMETER(Stride);2303}230423052306static2307cmsUInt8Number* Pack1WordSkip1(CMSREGISTER _cmsTRANSFORM* info,2308CMSREGISTER cmsUInt16Number wOut[],2309CMSREGISTER cmsUInt8Number* output,2310CMSREGISTER cmsUInt32Number Stride)2311{2312*(cmsUInt16Number*) output = wOut[0];2313output+= 4;23142315return output;23162317cmsUNUSED_PARAMETER(info);2318cmsUNUSED_PARAMETER(Stride);2319}23202321static2322cmsUInt8Number* Pack1WordSkip1SwapFirst(CMSREGISTER _cmsTRANSFORM* info,2323CMSREGISTER cmsUInt16Number wOut[],2324CMSREGISTER cmsUInt8Number* output,2325CMSREGISTER cmsUInt32Number Stride)2326{2327output += 2;2328*(cmsUInt16Number*) output = wOut[0];2329output+= 2;23302331return output;23322333cmsUNUSED_PARAMETER(info);2334cmsUNUSED_PARAMETER(Stride);2335}233623372338// Unencoded Float values -- don't try optimize speed2339static2340cmsUInt8Number* PackLabDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info,2341CMSREGISTER cmsUInt16Number wOut[],2342CMSREGISTER cmsUInt8Number* output,2343CMSREGISTER cmsUInt32Number Stride)2344{23452346if (T_PLANAR(info -> OutputFormat)) {23472348cmsCIELab Lab;2349cmsFloat64Number* Out = (cmsFloat64Number*) output;2350cmsLabEncoded2Float(&Lab, wOut);23512352Out[0] = Lab.L;2353Out[Stride] = Lab.a;2354Out[Stride*2] = Lab.b;23552356return output + sizeof(cmsFloat64Number);2357}2358else {23592360cmsLabEncoded2Float((cmsCIELab*) output, wOut);2361return output + (sizeof(cmsCIELab) + T_EXTRA(info ->OutputFormat) * sizeof(cmsFloat64Number));2362}2363}236423652366static2367cmsUInt8Number* PackLabFloatFrom16(CMSREGISTER _cmsTRANSFORM* info,2368CMSREGISTER cmsUInt16Number wOut[],2369CMSREGISTER cmsUInt8Number* output,2370CMSREGISTER cmsUInt32Number Stride)2371{2372cmsCIELab Lab;2373cmsLabEncoded2Float(&Lab, wOut);23742375if (T_PLANAR(info -> OutputFormat)) {23762377cmsFloat32Number* Out = (cmsFloat32Number*) output;23782379Stride /= PixelSize(info->OutputFormat);23802381Out[0] = (cmsFloat32Number)Lab.L;2382Out[Stride] = (cmsFloat32Number)Lab.a;2383Out[Stride*2] = (cmsFloat32Number)Lab.b;23842385return output + sizeof(cmsFloat32Number);2386}2387else {23882389((cmsFloat32Number*) output)[0] = (cmsFloat32Number) Lab.L;2390((cmsFloat32Number*) output)[1] = (cmsFloat32Number) Lab.a;2391((cmsFloat32Number*) output)[2] = (cmsFloat32Number) Lab.b;23922393return output + (3 + T_EXTRA(info ->OutputFormat)) * sizeof(cmsFloat32Number);2394}2395}23962397static2398cmsUInt8Number* PackXYZDoubleFrom16(CMSREGISTER _cmsTRANSFORM* Info,2399CMSREGISTER cmsUInt16Number wOut[],2400CMSREGISTER cmsUInt8Number* output,2401CMSREGISTER cmsUInt32Number Stride)2402{2403if (T_PLANAR(Info -> OutputFormat)) {24042405cmsCIEXYZ XYZ;2406cmsFloat64Number* Out = (cmsFloat64Number*) output;2407cmsXYZEncoded2Float(&XYZ, wOut);24082409Stride /= PixelSize(Info->OutputFormat);24102411Out[0] = XYZ.X;2412Out[Stride] = XYZ.Y;2413Out[Stride*2] = XYZ.Z;24142415return output + sizeof(cmsFloat64Number);24162417}2418else {24192420cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut);24212422return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));2423}2424}24252426static2427cmsUInt8Number* PackXYZFloatFrom16(CMSREGISTER _cmsTRANSFORM* Info,2428CMSREGISTER cmsUInt16Number wOut[],2429CMSREGISTER cmsUInt8Number* output,2430CMSREGISTER cmsUInt32Number Stride)2431{2432if (T_PLANAR(Info -> OutputFormat)) {24332434cmsCIEXYZ XYZ;2435cmsFloat32Number* Out = (cmsFloat32Number*) output;2436cmsXYZEncoded2Float(&XYZ, wOut);24372438Stride /= PixelSize(Info->OutputFormat);24392440Out[0] = (cmsFloat32Number) XYZ.X;2441Out[Stride] = (cmsFloat32Number) XYZ.Y;2442Out[Stride*2] = (cmsFloat32Number) XYZ.Z;24432444return output + sizeof(cmsFloat32Number);24452446}2447else {24482449cmsCIEXYZ XYZ;2450cmsFloat32Number* Out = (cmsFloat32Number*) output;2451cmsXYZEncoded2Float(&XYZ, wOut);24522453Out[0] = (cmsFloat32Number) XYZ.X;2454Out[1] = (cmsFloat32Number) XYZ.Y;2455Out[2] = (cmsFloat32Number) XYZ.Z;24562457return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));2458}2459}24602461static2462cmsUInt8Number* PackDoubleFrom16(CMSREGISTER _cmsTRANSFORM* info,2463CMSREGISTER cmsUInt16Number wOut[],2464CMSREGISTER cmsUInt8Number* output,2465CMSREGISTER cmsUInt32Number Stride)2466{2467cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);2468cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);2469cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);2470cmsUInt32Number Extra = T_EXTRA(info -> OutputFormat);2471cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> OutputFormat);2472cmsUInt32Number Planar = T_PLANAR(info -> OutputFormat);2473cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2474cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;2475cmsFloat64Number v = 0;2476cmsFloat64Number* swap1 = (cmsFloat64Number*) output;2477cmsUInt32Number i, start = 0;24782479Stride /= PixelSize(info->OutputFormat);24802481if (ExtraFirst)2482start = Extra;24832484for (i=0; i < nChan; i++) {24852486cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;24872488v = (cmsFloat64Number) wOut[index] / maximum;24892490if (Reverse)2491v = maximum - v;24922493if (Planar)2494((cmsFloat64Number*) output)[(i + start) * Stride]= v;2495else2496((cmsFloat64Number*) output)[i + start] = v;2497}249824992500if (Extra == 0 && SwapFirst) {25012502memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));2503*swap1 = v;2504}25052506if (T_PLANAR(info -> OutputFormat))2507return output + sizeof(cmsFloat64Number);2508else2509return output + (nChan + Extra) * sizeof(cmsFloat64Number);25102511}251225132514static2515cmsUInt8Number* PackFloatFrom16(CMSREGISTER _cmsTRANSFORM* info,2516CMSREGISTER cmsUInt16Number wOut[],2517CMSREGISTER cmsUInt8Number* output,2518CMSREGISTER cmsUInt32Number Stride)2519{2520cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);2521cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);2522cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);2523cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);2524cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);2525cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);2526cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2527cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;2528cmsFloat64Number v = 0;2529cmsFloat32Number* swap1 = (cmsFloat32Number*)output;2530cmsUInt32Number i, start = 0;25312532Stride /= PixelSize(info->OutputFormat);25332534if (ExtraFirst)2535start = Extra;25362537for (i = 0; i < nChan; i++) {25382539cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;25402541v = (cmsFloat64Number)wOut[index] / maximum;25422543if (Reverse)2544v = maximum - v;25452546if (Planar)2547((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;2548else2549((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;2550}255125522553if (Extra == 0 && SwapFirst) {25542555memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));2556*swap1 = (cmsFloat32Number)v;2557}25582559if (T_PLANAR(info->OutputFormat))2560return output + sizeof(cmsFloat32Number);2561else2562return output + (nChan + Extra) * sizeof(cmsFloat32Number);2563}2564256525662567// --------------------------------------------------------------------------------------------------------25682569static2570cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,2571cmsFloat32Number wOut[],2572cmsUInt8Number* output,2573cmsUInt32Number Stride)2574{2575cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);2576cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);2577cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);2578cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);2579cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);2580cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);2581cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2582cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;2583cmsFloat32Number* swap1 = (cmsFloat32Number*)output;2584cmsFloat64Number v = 0;2585cmsUInt32Number i, start = 0;25862587Stride /= PixelSize(info->OutputFormat);25882589if (ExtraFirst)2590start = Extra;25912592for (i = 0; i < nChan; i++) {25932594cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;25952596v = wOut[index] * maximum;25972598if (Reverse)2599v = maximum - v;26002601if (Planar)2602((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;2603else2604((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;2605}260626072608if (Extra == 0 && SwapFirst) {26092610memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));2611*swap1 = (cmsFloat32Number)v;2612}26132614if (T_PLANAR(info->OutputFormat))2615return output + sizeof(cmsFloat32Number);2616else2617return output + (nChan + Extra) * sizeof(cmsFloat32Number);2618}26192620static2621cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,2622cmsFloat32Number wOut[],2623cmsUInt8Number* output,2624cmsUInt32Number Stride)2625{2626cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);2627cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);2628cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);2629cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);2630cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);2631cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);2632cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2633cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;2634cmsFloat64Number v = 0;2635cmsFloat64Number* swap1 = (cmsFloat64Number*)output;2636cmsUInt32Number i, start = 0;26372638Stride /= PixelSize(info->OutputFormat);26392640if (ExtraFirst)2641start = Extra;26422643for (i = 0; i < nChan; i++) {26442645cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;26462647v = wOut[index] * maximum;26482649if (Reverse)2650v = maximum - v;26512652if (Planar)2653((cmsFloat64Number*)output)[(i + start) * Stride] = v;2654else2655((cmsFloat64Number*)output)[i + start] = v;2656}26572658if (Extra == 0 && SwapFirst) {26592660memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));2661*swap1 = v;2662}266326642665if (T_PLANAR(info->OutputFormat))2666return output + sizeof(cmsFloat64Number);2667else2668return output + (nChan + Extra) * sizeof(cmsFloat64Number);26692670}267126722673267426752676static2677cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info,2678cmsFloat32Number wOut[],2679cmsUInt8Number* output,2680cmsUInt32Number Stride)2681{2682cmsFloat32Number* Out = (cmsFloat32Number*) output;26832684if (T_PLANAR(Info -> OutputFormat)) {26852686Stride /= PixelSize(Info->OutputFormat);26872688Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);2689Out[Stride] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);2690Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);26912692return output + sizeof(cmsFloat32Number);2693}2694else {26952696Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);2697Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);2698Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);26992700return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));2701}27022703}270427052706static2707cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info,2708cmsFloat32Number wOut[],2709cmsUInt8Number* output,2710cmsUInt32Number Stride)2711{2712cmsFloat64Number* Out = (cmsFloat64Number*) output;27132714if (T_PLANAR(Info -> OutputFormat)) {27152716Stride /= PixelSize(Info->OutputFormat);27172718Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);2719Out[Stride] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);2720Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);27212722return output + sizeof(cmsFloat64Number);2723}2724else {27252726Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);2727Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);2728Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);27292730return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));2731}27322733}273427352736// From 0..1 range to 0..MAX_ENCODEABLE_XYZ2737static2738cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info,2739cmsFloat32Number wOut[],2740cmsUInt8Number* output,2741cmsUInt32Number Stride)2742{2743cmsFloat32Number* Out = (cmsFloat32Number*) output;27442745if (T_PLANAR(Info -> OutputFormat)) {27462747Stride /= PixelSize(Info->OutputFormat);27482749Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);2750Out[Stride] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);2751Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);27522753return output + sizeof(cmsFloat32Number);2754}2755else {27562757Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);2758Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);2759Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);27602761return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));2762}27632764}27652766// Same, but convert to double2767static2768cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info,2769cmsFloat32Number wOut[],2770cmsUInt8Number* output,2771cmsUInt32Number Stride)2772{2773cmsFloat64Number* Out = (cmsFloat64Number*) output;27742775if (T_PLANAR(Info -> OutputFormat)) {27762777Stride /= PixelSize(Info->OutputFormat);27782779Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);2780Out[Stride] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);2781Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);27822783return output + sizeof(cmsFloat64Number);2784}2785else {27862787Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);2788Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);2789Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);27902791return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));2792}27932794}279527962797// ----------------------------------------------------------------------------------------------------------------27982799#ifndef CMS_NO_HALF_SUPPORT28002801// Decodes an stream of half floats to wIn[] described by input format28022803static2804cmsUInt8Number* UnrollHalfTo16(CMSREGISTER _cmsTRANSFORM* info,2805CMSREGISTER cmsUInt16Number wIn[],2806CMSREGISTER cmsUInt8Number* accum,2807CMSREGISTER cmsUInt32Number Stride)2808{28092810cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);2811cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);2812cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);2813cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);2814cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);2815cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2816cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);2817cmsFloat32Number v;2818cmsUInt32Number i, start = 0;2819cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F;282028212822Stride /= PixelSize(info->OutputFormat);28232824if (ExtraFirst)2825start = Extra;28262827for (i=0; i < nChan; i++) {28282829cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;28302831if (Planar)2832v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );2833else2834v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;28352836if (Reverse) v = maximum - v;28372838wIn[index] = _cmsQuickSaturateWord((cmsFloat64Number) v * maximum);2839}284028412842if (Extra == 0 && SwapFirst) {2843cmsUInt16Number tmp = wIn[0];28442845memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));2846wIn[nChan-1] = tmp;2847}28482849if (T_PLANAR(info -> InputFormat))2850return accum + sizeof(cmsUInt16Number);2851else2852return accum + (nChan + Extra) * sizeof(cmsUInt16Number);2853}28542855// Decodes an stream of half floats to wIn[] described by input format28562857static2858cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info,2859cmsFloat32Number wIn[],2860cmsUInt8Number* accum,2861cmsUInt32Number Stride)2862{28632864cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);2865cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);2866cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);2867cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);2868cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);2869cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2870cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);2871cmsFloat32Number v;2872cmsUInt32Number i, start = 0;2873cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;28742875Stride /= PixelSize(info->OutputFormat);28762877if (ExtraFirst)2878start = Extra;28792880for (i=0; i < nChan; i++) {28812882cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;28832884if (Planar)2885v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );2886else2887v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[i + start] ) ;28882889v /= maximum;28902891wIn[index] = Reverse ? 1 - v : v;2892}289328942895if (Extra == 0 && SwapFirst) {2896cmsFloat32Number tmp = wIn[0];28972898memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsFloat32Number));2899wIn[nChan-1] = tmp;2900}29012902if (T_PLANAR(info -> InputFormat))2903return accum + sizeof(cmsUInt16Number);2904else2905return accum + (nChan + Extra) * sizeof(cmsUInt16Number);2906}290729082909static2910cmsUInt8Number* PackHalfFrom16(CMSREGISTER _cmsTRANSFORM* info,2911CMSREGISTER cmsUInt16Number wOut[],2912CMSREGISTER cmsUInt8Number* output,2913CMSREGISTER cmsUInt32Number Stride)2914{2915cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);2916cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);2917cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);2918cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);2919cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);2920cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);2921cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2922cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;2923cmsFloat32Number v = 0;2924cmsUInt16Number* swap1 = (cmsUInt16Number*)output;2925cmsUInt32Number i, start = 0;29262927Stride /= PixelSize(info->OutputFormat);29282929if (ExtraFirst)2930start = Extra;29312932for (i = 0; i < nChan; i++) {29332934cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;29352936v = (cmsFloat32Number)wOut[index] / maximum;29372938if (Reverse)2939v = maximum - v;29402941if (Planar)2942((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);2943else2944((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);2945}294629472948if (Extra == 0 && SwapFirst) {29492950memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));2951*swap1 = _cmsFloat2Half(v);2952}29532954if (T_PLANAR(info->OutputFormat))2955return output + sizeof(cmsUInt16Number);2956else2957return output + (nChan + Extra) * sizeof(cmsUInt16Number);2958}2959296029612962static2963cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,2964cmsFloat32Number wOut[],2965cmsUInt8Number* output,2966cmsUInt32Number Stride)2967{2968cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);2969cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);2970cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);2971cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);2972cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);2973cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);2974cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;2975cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;2976cmsUInt16Number* swap1 = (cmsUInt16Number*)output;2977cmsFloat32Number v = 0;2978cmsUInt32Number i, start = 0;29792980Stride /= PixelSize(info->OutputFormat);29812982if (ExtraFirst)2983start = Extra;29842985for (i = 0; i < nChan; i++) {29862987cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;29882989v = wOut[index] * maximum;29902991if (Reverse)2992v = maximum - v;29932994if (Planar)2995((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);2996else2997((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);2998}299930003001if (Extra == 0 && SwapFirst) {30023003memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));3004*swap1 = (cmsUInt16Number)_cmsFloat2Half(v);3005}30063007if (T_PLANAR(info->OutputFormat))3008return output + sizeof(cmsUInt16Number);3009else3010return output + (nChan + Extra)* sizeof(cmsUInt16Number);3011}30123013#endif30143015// ----------------------------------------------------------------------------------------------------------------301630173018static const cmsFormatters16 InputFormatters16[] = {30193020// Type Mask Function3021// ---------------------------- ------------------------------------ ----------------------------3022{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleTo16},3023{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleTo16},3024{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatTo16},3025{ TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatTo16},3026{ TYPE_GRAY_DBL, 0, UnrollDouble1Chan},3027{ FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|3028ANYSWAP|ANYEXTRA|ANYSPACE, UnrollDoubleTo16},3029{ FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|3030ANYSWAP|ANYEXTRA|ANYSPACE, UnrollFloatTo16},3031#ifndef CMS_NO_HALF_SUPPORT3032{ FLOAT_SH(1)|BYTES_SH(2), ANYCHANNELS|ANYPLANAR|ANYSWAPFIRST|ANYFLAVOR|3033ANYEXTRA|ANYSWAP|ANYSPACE, UnrollHalfTo16},3034#endif30353036{ CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Unroll1Byte},3037{ CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Unroll1ByteSkip1},3038{ CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2), ANYSPACE, Unroll1ByteSkip2},3039{ CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll1ByteReversed},3040{ COLORSPACE_SH(PT_MCH2)|CHANNELS_SH(2)|BYTES_SH(1), 0, Unroll2Bytes},30413042{ TYPE_LabV2_8, 0, UnrollLabV2_8 },3043{ TYPE_ALabV2_8, 0, UnrollALabV2_8 },3044{ TYPE_LabV2_16, 0, UnrollLabV2_16 },30453046{ CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Unroll3Bytes},3047{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSwap},3048{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3BytesSkip1Swap},3049{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3BytesSkip1SwapFirst},30503051{ CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),3052ANYSPACE, Unroll3BytesSkip1SwapSwapFirst},30533054{ CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Unroll4Bytes},3055{ CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Unroll4BytesReverse},3056{ CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapFirst},3057{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap},3058{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst},30593060{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|3061ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},30623063{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|3064ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},30653066{ CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word},3067{ CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll1WordReversed},3068{ CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3), ANYSPACE, Unroll1WordSkip3},30693070{ CHANNELS_SH(2)|BYTES_SH(2), ANYSPACE, Unroll2Words},3071{ CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Unroll3Words},3072{ CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Unroll4Words},30733074{ CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSwap},3075{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll3WordsSkip1SwapFirst},3076{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll3WordsSkip1Swap},3077{ CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Unroll4WordsReverse},3078{ CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapFirst},3079{ CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Unroll4WordsSwap},3080{ CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4WordsSwapSwapFirst},308130823083{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords},3084{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords},3085};3086308730883089static const cmsFormattersFloat InputFormattersFloat[] = {30903091// Type Mask Function3092// ---------------------------- ------------------------------------ ----------------------------3093{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, UnrollLabDoubleToFloat},3094{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, UnrollLabFloatToFloat},30953096{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, UnrollXYZDoubleToFloat},3097{ TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat},30983099{ FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|3100ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat},31013102{ FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|3103ANYCHANNELS|ANYSPACE, UnrollDoublesToFloat},3104#ifndef CMS_NO_HALF_SUPPORT3105{ FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|3106ANYCHANNELS|ANYSPACE, UnrollHalfToFloat},3107#endif3108};310931103111// Bit fields set to one in the mask are not compared3112static3113cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)3114{3115cmsUInt32Number i;3116cmsFormatter fr;31173118switch (dwFlags) {31193120case CMS_PACK_FLAGS_16BITS: {3121for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {3122const cmsFormatters16* f = InputFormatters16 + i;31233124if ((dwInput & ~f ->Mask) == f ->Type) {3125fr.Fmt16 = f ->Frm;3126return fr;3127}3128}3129}3130break;31313132case CMS_PACK_FLAGS_FLOAT: {3133for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {3134const cmsFormattersFloat* f = InputFormattersFloat + i;31353136if ((dwInput & ~f ->Mask) == f ->Type) {3137fr.FmtFloat = f ->Frm;3138return fr;3139}3140}3141}3142break;31433144default:;31453146}31473148fr.Fmt16 = NULL;3149return fr;3150}31513152static const cmsFormatters16 OutputFormatters16[] = {3153// Type Mask Function3154// ---------------------------- ------------------------------------ ----------------------------31553156{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFrom16},3157{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFrom16},31583159{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFrom16},3160{ TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFrom16},31613162{ FLOAT_SH(1)|BYTES_SH(0), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|3163ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackDoubleFrom16},3164{ FLOAT_SH(1)|BYTES_SH(4), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|3165ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackFloatFrom16},3166#ifndef CMS_NO_HALF_SUPPORT3167{ FLOAT_SH(1)|BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|3168ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE, PackHalfFrom16},3169#endif31703171{ CHANNELS_SH(1)|BYTES_SH(1), ANYSPACE, Pack1Byte},3172{ CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack1ByteSkip1},3173{ CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1ByteSkip1SwapFirst},31743175{ CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack1ByteReversed},31763177{ TYPE_LabV2_8, 0, PackLabV2_8 },3178{ TYPE_ALabV2_8, 0, PackALabV2_8 },3179{ TYPE_LabV2_16, 0, PackLabV2_16 },31803181{ CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesOptimized},3182{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesAndSkip1Optimized},3183{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),3184ANYSPACE, Pack3BytesAndSkip1SwapFirstOptimized},3185{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),3186ANYSPACE, Pack3BytesAndSkip1SwapSwapFirstOptimized},3187{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),3188ANYSPACE, Pack3BytesAndSkip1SwapOptimized},3189{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1), ANYSPACE, Pack3BytesSwapOptimized},3190319131923193{ CHANNELS_SH(3)|BYTES_SH(1), ANYSPACE, Pack3Bytes},3194{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1},3195{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3BytesAndSkip1SwapFirst},3196{ CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),3197ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst},3198{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap},3199{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap},3200{ CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes},3201{ CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap},3202{ CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes},3203{ CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse},3204{ CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst},3205{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap},3206{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst},32073208{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes},3209{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes},32103211{ CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word},3212{ CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1},3213{ CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack1WordSkip1SwapFirst},3214{ CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack1WordReversed},3215{ CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack1WordBigEndian},3216{ CHANNELS_SH(3)|BYTES_SH(2), ANYSPACE, Pack3Words},3217{ CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack3WordsSwap},3218{ CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack3WordsBigEndian},3219{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack3WordsAndSkip1},3220{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3WordsAndSkip1Swap},3221{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack3WordsAndSkip1SwapFirst},32223223{ CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),3224ANYSPACE, Pack3WordsAndSkip1SwapSwapFirst},32253226{ CHANNELS_SH(4)|BYTES_SH(2), ANYSPACE, Pack4Words},3227{ CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1), ANYSPACE, Pack4WordsReverse},3228{ CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack4WordsSwap},3229{ CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1), ANYSPACE, Pack4WordsBigEndian},32303231{ CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words},3232{ CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap},32333234{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords},3235{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords}32363237};323832393240static const cmsFormattersFloat OutputFormattersFloat[] = {3241// Type Mask Function3242// ---------------------------- --------------------------------------------------- ----------------------------3243{ TYPE_Lab_FLT, ANYPLANAR|ANYEXTRA, PackLabFloatFromFloat},3244{ TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, PackXYZFloatFromFloat},32453246{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat},3247{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat},32483249{ FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|3250ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackFloatsFromFloat },3251{ FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|3252ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackDoublesFromFloat },3253#ifndef CMS_NO_HALF_SUPPORT3254{ FLOAT_SH(1)|BYTES_SH(2),3255ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat },3256#endif32573258};325932603261// Bit fields set to one in the mask are not compared3262static3263cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)3264{3265cmsUInt32Number i;3266cmsFormatter fr;32673268// Optimization is only a hint3269dwInput &= ~OPTIMIZED_SH(1);32703271switch (dwFlags)3272{32733274case CMS_PACK_FLAGS_16BITS: {32753276for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {3277const cmsFormatters16* f = OutputFormatters16 + i;32783279if ((dwInput & ~f ->Mask) == f ->Type) {3280fr.Fmt16 = f ->Frm;3281return fr;3282}3283}3284}3285break;32863287case CMS_PACK_FLAGS_FLOAT: {32883289for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {3290const cmsFormattersFloat* f = OutputFormattersFloat + i;32913292if ((dwInput & ~f ->Mask) == f ->Type) {3293fr.FmtFloat = f ->Frm;3294return fr;3295}3296}3297}3298break;32993300default:;33013302}33033304fr.Fmt16 = NULL;3305return fr;3306}330733083309typedef struct _cms_formatters_factory_list {33103311cmsFormatterFactory Factory;3312struct _cms_formatters_factory_list *Next;33133314} cmsFormattersFactoryList;33153316_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL };331733183319// Duplicates the zone of memory used by the plug-in in the new context3320static3321void DupFormatterFactoryList(struct _cmsContext_struct* ctx,3322const struct _cmsContext_struct* src)3323{3324_cmsFormattersPluginChunkType newHead = { NULL };3325cmsFormattersFactoryList* entry;3326cmsFormattersFactoryList* Anterior = NULL;3327_cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin];33283329_cmsAssert(head != NULL);33303331// Walk the list copying all nodes3332for (entry = head->FactoryList;3333entry != NULL;3334entry = entry ->Next) {33353336cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList));33373338if (newEntry == NULL)3339return;33403341// We want to keep the linked list order, so this is a little bit tricky3342newEntry -> Next = NULL;3343if (Anterior)3344Anterior -> Next = newEntry;33453346Anterior = newEntry;33473348if (newHead.FactoryList == NULL)3349newHead.FactoryList = newEntry;3350}33513352ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType));3353}33543355// The interpolation plug-in memory chunk allocator/dup3356void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,3357const struct _cmsContext_struct* src)3358{3359_cmsAssert(ctx != NULL);33603361if (src != NULL) {33623363// Duplicate the LIST3364DupFormatterFactoryList(ctx, src);3365}3366else {3367static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };3368ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));3369}3370}3371337233733374// Formatters management3375cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)3376{3377_cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);3378cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;3379cmsFormattersFactoryList* fl ;33803381// Reset to built-in defaults3382if (Data == NULL) {33833384ctx ->FactoryList = NULL;3385return TRUE;3386}33873388fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList));3389if (fl == NULL) return FALSE;33903391fl ->Factory = Plugin ->FormattersFactory;33923393fl ->Next = ctx -> FactoryList;3394ctx ->FactoryList = fl;33953396return TRUE;3397}33983399cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID,3400cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_83401cmsFormatterDirection Dir,3402cmsUInt32Number dwFlags)3403{3404_cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);3405cmsFormattersFactoryList* f;34063407for (f =ctx->FactoryList; f != NULL; f = f ->Next) {34083409cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);3410if (fn.Fmt16 != NULL) return fn;3411}34123413// Revert to default3414if (Dir == cmsFormatterInput)3415return _cmsGetStockInputFormatter(Type, dwFlags);3416else3417return _cmsGetStockOutputFormatter(Type, dwFlags);3418}341934203421// Return whatever given formatter refers to float values3422cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type)3423{3424return T_FLOAT(Type) ? TRUE : FALSE;3425}34263427// Return whatever given formatter refers to 8 bits3428cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type)3429{3430cmsUInt32Number Bytes = T_BYTES(Type);34313432return (Bytes == 1);3433}34343435// Build a suitable formatter for the colorspace of this profile3436cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)3437{34383439cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile);3440cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);3441cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);3442cmsUInt32Number Float = lIsFloat ? 1U : 0;34433444// Create a fake formatter for result3445return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);3446}34473448// Build a suitable formatter for the colorspace of this profile3449cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)3450{34513452cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);34533454cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);3455cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);3456cmsUInt32Number Float = lIsFloat ? 1U : 0;34573458// Create a fake formatter for result3459return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);3460}3461346234633464