| /* |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| // This file is available under and governed by the GNU General Public |
| // License version 2 only, as published by the Free Software Foundation. |
| // However, the following notice accompanied the original version of this |
| // file: |
| // |
| // Little cms |
| // Copyright (C) 1998-2007 Marti Maria |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining |
| // a copy of this software and associated documentation files (the "Software"), |
| // to deal in the Software without restriction, including without limitation |
| // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| // and/or sell copies of the Software, and to permit persons to whom the Software |
| // is furnished to do so, subject to the following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included in |
| // all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO |
| // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| |
| #include "lcms.h" |
| |
| // This module handles all formats supported by lcms |
| |
| |
| // --------------------------------------------------------------------------- |
| |
| |
| // This macro return words stored as big endian |
| |
| #define CHANGE_ENDIAN(w) (WORD) ((WORD) ((w)<<8)|((w)>>8)) |
| |
| // These macros handles reversing (negative) |
| |
| #define REVERSE_FLAVOR_8(x) ((BYTE) (0xff-(x))) |
| #define REVERSE_FLAVOR_16(x) ((WORD)(0xffff-(x))) |
| |
| // Supress waning about info never being used |
| |
| #ifdef __BORLANDC__ |
| #pragma warn -par |
| #endif |
| |
| #ifdef _MSC_VER |
| #pragma warning(disable : 4100) |
| #endif |
| |
| // -------------------------------------------------------- Unpacking routines. |
| |
| |
| static |
| LPBYTE UnrollAnyBytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| int nChan = T_CHANNELS(info -> InputFormat); |
| register int i; |
| |
| for (i=0; i < nChan; i++) { |
| |
| wIn[i] = RGB_8_TO_16(*accum); accum++; |
| } |
| |
| return accum + T_EXTRA(info -> InputFormat); |
| } |
| |
| |
| |
| static |
| LPBYTE Unroll4Bytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // C |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // M |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // Y |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // K |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll4BytesReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C |
| wIn[1] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M |
| wIn[2] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y |
| wIn[3] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll4BytesSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // K |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // C |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // M |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // Y |
| |
| |
| return accum; |
| } |
| |
| |
| |
| // KYMC |
| static |
| LPBYTE Unroll4BytesSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // K |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // Y |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // M |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // C |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll4BytesSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // K |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // Y |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // M |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // C |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE UnrollAnyWords(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| int nChan = T_CHANNELS(info -> InputFormat); |
| register int i; |
| |
| for (i=0; i < nChan; i++) { |
| |
| wIn[i] = *(LPWORD) accum; accum += 2; |
| } |
| |
| return accum + T_EXTRA(info -> InputFormat) * sizeof(WORD); |
| } |
| |
| |
| static |
| LPBYTE Unroll4Words(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = *(LPWORD) accum; accum+= 2; // C |
| wIn[1] = *(LPWORD) accum; accum+= 2; // M |
| wIn[2] = *(LPWORD) accum; accum+= 2; // Y |
| wIn[3] = *(LPWORD) accum; accum+= 2; // K |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll4WordsReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // C |
| wIn[1] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // M |
| wIn[2] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // Y |
| wIn[3] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // K |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll4WordsSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = *(LPWORD) accum; accum+= 2; // K |
| wIn[0] = *(LPWORD) accum; accum+= 2; // C |
| wIn[1] = *(LPWORD) accum; accum+= 2; // M |
| wIn[2] = *(LPWORD) accum; accum+= 2; // Y |
| |
| return accum; |
| } |
| |
| |
| // KYMC |
| static |
| LPBYTE Unroll4WordsSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = *(LPWORD) accum; accum+= 2; // K |
| wIn[2] = *(LPWORD) accum; accum+= 2; // Y |
| wIn[1] = *(LPWORD) accum; accum+= 2; // M |
| wIn[0] = *(LPWORD) accum; accum+= 2; // C |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll4WordsSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[2] = *(LPWORD) accum; accum+= 2; // K |
| wIn[1] = *(LPWORD) accum; accum+= 2; // Y |
| wIn[0] = *(LPWORD) accum; accum+= 2; // M |
| wIn[3] = *(LPWORD) accum; accum+= 2; // C |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll4WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //C |
| wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //M |
| wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //Y |
| wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //K |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll4WordsBigEndianReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //C |
| wIn[1] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //M |
| wIn[2] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //Y |
| wIn[3] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //K |
| |
| return accum; |
| } |
| |
| |
| // KYMC |
| static |
| LPBYTE Unroll4WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //K |
| wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //Y |
| wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //M |
| wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //C |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll3Bytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // R |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // G |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // B |
| |
| return accum; |
| } |
| |
| |
| // Lab8 encoding using v2 PCS |
| |
| static |
| LPBYTE Unroll3BytesLab(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| |
| wIn[0] = (WORD) ((*accum) << 8); accum++; |
| wIn[1] = (WORD) ((*accum) << 8); accum++; |
| wIn[2] = (WORD) ((*accum) << 8); accum++; |
| |
| return accum; |
| } |
| |
| |
| // BRG |
| |
| static |
| LPBYTE Unroll3BytesSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| |
| wIn[2] = RGB_8_TO_16(*accum); accum++; // B |
| wIn[1] = RGB_8_TO_16(*accum); accum++; // G |
| wIn[0] = RGB_8_TO_16(*accum); accum++; // R |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll3Words(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = *(LPWORD) accum; accum+= 2; // C R |
| wIn[1] = *(LPWORD) accum; accum+= 2; // M G |
| wIn[2] = *(LPWORD) accum; accum+= 2; // Y B |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll3WordsSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[2] = *(LPWORD) accum; accum+= 2; // C R |
| wIn[1] = *(LPWORD) accum; accum+= 2; // M G |
| wIn[0] = *(LPWORD) accum; accum+= 2; // Y B |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll3WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll3WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| return accum; |
| } |
| |
| |
| |
| // Monochrome duplicates L into RGB for null-transforms |
| |
| static |
| LPBYTE Unroll1Byte(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++; // L |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll1ByteSkip2(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++; // L |
| accum += 2; |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll1ByteReversed(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(RGB_8_TO_16(*accum)); accum++; // L |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll1Word(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2; // L |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll1WordReversed(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll1WordBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll1WordSkip3(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; |
| |
| accum += 8; |
| return accum; |
| } |
| |
| |
| // Monochrome + alpha. Alpha is lost |
| |
| static |
| LPBYTE Unroll2Byte(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++; // L |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // alpha |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll2ByteSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = RGB_8_TO_16(*accum); accum++; // alpha |
| wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++; // L |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll2Word(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2; // L |
| wIn[3] = *(LPWORD) accum; accum += 2; // alpha |
| |
| return accum; |
| } |
| |
| |
| static |
| LPBYTE Unroll2WordSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[3] = *(LPWORD) accum; accum += 2; // alpha |
| wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2; // L |
| |
| return accum; |
| } |
| |
| static |
| LPBYTE Unroll2WordBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| wIn[0] = wIn[1] = wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; |
| |
| return accum; |
| } |
| |
| |
| |
| |
| static |
| LPBYTE UnrollPlanarBytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| int nChan = T_CHANNELS(info -> InputFormat); |
| register int i; |
| LPBYTE Init = accum; |
| |
| for (i=0; i < nChan; i++) { |
| |
| wIn[i] = RGB_8_TO_16(*accum); |
| accum += info -> StrideIn; |
| } |
| |
| return (Init + 1); |
| } |
| |
| |
| |
| static |
| LPBYTE UnrollPlanarWords(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| int nChan = T_CHANNELS(info -> InputFormat); |
| register int i; |
| LPBYTE Init = accum; |
| |
| for (i=0; i < nChan; i++) { |
| |
| wIn[i] = *(LPWORD) accum; |
| accum += (info -> StrideIn * sizeof(WORD)); |
| } |
| |
| return (Init + sizeof(WORD)); |
| } |
| |
| |
| |
| static |
| LPBYTE UnrollPlanarWordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| int nChan = T_CHANNELS(info -> InputFormat); |
| register int i; |
| LPBYTE Init = accum; |
| |
| for (i=0; i < nChan; i++) { |
| |
| wIn[i] = CHANGE_ENDIAN(*(LPWORD) accum); |
| accum += (info -> StrideIn * sizeof(WORD)); |
| } |
| |
| return (Init + sizeof(WORD)); |
| } |
| |
| |
| // floating point |
| static |
| LPBYTE UnrollLabDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| |
| if (T_PLANAR(info -> InputFormat)) { |
| |
| double* Pt = (double*) accum; |
| |
| cmsCIELab Lab; |
| |
| Lab.L = Pt[0]; |
| Lab.a = Pt[info->StrideIn]; |
| Lab.b = Pt[info->StrideIn*2]; |
| |
| if (info ->lInputV4Lab) |
| cmsFloat2LabEncoded4(wIn, &Lab); |
| else |
| cmsFloat2LabEncoded(wIn, &Lab); |
| |
| return accum + sizeof(double); |
| } |
| else { |
| |
| if (info ->lInputV4Lab) |
| cmsFloat2LabEncoded4(wIn, (LPcmsCIELab) accum); |
| else |
| cmsFloat2LabEncoded(wIn, (LPcmsCIELab) accum); |
| |
| accum += sizeof(cmsCIELab); |
| |
| return accum; |
| } |
| } |
| |
| static |
| LPBYTE UnrollXYZDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| if (T_PLANAR(info -> InputFormat)) { |
| |
| double* Pt = (double*) accum; |
| cmsCIEXYZ XYZ; |
| |
| XYZ.X = Pt[0]; |
| XYZ.Y = Pt[info->StrideIn]; |
| XYZ.Z = Pt[info->StrideIn*2]; |
| cmsFloat2XYZEncoded(wIn, &XYZ); |
| |
| return accum + sizeof(double); |
| |
| } |
| |
| else { |
| |
| |
| cmsFloat2XYZEncoded(wIn, (LPcmsCIEXYZ) accum); |
| accum += sizeof(cmsCIEXYZ); |
| |
| return accum; |
| } |
| } |
| |
| |
| |
| // Inks does come in percentage |
| static |
| LPBYTE UnrollInkDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| double* Inks = (double*) accum; |
| int nChan = T_CHANNELS(info -> InputFormat); |
| int Planar = T_PLANAR(info -> InputFormat); |
| int i; |
| double v; |
| |
| for (i=0; i < nChan; i++) { |
| |
| if (Planar) |
| |
| v = Inks[i * info ->StrideIn]; |
| else |
| v = Inks[i]; |
| |
| v = floor(v * 655.35 + 0.5); |
| |
| if (v > 65535.0) v = 65535.0; |
| if (v < 0) v = 0; |
| |
| wIn[i] = (WORD) v; |
| } |
| |
| if (T_PLANAR(info -> InputFormat)) |
| return accum + sizeof(double); |
| else |
| return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(double); |
| } |
| |
| |
| // Remaining cases are between 0..1.0 |
| static |
| LPBYTE UnrollDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| double* Inks = (double*) accum; |
| int nChan = T_CHANNELS(info -> InputFormat); |
| int Planar = T_PLANAR(info -> InputFormat); |
| int i; |
| double v; |
| |
| for (i=0; i < nChan; i++) { |
| |
| if (Planar) |
| |
| v = Inks[i * info ->StrideIn]; |
| else |
| v = Inks[i]; |
| |
| v = floor(v * 65535.0 + 0.5); |
| |
| if (v > 65535.0) v = 65535.0; |
| if (v < 0) v = 0; |
| |
| wIn[i] = (WORD) v; |
| } |
| |
| if (T_PLANAR(info -> InputFormat)) |
| return accum + sizeof(double); |
| else |
| return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(double); |
| } |
| |
| |
| |
| static |
| LPBYTE UnrollDouble1Chan(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) |
| { |
| double* Inks = (double*) accum; |
| double v; |
| |
| |
| v = floor(Inks[0] * 65535.0 + 0.5); |
| |
| if (v > 65535.0) v = 65535.0; |
| if (v < 0) v = 0; |
| |
| |
| wIn[0] = wIn[1] = wIn[2] = (WORD) v; |
| |
| return accum + sizeof(double); |
| } |
| |
| |
| // ----------------------------------------------------------- Packing routines |
| |
| |
| // Generic N-bytes plus dither 16-to-8 conversion. Currently is just a quick hack |
| |
| static int err[MAXCHANNELS]; |
| |
| static |
| LPBYTE PackNBytesDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| unsigned int n, pe, pf; |
| |
| for (i=0; i < nChan; i++) { |
| |
| n = wOut[i] + err[i]; // Value |
| |
| pe = (n / 257); // Whole part |
| pf = (n % 257); // Fractional part |
| |
| err[i] = pf; // Store it for next pixel |
| |
| *output++ = (BYTE) pe; |
| } |
| |
| return output + T_EXTRA(info ->OutputFormat); |
| } |
| |
| |
| |
| static |
| LPBYTE PackNBytesSwapDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| unsigned int n, pe, pf; |
| |
| for (i=nChan-1; i >= 0; --i) { |
| |
| n = wOut[i] + err[i]; // Value |
| |
| pe = (n / 257); // Whole part |
| pf = (n % 257); // Fractional part |
| |
| err[i] = pf; // Store it for next pixel |
| |
| *output++ = (BYTE) pe; |
| } |
| |
| |
| return output + T_EXTRA(info ->OutputFormat); |
| } |
| |
| |
| |
| // Generic chunky for byte |
| |
| static |
| LPBYTE PackNBytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=0; i < nChan; i++) |
| *output++ = RGB_16_TO_8(wOut[i]); |
| |
| return output + T_EXTRA(info ->OutputFormat); |
| } |
| |
| // Chunky reversed order bytes |
| |
| static |
| LPBYTE PackNBytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=nChan-1; i >= 0; --i) |
| *output++ = RGB_16_TO_8(wOut[i]); |
| |
| return output + T_EXTRA(info ->OutputFormat); |
| |
| } |
| |
| |
| static |
| LPBYTE PackNWords(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=0; i < nChan; i++) { |
| *(LPWORD) output = wOut[i]; |
| output += sizeof(WORD); |
| } |
| |
| return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD); |
| } |
| |
| static |
| LPBYTE PackNWordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=nChan-1; i >= 0; --i) { |
| *(LPWORD) output = wOut[i]; |
| output += sizeof(WORD); |
| } |
| |
| return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD); |
| } |
| |
| |
| |
| static |
| LPBYTE PackNWordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=0; i < nChan; i++) { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[i]); |
| output += sizeof(WORD); |
| } |
| |
| return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD); |
| } |
| |
| |
| static |
| LPBYTE PackNWordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| |
| for (i=nChan-1; i >= 0; --i) { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[i]); |
| output += sizeof(WORD); |
| } |
| |
| return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD); |
| } |
| |
| |
| static |
| LPBYTE PackPlanarBytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| LPBYTE Init = output; |
| |
| for (i=0; i < nChan; i++) { |
| |
| *(LPBYTE) output = RGB_16_TO_8(wOut[i]); |
| output += info -> StrideOut; |
| } |
| |
| return (Init + 1); |
| } |
| |
| |
| static |
| LPBYTE PackPlanarWords(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| int nChan = T_CHANNELS(info -> OutputFormat); |
| register int i; |
| LPBYTE Init = output; |
| |
| for (i=0; i < nChan; i++) { |
| |
| *(LPWORD) output = wOut[i]; |
| output += (info -> StrideOut * sizeof(WORD)); |
| } |
| |
| return (Init + 2); |
| } |
| |
| |
| // CMYKcm (unrolled for speed) |
| |
| static |
| LPBYTE Pack6Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[3]); |
| *output++ = RGB_16_TO_8(wOut[4]); |
| *output++ = RGB_16_TO_8(wOut[5]); |
| |
| return output; |
| } |
| |
| // KCMYcm |
| |
| static |
| LPBYTE Pack6BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[3]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[4]); |
| *output++ = RGB_16_TO_8(wOut[5]); |
| |
| return output; |
| } |
| |
| // CMYKcm |
| static |
| LPBYTE Pack6Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[3]; |
| output+= 2; |
| *(LPWORD) output = wOut[4]; |
| output+= 2; |
| *(LPWORD) output = wOut[5]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| // KCMYcm |
| static |
| LPBYTE Pack6WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[3]; |
| output+= 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[4]; |
| output+= 2; |
| *(LPWORD) output = wOut[5]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| // CMYKcm |
| static |
| LPBYTE Pack6WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[3]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[4]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[5]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| // KCMYcm |
| static |
| LPBYTE Pack6WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[3]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[4]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[5]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[3]); |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack4BytesReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[0])); |
| *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[1])); |
| *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[2])); |
| *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[3])); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4BytesSwapFirst(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[3]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| |
| return output; |
| } |
| |
| |
| // ABGR |
| |
| static |
| LPBYTE Pack4BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[3]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4BytesSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[3]); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[3]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4WordsReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = REVERSE_FLAVOR_16(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = REVERSE_FLAVOR_16(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = REVERSE_FLAVOR_16(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = REVERSE_FLAVOR_16(wOut[3]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| // ABGR |
| |
| static |
| LPBYTE Pack4WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[3]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| // CMYK |
| static |
| LPBYTE Pack4WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[3]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack4WordsBigEndianReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[0])); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[1])); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[2])); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[3])); |
| output+= 2; |
| |
| return output; |
| } |
| |
| // KYMC |
| |
| static |
| LPBYTE Pack4WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[3]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3BytesLab(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = (BYTE) (wOut[0] >> 8); |
| *output++ = (BYTE) (wOut[1] >> 8); |
| *output++ = (BYTE) (wOut[2] >> 8); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3WordsSwapBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3BytesAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| output++; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3BytesAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output++; |
| *output++ = RGB_16_TO_8(wOut[0]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[2]); |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3BytesAndSkip1Swap(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output++; |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3BytesAndSkip1SwapSwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[2]); |
| *output++ = RGB_16_TO_8(wOut[1]); |
| *output++ = RGB_16_TO_8(wOut[0]); |
| output++; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3WordsAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| output+= 2; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack3WordsAndSkip1Swap(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output+= 2; |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3WordsAndSkip1SwapSwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[2]; |
| output+= 2; |
| *(LPWORD) output = wOut[1]; |
| output+= 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| output+= 2; |
| |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3WordsAndSkip1BigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack3WordsAndSkip1SwapBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[2]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[1]); |
| output+= 2; |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| |
| |
| return output; |
| } |
| |
| |
| |
| static |
| LPBYTE Pack1Byte(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack1ByteAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *output++ = RGB_16_TO_8(wOut[0]); |
| output++; |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack1ByteAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output++; |
| *output++ = RGB_16_TO_8(wOut[0]); |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack1Word(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack1WordBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack1WordAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = wOut[0]; |
| output+= 4; |
| |
| return output; |
| } |
| |
| static |
| LPBYTE Pack1WordAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| output += 2; |
| *(LPWORD) output = wOut[0]; |
| output+= 2; |
| |
| return output; |
| } |
| |
| |
| static |
| LPBYTE Pack1WordAndSkip1BigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| *(LPWORD) output = CHANGE_ENDIAN(wOut[0]); |
| output+= 4; |
| |
| return output; |
| } |
| |
| |
| // Unencoded Float values -- don't try optimize speed |
| |
| static |
| LPBYTE PackLabDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| |
| if (T_PLANAR(Info -> OutputFormat)) { |
| |
| cmsCIELab Lab; |
| double* Out = (double*) output; |
| cmsLabEncoded2Float(&Lab, wOut); |
| |
| Out[0] = Lab.L; |
| Out[Info ->StrideOut] = Lab.a; |
| Out[Info ->StrideOut*2] = Lab.b; |
| |
| return output + sizeof(double); |
| |
| } |
| else { |
| |
| if (Info ->lOutputV4Lab) |
| cmsLabEncoded2Float4((LPcmsCIELab) output, wOut); |
| else |
| cmsLabEncoded2Float((LPcmsCIELab) output, wOut); |
| |
| return output + (sizeof(cmsCIELab) + T_EXTRA(Info ->OutputFormat) * sizeof(double)); |
| } |
| |
| } |
| |
| static |
| LPBYTE PackXYZDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| |
| if (T_PLANAR(Info -> OutputFormat)) { |
| |
| cmsCIEXYZ XYZ; |
| double* Out = (double*) output; |
| cmsXYZEncoded2Float(&XYZ, wOut); |
| |
| Out[0] = XYZ.X; |
| Out[Info ->StrideOut] = XYZ.Y; |
| Out[Info ->StrideOut*2] = XYZ.Z; |
| |
| return output + sizeof(double); |
| |
| } |
| else { |
| |
| cmsXYZEncoded2Float((LPcmsCIEXYZ) output, wOut); |
| |
| return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(double)); |
| } |
| } |
| |
| |
| |
| static |
| LPBYTE PackInkDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| double* Inks = (double*) output; |
| int nChan = T_CHANNELS(Info -> OutputFormat); |
| int i; |
| |
| if (T_PLANAR(Info -> OutputFormat)) { |
| |
| for (i=0; i < nChan; i++) { |
| |
| Inks[i*Info ->StrideOut] = wOut[i] / 655.35; |
| } |
| |
| return output + sizeof(double); |
| } |
| else { |
| |
| for (i=0; i < nChan; i++) { |
| |
| Inks[i] = wOut[i] / 655.35; |
| } |
| |
| |
| return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(double); |
| } |
| |
| } |
| |
| |
| static |
| LPBYTE PackDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output) |
| { |
| double* Inks = (double*) output; |
| int nChan = T_CHANNELS(Info -> OutputFormat); |
| int i; |
| |
| |
| if (T_PLANAR(Info -> OutputFormat)) { |
| |
| for (i=0; i < nChan; i++) { |
| |
| Inks[i*Info ->StrideOut] = wOut[i] / 65535.0; |
| } |
| |
| return output + sizeof(double); |
| |
| } |
| else { |
| for (i=0; i < nChan; i++) { |
| |
| Inks[i] = wOut[i] / 65535.0; |
| } |
| |
| return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(double); |
| } |
| |
| } |
| |
| |
| // choose routine from Input identifier |
| |
| _cmsFIXFN _cmsIdentifyInputFormat(_LPcmsTRANSFORM xform, DWORD dwInput) |
| { |
| _cmsFIXFN FromInput = NULL; |
| |
| |
| // Check Named Color |
| |
| if (xform) { |
| |
| if (xform ->InputProfile) { |
| |
| if (cmsGetDeviceClass(xform ->InputProfile) == icSigNamedColorClass) { |
| |
| if (dwInput != TYPE_NAMED_COLOR_INDEX) { |
| cmsSignalError(LCMS_ERRC_ABORTED, "Named color needs TYPE_NAMED_COLOR_INDEX"); |
| return NULL; |
| } |
| } |
| |
| } |
| } |
| |
| // Unencoded modes |
| |
| if (T_BYTES(dwInput) == 0) { |
| |
| switch (T_COLORSPACE(dwInput)) { |
| |
| case PT_Lab: |
| FromInput = UnrollLabDouble; |
| break; |
| case PT_XYZ: |
| FromInput = UnrollXYZDouble; |
| break; |
| |
| // 0.0 .. 1.0 range |
| |
| case PT_GRAY: |
| case PT_RGB: |
| case PT_YCbCr: |
| case PT_YUV: |
| case PT_YUVK: |
| case PT_HSV: |
| case PT_HLS: |
| case PT_Yxy: |
| if (T_CHANNELS(dwInput) == 1) |
| FromInput = UnrollDouble1Chan; |
| else |
| FromInput = UnrollDouble; |
| break; |
| |
| // Inks (%) 0.0 .. 100.0 |
| |
| default: |
| FromInput = UnrollInkDouble; |
| break; |
| } |
| |
| } |
| else { |
| |
| if (T_PLANAR(dwInput)) { |
| |
| switch (T_BYTES(dwInput)) { |
| |
| case 1: |
| FromInput = UnrollPlanarBytes; |
| break; |
| |
| case 2: |
| if (T_ENDIAN16(dwInput)) |
| FromInput = UnrollPlanarWordsBigEndian; |
| else |
| FromInput = UnrollPlanarWords; |
| break; |
| |
| default:; |
| } |
| } |
| else { |
| |
| switch (T_BYTES(dwInput)) { |
| |
| case 1: // 1 byte per channel |
| |
| switch (T_CHANNELS(dwInput) + T_EXTRA(dwInput)) { |
| |
| case 1: if (T_FLAVOR(dwInput)) |
| FromInput = Unroll1ByteReversed; |
| else |
| FromInput = Unroll1Byte; |
| break; |
| |
| case 2: if (T_SWAPFIRST(dwInput)) |
| FromInput = Unroll2ByteSwapFirst; |
| else |
| FromInput = Unroll2Byte; |
| break; |
| |
| case 3: if (T_DOSWAP(dwInput)) |
| FromInput = Unroll3BytesSwap; |
| else { |
| if (T_EXTRA(dwInput) == 2) |
| FromInput = Unroll1ByteSkip2; |
| else |
| if (T_COLORSPACE(dwInput) == PT_Lab) |
| FromInput = Unroll3BytesLab; |
| else |
| FromInput = Unroll3Bytes; |
| } |
| break; |
| case 4: |
| // TODO: ALab8 must be fixed to match v2 encoding |
| |
| if (T_DOSWAP(dwInput)) { |
| if (T_SWAPFIRST(dwInput)) |
| |
| FromInput = Unroll4BytesSwapSwapFirst; |
| else |
| FromInput = Unroll4BytesSwap; |
| } |
| else { |
| if (T_SWAPFIRST(dwInput)) |
| FromInput = Unroll4BytesSwapFirst; |
| else { |
| if (T_FLAVOR(dwInput)) |
| FromInput = Unroll4BytesReverse; |
| else |
| FromInput = Unroll4Bytes; |
| } |
| } |
| break; |
| |
| |
| case 5: |
| case 6: |
| case 7: |
| case 8: |
| if (!T_DOSWAP(dwInput) && !T_SWAPFIRST(dwInput)) |
| FromInput = UnrollAnyBytes; |
| break; |
| |
| |
| default:; |
| } |
| break; |
| |
| |
| case 2: // 1 word per channel |
| |
| switch (T_CHANNELS(dwInput) + T_EXTRA(dwInput)) |
| { |
| case 1: if (T_ENDIAN16(dwInput)) |
| FromInput = Unroll1WordBigEndian; |
| else |
| if (T_FLAVOR(dwInput)) |
| FromInput = Unroll1WordReversed; |
| else |
| FromInput = Unroll1Word; |
| break; |
| |
| case 2: if (T_ENDIAN16(dwInput)) |
| FromInput = Unroll2WordBigEndian; |
| else { |
| if (T_SWAPFIRST(dwInput)) |
| FromInput = Unroll2WordSwapFirst; |
| else |
| FromInput = Unroll2Word; |
| } |
| break; |
| |
| case 3: if (T_DOSWAP(dwInput)) { |
| if (T_ENDIAN16(dwInput)) |
| FromInput = Unroll3WordsSwapBigEndian; |
| else |
| FromInput = Unroll3WordsSwap; |
| } |
| else { |
| if (T_ENDIAN16(dwInput)) |
| FromInput = Unroll3WordsBigEndian; |
| else |
| FromInput = Unroll3Words; |
| } |
| break; |
| |
| case 4: if (T_DOSWAP(dwInput)) { |
| |
| if (T_ENDIAN16(dwInput)) |
| FromInput = Unroll4WordsSwapBigEndian; |
| else { |
| |
| if (T_SWAPFIRST(dwInput)) |
| FromInput = Unroll4WordsSwapSwapFirst; |
| else |
| FromInput = Unroll4WordsSwap; |
| |
| } |
| |
| } |
| else { |
| |
| if (T_EXTRA(dwInput) == 3) |
| FromInput = Unroll1WordSkip3; |
| else |
| |
| if (T_ENDIAN16(dwInput)) { |
| |
| if (T_FLAVOR(dwInput)) |
| FromInput = Unroll4WordsBigEndianReverse; |
| else |
| FromInput = Unroll4WordsBigEndian; |
| } |
| else { |
| if (T_SWAPFIRST(dwInput)) |
| FromInput = Unroll4WordsSwapFirst; |
| else { |
| if (T_FLAVOR(dwInput)) |
| FromInput = Unroll4WordsReverse; |
| else |
| FromInput = Unroll4Words; |
| } |
| } |
| } |
| break; |
| |
| |
| case 5: |
| case 6: |
| case 7: |
| case 8: |
| if (!T_DOSWAP(dwInput) && !T_SWAPFIRST(dwInput)) |
| FromInput = UnrollAnyWords; |
| break; |
| |
| } |
| break; |
| |
| default:; |
| } |
| } |
| } |
| |
| |
| if (!FromInput) |
| cmsSignalError(LCMS_ERRC_ABORTED, "Unknown input format"); |
| |
| return FromInput; |
| } |
| |
| // choose routine from Input identifier |
| |
| _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput) |
| { |
| _cmsFIXFN ToOutput = NULL; |
| |
| |
| if (T_BYTES(dwOutput) == 0) { |
| |
| switch (T_COLORSPACE(dwOutput)) { |
| |
| case PT_Lab: |
| ToOutput = PackLabDouble; |
| break; |
| case PT_XYZ: |
| ToOutput = PackXYZDouble; |
| break; |
| |
| // 0.0 .. 1.0 range |
| case PT_GRAY: |
| case PT_RGB: |
| case PT_YCbCr: |
| case PT_YUV: |
| case PT_YUVK: |
| case PT_HSV: |
| case PT_HLS: |
| case PT_Yxy: |
| ToOutput = PackDouble; |
| break; |
| |
| // Inks (%) 0.0 .. 100.0 |
| |
| default: |
| ToOutput = PackInkDouble; |
| break; |
| } |
| |
| } |
| else |
| |
| if (T_PLANAR(dwOutput)) { |
| |
| switch (T_BYTES(dwOutput)) { |
| |
| case 1: ToOutput = PackPlanarBytes; |
| break; |
| |
| case 2:if (!T_ENDIAN16(dwOutput)) |
| ToOutput = PackPlanarWords; |
| break; |
| |
| default:; |
| } |
| } |
| else { |
| |
| switch (T_BYTES(dwOutput)) { |
| |
| case 1: |
| switch (T_CHANNELS(dwOutput)) |
| { |
| case 1: |
| if (T_DITHER(dwOutput)) |
| ToOutput = PackNBytesDither; |
| else |
| ToOutput = Pack1Byte; |
| if (T_EXTRA(dwOutput) == 1) { |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack1ByteAndSkip1SwapFirst; |
| else |
| ToOutput = Pack1ByteAndSkip1; |
| } |
| break; |
| |
| case 3: |
| switch (T_EXTRA(dwOutput)) { |
| |
| case 0: if (T_DOSWAP(dwOutput)) |
| ToOutput = Pack3BytesSwap; |
| else |
| if (T_COLORSPACE(dwOutput) == PT_Lab) |
| ToOutput = Pack3BytesLab; |
| else { |
| if (T_DITHER(dwOutput)) |
| ToOutput = PackNBytesDither; |
| else |
| ToOutput = Pack3Bytes; |
| } |
| break; |
| |
| case 1: // TODO: ALab8 should be handled here |
| |
| if (T_DOSWAP(dwOutput)) { |
| |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack3BytesAndSkip1SwapSwapFirst; |
| else |
| ToOutput = Pack3BytesAndSkip1Swap; |
| } |
| else { |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack3BytesAndSkip1SwapFirst; |
| else |
| ToOutput = Pack3BytesAndSkip1; |
| } |
| break; |
| |
| default:; |
| } |
| break; |
| |
| case 4: if (T_EXTRA(dwOutput) == 0) { |
| |
| |
| if (T_DOSWAP(dwOutput)) { |
| |
| |
| if (T_SWAPFIRST(dwOutput)) { |
| ToOutput = Pack4BytesSwapSwapFirst; |
| } |
| else { |
| |
| if (T_DITHER(dwOutput)) { |
| ToOutput = PackNBytesSwapDither; |
| } |
| else { |
| ToOutput = Pack4BytesSwap; |
| } |
| } |
| } |
| else { |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack4BytesSwapFirst; |
| else { |
| |
| if (T_FLAVOR(dwOutput)) |
| ToOutput = Pack4BytesReverse; |
| else { |
| if (T_DITHER(dwOutput)) |
| ToOutput = PackNBytesDither; |
| else |
| ToOutput = Pack4Bytes; |
| } |
| } |
| } |
| } |
| else { |
| if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput)) |
| ToOutput = PackNBytes; |
| } |
| break; |
| |
| // Hexachrome separations. |
| case 6: if (T_EXTRA(dwOutput) == 0) { |
| |
| if( T_DOSWAP(dwOutput)) |
| ToOutput = Pack6BytesSwap; |
| else |
| ToOutput = Pack6Bytes; |
| } |
| else { |
| if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput)) |
| ToOutput = PackNBytes; |
| |
| } |
| break; |
| |
| case 2: |
| case 5: |
| case 7: |
| case 8: |
| case 9: |
| case 10: |
| case 11: |
| case 12: |
| case 13: |
| case 14: |
| case 15: |
| |
| if ((T_EXTRA(dwOutput) == 0) && (T_SWAPFIRST(dwOutput) == 0)) |
| { |
| if (T_DOSWAP(dwOutput)) |
| ToOutput = PackNBytesSwap; |
| else { |
| |
| if (T_DITHER(dwOutput)) |
| ToOutput = PackNBytesDither; |
| else |
| ToOutput = PackNBytes; |
| } |
| } |
| break; |
| |
| default:; |
| } |
| break; |
| |
| |
| case 2: |
| |
| switch (T_CHANNELS(dwOutput)) { |
| |
| case 1: |
| if (T_ENDIAN16(dwOutput)) |
| |
| ToOutput = Pack1WordBigEndian; |
| else |
| ToOutput = Pack1Word; |
| |
| if (T_EXTRA(dwOutput) == 1) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| |
| ToOutput = Pack1WordAndSkip1BigEndian; |
| else { |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack1WordAndSkip1SwapFirst; |
| else |
| ToOutput = Pack1WordAndSkip1; |
| } |
| } |
| break; |
| |
| case 3: |
| |
| switch (T_EXTRA(dwOutput)) { |
| |
| case 0: |
| if (T_DOSWAP(dwOutput)) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| |
| ToOutput = Pack3WordsSwapBigEndian; |
| else |
| ToOutput = Pack3WordsSwap; |
| } |
| else { |
| if (T_ENDIAN16(dwOutput)) |
| |
| ToOutput = Pack3WordsBigEndian; |
| else |
| ToOutput = Pack3Words; |
| } |
| break; |
| |
| case 1: if (T_DOSWAP(dwOutput)) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| |
| ToOutput = Pack3WordsAndSkip1SwapBigEndian; |
| else { |
| if (T_SWAPFIRST(dwOutput)) |
| ToOutput = Pack3WordsAndSkip1SwapSwapFirst; |
| else |
| ToOutput = Pack3WordsAndSkip1Swap; |
| } |
| } |
| else { |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = Pack3WordsAndSkip1BigEndian; |
| else |
| ToOutput = Pack3WordsAndSkip1; |
| } |
| default:; |
| } |
| break; |
| |
| case 4: if (T_EXTRA(dwOutput) == 0) { |
| |
| if (T_DOSWAP(dwOutput)) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = Pack4WordsSwapBigEndian; |
| else |
| ToOutput = Pack4WordsSwap; |
| } |
| else { |
| |
| if (T_ENDIAN16(dwOutput)) { |
| |
| if (T_FLAVOR(dwOutput)) |
| ToOutput = Pack4WordsBigEndianReverse; |
| else |
| ToOutput = Pack4WordsBigEndian; |
| } |
| else { |
| if (T_FLAVOR(dwOutput)) |
| ToOutput = Pack4WordsReverse; |
| else |
| ToOutput = Pack4Words; |
| } |
| } |
| } |
| else { |
| if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput)) |
| ToOutput = PackNWords; |
| } |
| break; |
| |
| case 6: if (T_EXTRA(dwOutput) == 0) { |
| |
| if (T_DOSWAP(dwOutput)) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = Pack6WordsSwapBigEndian; |
| else |
| ToOutput = Pack6WordsSwap; |
| } |
| else { |
| |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = Pack6WordsBigEndian; |
| else |
| ToOutput = Pack6Words; |
| } |
| } |
| else { |
| if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput)) |
| ToOutput = PackNWords; |
| } |
| break; |
| |
| |
| case 2: |
| case 5: |
| case 7: |
| case 8: |
| case 9: |
| case 10: |
| case 11: |
| case 12: |
| case 13: |
| case 14: |
| case 15: if ((T_EXTRA(dwOutput) == 0) && (T_SWAPFIRST(dwOutput) == 0)) { |
| |
| if (T_DOSWAP(dwOutput)) { |
| |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = PackNWordsSwapBigEndian; |
| else |
| ToOutput = PackNWordsSwap; |
| } |
| else { |
| |
| if (T_ENDIAN16(dwOutput)) |
| ToOutput = PackNWordsBigEndian; |
| else |
| ToOutput = PackNWords; |
| } |
| } |
| break; |
| |
| default:; |
| } |
| break; |
| |
| default:; |
| } |
| } |
| |
| if (!ToOutput) |
| cmsSignalError(LCMS_ERRC_ABORTED, "Unknown output format"); |
| |
| return ToOutput; |
| } |
| |
| // User formatters for (weird) cases not already included |
| |
| void LCMSEXPORT cmsSetUserFormatters(cmsHTRANSFORM hTransform, DWORD dwInput, cmsFORMATTER Input, |
| DWORD dwOutput, cmsFORMATTER Output) |
| { |
| _LPcmsTRANSFORM xform = (_LPcmsTRANSFORM) (LPSTR) hTransform; |
| |
| if (Input != NULL) { |
| xform ->FromInput = (_cmsFIXFN) Input; |
| xform ->InputFormat = dwInput; |
| } |
| |
| if (Output != NULL) { |
| xform ->ToOutput = (_cmsFIXFN) Output; |
| xform ->OutputFormat = dwOutput; |
| } |
| |
| } |
| |
| void LCMSEXPORT cmsGetUserFormatters(cmsHTRANSFORM hTransform, |
| LPDWORD InputFormat, cmsFORMATTER* Input, |
| LPDWORD OutputFormat, cmsFORMATTER* Output) |
| { |
| _LPcmsTRANSFORM xform = (_LPcmsTRANSFORM) (LPSTR) hTransform; |
| |
| if (Input) *Input = (cmsFORMATTER) xform ->FromInput; |
| if (InputFormat) *InputFormat = xform -> InputFormat; |
| if (Output) *Output = (cmsFORMATTER) xform ->ToOutput; |
| if (OutputFormat) *OutputFormat = xform -> OutputFormat; |
| } |
| |
| |
| // Change format of yet existing transform. No colorspace checking is performed |
| |
| void LCMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, |
| DWORD dwInputFormat, |
| DWORD dwOutputFormat) |
| { |
| |
| cmsSetUserFormatters(hTransform, |
| dwInputFormat, |
| (cmsFORMATTER) _cmsIdentifyInputFormat((_LPcmsTRANSFORM) hTransform, dwInputFormat), |
| dwOutputFormat, |
| (cmsFORMATTER) _cmsIdentifyOutputFormat((_LPcmsTRANSFORM) hTransform, dwOutputFormat)); |
| } |