Compare commits

...

44 Commits

Author SHA1 Message Date
mayeut
f0dd842b11 Fix warning
applications\codec\convertpng.c(465) : warning C4018: '<' :
signed/unsigned mismatch
2015-11-07 01:29:43 +01:00
mayeut
96c3a8315b PNG support enhancement
Update #611
2015-11-05 22:44:58 +01:00
mayeut
6711fa669a BMP support enhancement
Update #611
2015-11-05 00:29:37 +01:00
mayeut
935816e8c9 Update TIFF conversion to support more bit depth.
Update #611
2015-11-03 22:34:43 +01:00
mayeut
c0abb808f5 Fix invalid read in pngtoimage 2015-10-18 19:10:31 +02:00
mayeut
348e96e44b resets resno_decoded for each tile
Update #574
2015-10-18 18:58:54 +02:00
mayeut
e94720fea0 Fix ycc_to_rgb conversions
Update #574
2015-10-18 18:27:14 +02:00
mayeut
04291bf0ab Fix typo 2015-10-18 18:15:12 +02:00
mayeut
46440fe368 Fix some calculations in tcd_malloc_encode and tcd_malloc_decode_tile
Fix #388
2015-10-18 18:10:38 +02:00
mayeut
9cf9018ffc Update to libtiff 4.0.4 2015-10-18 17:18:21 +02:00
mayeut
001cd957ba Update to libpng 1.6.17 2015-10-18 16:45:42 +02:00
mayeut
a024c148fc Update to lib 1.2.8 2015-10-18 16:39:45 +02:00
mayeut
a4bd2ed06e Update to libcms2-2.6 2015-10-18 16:31:49 +02:00
mayeut
66f65919cf Update color_apply_icc_profile 2015-10-18 16:24:51 +02:00
mayeut
7ad3e2a870 Add "-p", "-force-rgb" and "-upsample" options to j2k_to_image
Fix #606
2015-10-18 16:07:40 +02:00
mayeut
9542c08d62 Don't rely on float equality
Fix #591
2015-10-15 15:52:01 +02:00
mayeut
cbaa2d7d98 Fix j2k_validate_encode 2015-10-15 15:48:02 +02:00
mayeut
650df81e09 Use -ffast-math only for compilation
Updates #488
Closes #554
2015-10-15 14:59:36 +02:00
Antonin Descampe
618e50954f Fixes overflow when high number of decompositions
Update #603
2015-10-09 16:56:54 +02:00
Antonin Descampe
959ebdab5e Gracefully reject codestreams with malformed SIZ markers
Update #603
2015-09-30 09:00:50 +02:00
Antonin Descampe
3cee252347 commented out some tests
No plan to fix this in 1.5 branch right now
2015-09-29 16:28:41 +02:00
Antonin Descampe
2a4101c60e Fixed non regression test config + ignore some files 2015-09-23 22:02:13 +02:00
Antonin Descampe
32b04ad49d Makes j2k_dump focus on parsing j2k codestreams, nothing else.
Avoid processing JP2 PCLR, CMAP, CDEF boxes and J2K packets in j2k_dump.
Fixes #595
2015-09-23 17:48:30 +02:00
Antonin Descampe
5e3fae7f48 update md5 signatures
Updates #604
2015-09-22 17:08:11 +02:00
Pedro Gimeno
4469a98cd7 Wrong TGA header generated by j2k_to_image
The TGA file writer used by j2k_to_image writes a wrong field to the
header for alpha-less images.

To reproduce:
1. Take any 24-bit j2k image with no alpha.
2. Convert it to TGA with j2k_to_image -i <image>.j2k -o <image>.tga
3. Open <image>.tga with Gimp.

When opened, the image will have a wrong alpha channel, because Gimp
uses a certain field in the header to determine if the image has alpha.
That field is saved wrongly by j2k_to_image for alpha-less images. Per
the TGA specification, Gimp is correct in this case.
2015-09-16 20:28:29 +02:00
Antonin Descampe
93c79f8fb1 modified checkmd5 2015-09-16 17:04:51 +02:00
Antonin Descampe
e755ebd1b0 backport fixes for issues #362 (-2863) and #393 on branch 1.5 2015-09-16 16:51:15 +02:00
Antonin Descampe
f35aaa8a82 added tests from master in 1.5 branch 2015-09-16 15:48:24 +02:00
Antonin Descampe
b44e07fe19 removed warnings when configuring with CMake 3.x on MacOS (update issue 443 for 1.5 branch) 2015-09-16 13:14:00 +02:00
Antonin Descampe
d3c0915992 added a validation procedure before launching actual decoding, fixed testempty tests 2015-09-16 13:05:20 +02:00
Antonin Descampe
c91e2099b1 disabled gX_colr kdu tests for now 2015-09-16 10:47:00 +02:00
Antonin Descampe
d0e85b0c52 fixed typo in CMakeLists.txt preventing use of libpng 2015-09-15 18:21:07 +02:00
Antonin Descampe
31e35fcf7b preventde seg fault when unknown long options and fixed ability to use USE_SYSTEM_GETOPT 2015-09-15 18:00:52 +02:00
Antonin Descampe
2d47938b25 added testempty0 test 2015-09-15 15:49:58 +02:00
Antonin Descampe
2e508f1c89 backport issue #80 to 1.5 branch 2015-09-15 15:42:17 +02:00
Antonin Descampe
f8013bec95 update conformance test files on 1.5 branch 2015-09-15 15:11:12 +02:00
Antonin Descampe
770e81eebc Fixed "unsupported platform" error 2015-09-14 17:03:03 +02:00
Antonin Descampe
2c3f5c269a [1.5] added int64_t define for win platforms in int.h so that r2990 actually workswith windows 2015-01-27 16:51:27 +00:00
Antonin Descampe
0ec0b2594c [1.5] fixed int_ceildivpow2 implementation (backport from trunk)
Update issue 388
2015-01-08 23:18:52 +00:00
Mathieu Malaterre
2eebb05ca2 [1.5] Fix a typo in comments 2014-04-01 13:55:28 +00:00
Mathieu Malaterre
ff72d131ed [1.5] Rework r2827. getopt was still being used in java binding
Update issue 301
2014-04-01 13:40:41 +00:00
Mathieu Malaterre
7d6d19c473 [1.5] Rework r2769. getopt was still being used in mj2/jpwl codecs
Update issue 301
2014-04-01 13:32:02 +00:00
Mathieu Malaterre
78053c44c8 [1.5] Make sure to compile java code with a defined source/target version 2014-04-01 11:54:43 +00:00
Mathieu Malaterre
902fe2569c [1.5] Tag this version to be the next 1.5.3 2014-04-01 11:54:21 +00:00
181 changed files with 61584 additions and 36532 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
CMakeLists.txt.user
*.bak

16
CMake/FindCPPCHECK.cmake Normal file
View File

@@ -0,0 +1,16 @@
# cppcheck
#
# Copyright (c) 2011 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
find_program(CPPCHECK_EXECUTABLE
cppcheck
)
mark_as_advanced(
CPPCHECK_EXECUTABLE
)

12
CMake/FindJPYLYZER.cmake Normal file
View File

@@ -0,0 +1,12 @@
#
# this module looks for JPYLYZER
# http://jpylyzer.openpreservation.org
#
find_program(JPYLYZER_EXECUTABLE
jpylyzer
)
mark_as_advanced(
JPYLYZER_EXECUTABLE
)

View File

@@ -11,6 +11,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
if (NOT (${CMAKE_VERSION} VERSION_LESS 3.0))
cmake_policy(SET CMP0042 NEW)
endif()
ENDIF(COMMAND CMAKE_POLICY)
IF(NOT OPENJPEG_NAMESPACE)
@@ -29,7 +32,7 @@ INCLUDE_REGULAR_EXPRESSION("^.*$")
# OPENJPEG version number, useful for packaging and doxygen doc:
SET(OPENJPEG_VERSION_MAJOR 1)
SET(OPENJPEG_VERSION_MINOR 5)
SET(OPENJPEG_VERSION_BUILD 2)
SET(OPENJPEG_VERSION_BUILD 3)
SET(OPENJPEG_VERSION
"${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}")
SET(PACKAGE_VERSION
@@ -200,7 +203,7 @@ IF(CMAKE_COMPILER_IS_GNUCC)
# For all builds, make sure openjpeg is std99 compliant:
# SET(CMAKE_C_FLAGS "-Wall -std=c99 ${CMAKE_C_FLAGS}") # FIXME: this setting prevented us from setting a coverage build.
# Do not use ffast-math for all build, it would produce incorrect results, only set for release:
SET(CMAKE_C_FLAGS_RELEASE "-ffast-math ${CMAKE_C_FLAGS_RELEASE}")
SET(OPENJPEG_LIBRARY_COMPILE_OPTIONS ${OPENJPEG_LIBRARY_COMPILE_OPTIONS} "$<$<CONFIG:Release>:-ffast-math>")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
#-----------------------------------------------------------------------------

View File

@@ -7,8 +7,12 @@ SET(openjpegjni_SRCS
${OPENJPEG_SOURCE_DIR}/applications/codec/index.c
${OPENJPEG_SOURCE_DIR}/applications/codec/convert.c
#${OPENJPEG_SOURCE_DIR}/applications/common/color.c
${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
if(NOT USE_SYSTEM_GETOPT)
list(APPEND openjpegjni_SRCS
${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
endif()
# JNI binding:
find_package(JNI REQUIRED)
@@ -41,6 +45,14 @@ INSTALL(TARGETS openjpegjni
# build jar:
FIND_PACKAGE(Java 1.5 REQUIRED) # javac, jar
# User can override this:
if(NOT DEFINED JAVA_SOURCE_VERSION)
set(JAVA_SOURCE_VERSION 1.5)
endif()
if(NOT DEFINED JAVA_TARGET_VERSION)
set(JAVA_TARGET_VERSION 1.5)
endif()
# build dep list:
file(GLOB java_srcs "java-sources/org/openJpeg/*.java")
@@ -49,7 +61,9 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/classes)
# Build java
ADD_CUSTOM_COMMAND(
OUTPUT ${LIBRARY_OUTPUT_PATH}/openjpeg.jar
COMMAND ${Java_JAVAC_EXECUTABLE} -sourcepath "${CMAKE_CURRENT_SOURCE_DIR}/java-sources"
COMMAND ${Java_JAVAC_EXECUTABLE}
-source ${JAVA_SOURCE_VERSION} -target ${JAVA_TARGET_VERSION}
-sourcepath "${CMAKE_CURRENT_SOURCE_DIR}/java-sources"
${java_srcs} -d ${CMAKE_CURRENT_BINARY_DIR}/classes
COMMAND ${Java_JAR_EXECUTABLE} cvf ${LIBRARY_OUTPUT_PATH}/openjpeg.jar org
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/classes

View File

@@ -1721,7 +1721,7 @@ opj_image_t* loadImage(opj_cparameters_t *parameters, JNIEnv *env, jobject obj,
len = (*env)->GetArrayLength(env, jba);
jbBody = (*env)->GetPrimitiveArrayCritical(env, jba, &isCopy);
/* printf("C: before transfering 8 bpp image\n"); */
/* printf("C: before transferring 8 bpp image\n"); */
if (comp->sgnd) {
for(i=0; i< len;i++) {
comp->data[i] = (char) jbBody[i];
@@ -1740,7 +1740,7 @@ opj_image_t* loadImage(opj_cparameters_t *parameters, JNIEnv *env, jobject obj,
len = (*env)->GetArrayLength(env, jsa);
jsBody = (*env)->GetPrimitiveArrayCritical(env, jsa, &isCopy);
/*printf("C: before transfering 16 bpp image\n"); */
/*printf("C: before transferring 16 bpp image\n"); */
if (comp->sgnd) {
/* Special behaviour to deal with signed elements ?? */
comp->data[i] = (short) jsBody[i];
@@ -1761,7 +1761,7 @@ opj_image_t* loadImage(opj_cparameters_t *parameters, JNIEnv *env, jobject obj,
shift = compno*8;
jiBody = (*env)->GetPrimitiveArrayCritical(env, jia, &isCopy);
/*printf("C: before transfering 24 bpp image (component %d, signed = %d)\n", compno, comp->sgnd);*/
/*printf("C: before transferring 24 bpp image (component %d, signed = %d)\n", compno, comp->sgnd);*/
if (comp->sgnd) {
/* Special behaviour to deal with signed elements ?? XXXXX */
for(i=0; i< len;i++) {

View File

@@ -615,7 +615,7 @@ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2Kto
/* printf("C: %d bytes read from file\n",file_length); */
} else {
/* Preparing the transfer of the codestream from Java to C */
/* printf("C: before transfering codestream\n"); */
/* printf("C: before transferring codestream\n"); */
fid = (*env)->GetFieldID(env, cls,"compressedStream", "[B");
jba = (*env)->GetObjectField(env, obj, fid);
file_length = (*env)->GetArrayLength(env, jba);
@@ -797,7 +797,7 @@ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2Kto
jia = (*env)->GetObjectField(env, obj, fid);
jiBody = (*env)->GetIntArrayElements(env, jia, 0);
ptrIBody = jiBody;
printf("C: transfering image24: %d int to Java pointer=%d\n",image->numcomps*w*h, ptrIBody);
printf("C: transferring image24: %d int to Java pointer=%d\n",image->numcomps*w*h, ptrIBody);
for (i=0; i<w*h; i++) {
tempUC = (unsigned char)(ptr[i]);
@@ -823,7 +823,7 @@ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2Kto
} else { /* 1 component 8 or 16 bpp image */
ptr = image->comps[0].data;
printf("C: before transfering a %d bpp image to java (length = %d)\n",image->comps[0].prec ,w*h);
printf("C: before transferring a %d bpp image to java (length = %d)\n",image->comps[0].prec ,w*h);
if (image->comps[0].prec<=8) {
fid = (*env)->GetFieldID(env, cls,"image8", "[B");
jba = (*env)->GetObjectField(env, obj, fid);
@@ -838,7 +838,7 @@ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2Kto
max_value = 255;
}
#endif
/* printf("C: transfering %d shorts to Java image8 pointer = %d\n", wr*hr,ptrSBody); */
/* printf("C: transferring %d shorts to Java image8 pointer = %d\n", wr*hr,ptrSBody); */
for (i=0; i<w*h; i++) {
tempUC = (unsigned char) (ptr[i]);
#ifdef CHECK_THRESHOLDS
@@ -866,7 +866,7 @@ JNIEXPORT jint JNICALL Java_org_openJpeg_OpenJPEGJavaDecoder_internalDecodeJ2Kto
}
printf("C: minValue = %d, maxValue = %d\n", min_value, max_value);
#endif
printf("C: transfering %d shorts to Java image16 pointer = %d\n", w*h,ptrSBody);
printf("C: transferring %d shorts to Java image16 pointer = %d\n", w*h,ptrSBody);
for (i=0; i<w*h; i++) {
tempS = (short) (ptr[i]);
#ifdef CHECK_THRESHOLDS

View File

@@ -3,6 +3,9 @@
# First thing define the common source:
SET(common_SRCS
convert.c
converttif.c
convertbmp.c
convertpng.c
index.c
${OPENJPEG_SOURCE_DIR}/applications/common/color.c
)

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,21 @@ typedef struct raw_cparameters {
/*@}*/
} raw_cparameters_t;
/* Component precision scaling */
void clip_component(opj_image_comp_t* component, int precision);
void scale_component(opj_image_comp_t* component, int precision);
/* planar / interleaved conversions */
typedef void (* convert_32s_CXPX)(const int* pSrc, int* const* pDst, size_t length);
extern const convert_32s_CXPX convert_32s_CXPX_LUT[5];
typedef void (* convert_32s_PXCX)(int const* const* pSrc, int* pDst, size_t length, int adjust);
extern const convert_32s_PXCX convert_32s_PXCX_LUT[5];
/* bit depth conversions */
typedef void (* convert_XXx32s_C1R)(const unsigned char* pSrc, int* pDst, size_t length);
extern const convert_XXx32s_C1R convert_XXu32s_C1R_LUT[9]; /* up to 8bpp */
typedef void (* convert_32sXXx_C1R)(const int* pSrc, unsigned char* pDst, size_t length);
extern const convert_32sXXx_C1R convert_32sXXu_C1R_LUT[9]; /* up to 8bpp */
/* TGA conversion */
opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters);
int imagetotga(opj_image_t * image, const char *outfile);

View File

@@ -0,0 +1,995 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2014, Professor Benoit Macq
* Copyright (c) 2001-2003, David Janssens
* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux
* Copyright (c) 2003-2014, Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2006-2007, Parvatha Elangovan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "openjpeg.h"
#include "convert.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#if defined(_WIN32)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#error unsupported platform
#endif
#endif
typedef struct {
uint16_t bfType; /* 'BM' for Bitmap (19776) */
uint32_t bfSize; /* Size of the file */
uint16_t bfReserved1; /* Reserved : 0 */
uint16_t bfReserved2; /* Reserved : 0 */
uint32_t bfOffBits; /* Offset */
} OPJ_BITMAPFILEHEADER;
typedef struct {
uint32_t biSize; /* Size of the structure in bytes */
uint32_t biWidth; /* Width of the image in pixels */
uint32_t biHeight; /* Heigth of the image in pixels */
uint16_t biPlanes; /* 1 */
uint16_t biBitCount; /* Number of color bits by pixels */
uint32_t biCompression; /* Type of encoding 0: none 1: RLE8 2: RLE4 */
uint32_t biSizeImage; /* Size of the image in bytes */
uint32_t biXpelsPerMeter; /* Horizontal (X) resolution in pixels/meter */
uint32_t biYpelsPerMeter; /* Vertical (Y) resolution in pixels/meter */
uint32_t biClrUsed; /* Number of color used in the image (0: ALL) */
uint32_t biClrImportant; /* Number of important color (0: ALL) */
uint32_t biRedMask; /* Red channel bit mask */
uint32_t biGreenMask; /* Green channel bit mask */
uint32_t biBlueMask; /* Blue channel bit mask */
uint32_t biAlphaMask; /* Alpha channel bit mask */
uint32_t biColorSpaceType; /* Color space type */
uint8_t biColorSpaceEP[36]; /* Color space end points */
uint32_t biRedGamma; /* Red channel gamma */
uint32_t biGreenGamma; /* Green channel gamma */
uint32_t biBlueGamma; /* Blue channel gamma */
uint32_t biIntent; /* Intent */
uint32_t biIccProfileData; /* ICC profile data */
uint32_t biIccProfileSize; /* ICC profile size */
uint32_t biReserved; /* Reserved */
} OPJ_BITMAPINFOHEADER;
static void opj_applyLUT8u_8u32s_C1R(
uint8_t const* pSrc, int32_t srcStride,
int32_t* pDst, int32_t dstStride,
uint8_t const* pLUT,
uint32_t width, uint32_t height)
{
uint32_t y;
for (y = height; y != 0U; --y) {
uint32_t x;
for(x = 0; x < width; x++)
{
pDst[x] = (int32_t)pLUT[pSrc[x]];
}
pSrc += srcStride;
pDst += dstStride;
}
}
static void opj_applyLUT8u_8u32s_C1P3R(
uint8_t const* pSrc, int32_t srcStride,
int32_t* const* pDst, int32_t const* pDstStride,
uint8_t const* const* pLUT,
uint32_t width, uint32_t height)
{
uint32_t y;
int32_t* pR = pDst[0];
int32_t* pG = pDst[1];
int32_t* pB = pDst[2];
uint8_t const* pLUT_R = pLUT[0];
uint8_t const* pLUT_G = pLUT[1];
uint8_t const* pLUT_B = pLUT[2];
for (y = height; y != 0U; --y) {
uint32_t x;
for(x = 0; x < width; x++)
{
uint8_t idx = pSrc[x];
pR[x] = (int32_t)pLUT_R[idx];
pG[x] = (int32_t)pLUT_G[idx];
pB[x] = (int32_t)pLUT_B[idx];
}
pSrc += srcStride;
pR += pDstStride[0];
pG += pDstStride[1];
pB += pDstStride[2];
}
}
static void bmp24toimage(const uint8_t* pData, uint32_t stride, opj_image_t* image)
{
int index;
uint32_t width, height;
uint32_t x, y;
const uint8_t *pSrc = NULL;
width = image->comps[0].w;
height = image->comps[0].h;
index = 0;
pSrc = pData + (height - 1U) * stride;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
image->comps[0].data[index] = (int32_t)pSrc[3*x+2]; /* R */
image->comps[1].data[index] = (int32_t)pSrc[3*x+1]; /* G */
image->comps[2].data[index] = (int32_t)pSrc[3*x+0]; /* B */
index++;
}
pSrc -= stride;
}
}
static void bmp_mask_get_shift_and_prec(uint32_t mask, uint32_t* shift, uint32_t* prec)
{
uint32_t l_shift, l_prec;
l_shift = l_prec = 0U;
if (mask != 0U) {
while ((mask & 1U) == 0U) {
mask >>= 1;
l_shift++;
}
while (mask & 1U) {
mask >>= 1;
l_prec++;
}
}
*shift = l_shift; *prec = l_prec;
}
static void bmpmask32toimage(const uint8_t* pData, uint32_t stride, opj_image_t* image, uint32_t redMask, uint32_t greenMask, uint32_t blueMask, uint32_t alphaMask)
{
int index;
uint32_t width, height;
uint32_t x, y;
const uint8_t *pSrc = NULL;
opj_bool hasAlpha = OPJ_FALSE;
uint32_t redShift, redPrec;
uint32_t greenShift, greenPrec;
uint32_t blueShift, bluePrec;
uint32_t alphaShift, alphaPrec;
width = image->comps[0].w;
height = image->comps[0].h;
hasAlpha = image->numcomps > 3U;
bmp_mask_get_shift_and_prec(redMask, &redShift, &redPrec);
bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec);
bmp_mask_get_shift_and_prec(blueMask, &blueShift, &bluePrec);
bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec);
image->comps[0].bpp = redPrec;
image->comps[0].prec = redPrec;
image->comps[1].bpp = greenPrec;
image->comps[1].prec = greenPrec;
image->comps[2].bpp = bluePrec;
image->comps[2].prec = bluePrec;
if (hasAlpha) {
image->comps[3].bpp = alphaPrec;
image->comps[3].prec = alphaPrec;
}
index = 0;
pSrc = pData + (height - 1U) * stride;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
uint32_t value = 0U;
value |= ((uint32_t)pSrc[4*x+0]) << 0;
value |= ((uint32_t)pSrc[4*x+1]) << 8;
value |= ((uint32_t)pSrc[4*x+2]) << 16;
value |= ((uint32_t)pSrc[4*x+3]) << 24;
image->comps[0].data[index] = (int32_t)((value & redMask) >> redShift); /* R */
image->comps[1].data[index] = (int32_t)((value & greenMask) >> greenShift); /* G */
image->comps[2].data[index] = (int32_t)((value & blueMask) >> blueShift); /* B */
if (hasAlpha) {
image->comps[3].data[index] = (int32_t)((value & alphaMask) >> alphaShift); /* A */
}
index++;
}
pSrc -= stride;
}
}
static void bmpmask16toimage(const uint8_t* pData, uint32_t stride, opj_image_t* image, uint32_t redMask, uint32_t greenMask, uint32_t blueMask, uint32_t alphaMask)
{
int index;
uint32_t width, height;
uint32_t x, y;
const uint8_t *pSrc = NULL;
opj_bool hasAlpha = OPJ_FALSE;
uint32_t redShift, redPrec;
uint32_t greenShift, greenPrec;
uint32_t blueShift, bluePrec;
uint32_t alphaShift, alphaPrec;
width = image->comps[0].w;
height = image->comps[0].h;
hasAlpha = image->numcomps > 3U;
bmp_mask_get_shift_and_prec(redMask, &redShift, &redPrec);
bmp_mask_get_shift_and_prec(greenMask, &greenShift, &greenPrec);
bmp_mask_get_shift_and_prec(blueMask, &blueShift, &bluePrec);
bmp_mask_get_shift_and_prec(alphaMask, &alphaShift, &alphaPrec);
image->comps[0].bpp = redPrec;
image->comps[0].prec = redPrec;
image->comps[1].bpp = greenPrec;
image->comps[1].prec = greenPrec;
image->comps[2].bpp = bluePrec;
image->comps[2].prec = bluePrec;
if (hasAlpha) {
image->comps[3].bpp = alphaPrec;
image->comps[3].prec = alphaPrec;
}
index = 0;
pSrc = pData + (height - 1U) * stride;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++)
{
uint32_t value = 0U;
value |= ((uint32_t)pSrc[2*x+0]) << 0;
value |= ((uint32_t)pSrc[2*x+1]) << 8;
image->comps[0].data[index] = (int32_t)((value & redMask) >> redShift); /* R */
image->comps[1].data[index] = (int32_t)((value & greenMask) >> greenShift); /* G */
image->comps[2].data[index] = (int32_t)((value & blueMask) >> blueShift); /* B */
if (hasAlpha) {
image->comps[3].data[index] = (int32_t)((value & alphaMask) >> alphaShift); /* A */
}
index++;
}
pSrc -= stride;
}
}
static opj_image_t* bmp8toimage(const uint8_t* pData, uint32_t stride, opj_image_t* image, uint8_t const* const* pLUT)
{
uint32_t width, height;
const uint8_t *pSrc = NULL;
width = image->comps[0].w;
height = image->comps[0].h;
pSrc = pData + (height - 1U) * stride;
if (image->numcomps == 1U) {
opj_applyLUT8u_8u32s_C1R(pSrc, -(int32_t)stride, image->comps[0].data, (int32_t)width, pLUT[0], width, height);
}
else {
int32_t* pDst[3];
int32_t pDstStride[3];
pDst[0] = image->comps[0].data; pDst[1] = image->comps[1].data; pDst[2] = image->comps[2].data;
pDstStride[0] = (int32_t)width; pDstStride[1] = (int32_t)width; pDstStride[2] = (int32_t)width;
opj_applyLUT8u_8u32s_C1P3R(pSrc, -(int32_t)stride, pDst, pDstStride, pLUT, width, height);
}
return image;
}
static opj_bool bmp_read_file_header(FILE* IN, OPJ_BITMAPFILEHEADER* header)
{
header->bfType = (uint16_t)getc(IN);
header->bfType |= (uint16_t)((uint32_t)getc(IN) << 8);
if (header->bfType != 19778) {
fprintf(stderr,"Error, not a BMP file!\n");
return OPJ_FALSE;
}
/* FILE HEADER */
/* ------------- */
header->bfSize = (uint32_t)getc(IN);
header->bfSize |= (uint32_t)getc(IN) << 8;
header->bfSize |= (uint32_t)getc(IN) << 16;
header->bfSize |= (uint32_t)getc(IN) << 24;
header->bfReserved1 = (uint16_t)getc(IN);
header->bfReserved1 |= (uint16_t)((uint32_t)getc(IN) << 8);
header->bfReserved2 = (uint16_t)getc(IN);
header->bfReserved2 |= (uint16_t)((uint32_t)getc(IN) << 8);
header->bfOffBits = (uint32_t)getc(IN);
header->bfOffBits |= (uint32_t)getc(IN) << 8;
header->bfOffBits |= (uint32_t)getc(IN) << 16;
header->bfOffBits |= (uint32_t)getc(IN) << 24;
return OPJ_TRUE;
}
static opj_bool bmp_read_info_header(FILE* IN, OPJ_BITMAPINFOHEADER* header)
{
memset(header, 0, sizeof(*header));
/* INFO HEADER */
/* ------------- */
header->biSize = (uint32_t)getc(IN);
header->biSize |= (uint32_t)getc(IN) << 8;
header->biSize |= (uint32_t)getc(IN) << 16;
header->biSize |= (uint32_t)getc(IN) << 24;
switch (header->biSize) {
case 12U: /* BITMAPCOREHEADER */
case 40U: /* BITMAPINFOHEADER */
case 52U: /* BITMAPV2INFOHEADER */
case 56U: /* BITMAPV3INFOHEADER */
case 108U: /* BITMAPV4HEADER */
case 124U: /* BITMAPV5HEADER */
break;
default:
fprintf(stderr,"Error, unknown BMP header size %d\n", header->biSize);
return OPJ_FALSE;
}
header->biWidth = (uint32_t)getc(IN);
header->biWidth |= (uint32_t)getc(IN) << 8;
header->biWidth |= (uint32_t)getc(IN) << 16;
header->biWidth |= (uint32_t)getc(IN) << 24;
header->biHeight = (uint32_t)getc(IN);
header->biHeight |= (uint32_t)getc(IN) << 8;
header->biHeight |= (uint32_t)getc(IN) << 16;
header->biHeight |= (uint32_t)getc(IN) << 24;
header->biPlanes = (uint16_t)getc(IN);
header->biPlanes |= (uint16_t)((uint32_t)getc(IN) << 8);
header->biBitCount = (uint16_t)getc(IN);
header->biBitCount |= (uint16_t)((uint32_t)getc(IN) << 8);
if(header->biSize >= 40U) {
header->biCompression = (uint32_t)getc(IN);
header->biCompression |= (uint32_t)getc(IN) << 8;
header->biCompression |= (uint32_t)getc(IN) << 16;
header->biCompression |= (uint32_t)getc(IN) << 24;
header->biSizeImage = (uint32_t)getc(IN);
header->biSizeImage |= (uint32_t)getc(IN) << 8;
header->biSizeImage |= (uint32_t)getc(IN) << 16;
header->biSizeImage |= (uint32_t)getc(IN) << 24;
header->biXpelsPerMeter = (uint32_t)getc(IN);
header->biXpelsPerMeter |= (uint32_t)getc(IN) << 8;
header->biXpelsPerMeter |= (uint32_t)getc(IN) << 16;
header->biXpelsPerMeter |= (uint32_t)getc(IN) << 24;
header->biYpelsPerMeter = (uint32_t)getc(IN);
header->biYpelsPerMeter |= (uint32_t)getc(IN) << 8;
header->biYpelsPerMeter |= (uint32_t)getc(IN) << 16;
header->biYpelsPerMeter |= (uint32_t)getc(IN) << 24;
header->biClrUsed = (uint32_t)getc(IN);
header->biClrUsed |= (uint32_t)getc(IN) << 8;
header->biClrUsed |= (uint32_t)getc(IN) << 16;
header->biClrUsed |= (uint32_t)getc(IN) << 24;
header->biClrImportant = (uint32_t)getc(IN);
header->biClrImportant |= (uint32_t)getc(IN) << 8;
header->biClrImportant |= (uint32_t)getc(IN) << 16;
header->biClrImportant |= (uint32_t)getc(IN) << 24;
}
if(header->biSize >= 56U) {
header->biRedMask = (uint32_t)getc(IN);
header->biRedMask |= (uint32_t)getc(IN) << 8;
header->biRedMask |= (uint32_t)getc(IN) << 16;
header->biRedMask |= (uint32_t)getc(IN) << 24;
header->biGreenMask = (uint32_t)getc(IN);
header->biGreenMask |= (uint32_t)getc(IN) << 8;
header->biGreenMask |= (uint32_t)getc(IN) << 16;
header->biGreenMask |= (uint32_t)getc(IN) << 24;
header->biBlueMask = (uint32_t)getc(IN);
header->biBlueMask |= (uint32_t)getc(IN) << 8;
header->biBlueMask |= (uint32_t)getc(IN) << 16;
header->biBlueMask |= (uint32_t)getc(IN) << 24;
header->biAlphaMask = (uint32_t)getc(IN);
header->biAlphaMask |= (uint32_t)getc(IN) << 8;
header->biAlphaMask |= (uint32_t)getc(IN) << 16;
header->biAlphaMask |= (uint32_t)getc(IN) << 24;
}
if(header->biSize >= 108U) {
header->biColorSpaceType = (uint32_t)getc(IN);
header->biColorSpaceType |= (uint32_t)getc(IN) << 8;
header->biColorSpaceType |= (uint32_t)getc(IN) << 16;
header->biColorSpaceType |= (uint32_t)getc(IN) << 24;
if (fread(&(header->biColorSpaceEP), 1U, sizeof(header->biColorSpaceEP), IN) != sizeof(header->biColorSpaceEP)) {
fprintf(stderr,"Error, can't read BMP header\n");
return OPJ_FALSE;
}
header->biRedGamma = (uint32_t)getc(IN);
header->biRedGamma |= (uint32_t)getc(IN) << 8;
header->biRedGamma |= (uint32_t)getc(IN) << 16;
header->biRedGamma |= (uint32_t)getc(IN) << 24;
header->biGreenGamma = (uint32_t)getc(IN);
header->biGreenGamma |= (uint32_t)getc(IN) << 8;
header->biGreenGamma |= (uint32_t)getc(IN) << 16;
header->biGreenGamma |= (uint32_t)getc(IN) << 24;
header->biBlueGamma = (uint32_t)getc(IN);
header->biBlueGamma |= (uint32_t)getc(IN) << 8;
header->biBlueGamma |= (uint32_t)getc(IN) << 16;
header->biBlueGamma |= (uint32_t)getc(IN) << 24;
}
if(header->biSize >= 124U) {
header->biIntent = (uint32_t)getc(IN);
header->biIntent |= (uint32_t)getc(IN) << 8;
header->biIntent |= (uint32_t)getc(IN) << 16;
header->biIntent |= (uint32_t)getc(IN) << 24;
header->biIccProfileData = (uint32_t)getc(IN);
header->biIccProfileData |= (uint32_t)getc(IN) << 8;
header->biIccProfileData |= (uint32_t)getc(IN) << 16;
header->biIccProfileData |= (uint32_t)getc(IN) << 24;
header->biIccProfileSize = (uint32_t)getc(IN);
header->biIccProfileSize |= (uint32_t)getc(IN) << 8;
header->biIccProfileSize |= (uint32_t)getc(IN) << 16;
header->biIccProfileSize |= (uint32_t)getc(IN) << 24;
header->biReserved = (uint32_t)getc(IN);
header->biReserved |= (uint32_t)getc(IN) << 8;
header->biReserved |= (uint32_t)getc(IN) << 16;
header->biReserved |= (uint32_t)getc(IN) << 24;
}
return OPJ_TRUE;
}
static opj_bool bmp_read_raw_data(FILE* IN, uint8_t* pData, uint32_t stride, uint32_t width, uint32_t height)
{
OPJ_ARG_NOT_USED(width);
if ( fread(pData, sizeof(uint8_t), stride * height, IN) != (stride * height) )
{
fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
return OPJ_FALSE;
}
return OPJ_TRUE;
}
static opj_bool bmp_read_rle8_data(FILE* IN, uint8_t* pData, uint32_t stride, uint32_t width, uint32_t height)
{
uint32_t x, y;
uint8_t *pix;
const uint8_t *beyond;
beyond = pData + stride * height;
pix = pData;
x = y = 0U;
while (y < height)
{
int c = getc(IN);
if (c) {
int j;
uint8_t c1 = (uint8_t)getc(IN);
for (j = 0; (j < c) && (x < width) && ((size_t)pix < (size_t)beyond); j++, x++, pix++) {
*pix = c1;
}
}
else {
c = getc(IN);
if (c == 0x00) { /* EOL */
x = 0;
++y;
pix = pData + y * stride + x;
}
else if (c == 0x01) { /* EOP */
break;
}
else if (c == 0x02) { /* MOVE by dxdy */
c = getc(IN);
x += (uint32_t)c;
c = getc(IN);
y += (uint32_t)c;
pix = pData + y * stride + x;
}
else /* 03 .. 255 */
{
int j;
for (j = 0; (j < c) && (x < width) && ((size_t)pix < (size_t)beyond); j++, x++, pix++)
{
uint8_t c1 = (uint8_t)getc(IN);
*pix = c1;
}
if ((uint32_t)c & 1U) { /* skip padding byte */
getc(IN);
}
}
}
}/* while() */
return OPJ_TRUE;
}
static opj_bool bmp_read_rle4_data(FILE* IN, uint8_t* pData, uint32_t stride, uint32_t width, uint32_t height)
{
uint32_t x, y;
uint8_t *pix;
const uint8_t *beyond;
beyond = pData + stride * height;
pix = pData;
x = y = 0U;
while(y < height)
{
int c = getc(IN);
if(c == EOF) break;
if(c) {/* encoded mode */
int j;
uint8_t c1 = (uint8_t)getc(IN);
for (j = 0; (j < c) && (x < width) && ((size_t)pix < (size_t)beyond); j++, x++, pix++) {
*pix = (uint8_t)((j&1) ? (c1 & 0x0fU) : ((c1>>4)&0x0fU));
}
}
else { /* absolute mode */
c = getc(IN);
if(c == EOF) break;
if(c == 0x00) { /* EOL */
x = 0; y++; pix = pData + y * stride;
}
else if(c == 0x01) { /* EOP */
break;
}
else if(c == 0x02) { /* MOVE by dxdy */
c = getc(IN); x += (uint32_t)c;
c = getc(IN); y += (uint32_t)c;
pix = pData + y * stride + x;
}
else { /* 03 .. 255 : absolute mode */
int j;
uint8_t c1 = 0U;
for (j = 0; (j < c) && (x < width) && ((size_t)pix < (size_t)beyond); j++, x++, pix++) {
if((j&1) == 0) {
c1 = (uint8_t)getc(IN);
}
*pix = (uint8_t)((j&1) ? (c1 & 0x0fU) : ((c1>>4)&0x0fU));
}
if(((c&3) == 1) || ((c&3) == 2)) { /* skip padding byte */
getc(IN);
}
}
}
} /* while(y < height) */
return OPJ_TRUE;
}
opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters)
{
opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */
uint8_t lut_R[256], lut_G[256], lut_B[256];
uint8_t const* pLUT[3];
opj_image_t * image = NULL;
FILE *IN;
OPJ_BITMAPFILEHEADER File_h;
OPJ_BITMAPINFOHEADER Info_h;
uint32_t i, palette_len, numcmpts = 1U;
opj_bool l_result = OPJ_FALSE;
uint8_t* pData = NULL;
uint32_t stride;
pLUT[0] = lut_R; pLUT[1] = lut_G; pLUT[2] = lut_B;
IN = fopen(filename, "rb");
if (!IN)
{
fprintf(stderr, "Failed to open %s for reading !!\n", filename);
return NULL;
}
if (!bmp_read_file_header(IN, &File_h)) {
fclose(IN);
return NULL;
}
if (!bmp_read_info_header(IN, &Info_h)) {
fclose(IN);
return NULL;
}
/* Load palette */
if (Info_h.biBitCount <= 8U)
{
memset(&lut_R[0], 0, sizeof(lut_R));
memset(&lut_G[0], 0, sizeof(lut_G));
memset(&lut_B[0], 0, sizeof(lut_B));
palette_len = Info_h.biClrUsed;
if((palette_len == 0U) && (Info_h.biBitCount <= 8U)) {
palette_len = (1U << Info_h.biBitCount);
}
if (palette_len > 256U) {
palette_len = 256U;
}
if (palette_len > 0U) {
uint8_t has_color = 0U;
for (i = 0U; i < palette_len; i++) {
lut_B[i] = (uint8_t)getc(IN);
lut_G[i] = (uint8_t)getc(IN);
lut_R[i] = (uint8_t)getc(IN);
(void)getc(IN); /* padding */
has_color |= (lut_B[i] ^ lut_G[i]) | (lut_G[i] ^ lut_R[i]);
}
if(has_color) {
numcmpts = 3U;
}
}
} else {
numcmpts = 3U;
if ((Info_h.biCompression == 3) && (Info_h.biAlphaMask != 0U)) {
numcmpts++;
}
}
stride = ((Info_h.biWidth * Info_h.biBitCount + 31U) / 32U) * 4U; /* rows are aligned on 32bits */
if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /* RLE 4 gets decoded as 8 bits data for now... */
stride = ((Info_h.biWidth * 8U + 31U) / 32U) * 4U;
}
pData = (uint8_t *) calloc(1, stride * Info_h.biHeight * sizeof(uint8_t));
if (pData == NULL) {
fclose(IN);
return NULL;
}
/* Place the cursor at the beginning of the image information */
fseek(IN, 0, SEEK_SET);
fseek(IN, (long)File_h.bfOffBits, SEEK_SET);
switch (Info_h.biCompression) {
case 0:
case 3:
/* read raw data */
l_result = bmp_read_raw_data(IN, pData, stride, Info_h.biWidth, Info_h.biHeight);
break;
case 1:
/* read rle8 data */
l_result = bmp_read_rle8_data(IN, pData, stride, Info_h.biWidth, Info_h.biHeight);
break;
case 2:
/* read rle4 data */
l_result = bmp_read_rle4_data(IN, pData, stride, Info_h.biWidth, Info_h.biHeight);
break;
default:
fprintf(stderr, "Unsupported BMP compression\n");
l_result = OPJ_FALSE;
break;
}
if (!l_result) {
free(pData);
fclose(IN);
return NULL;
}
/* create the image */
memset(&cmptparm[0], 0, sizeof(cmptparm));
for(i = 0; i < 4U; i++)
{
cmptparm[i].prec = 8;
cmptparm[i].bpp = 8;
cmptparm[i].sgnd = 0;
cmptparm[i].dx = parameters->subsampling_dx;
cmptparm[i].dy = parameters->subsampling_dy;
cmptparm[i].w = Info_h.biWidth;
cmptparm[i].h = Info_h.biHeight;
}
image = opj_image_create(numcmpts, &cmptparm[0], (numcmpts == 1U) ? CLRSPC_GRAY : CLRSPC_SRGB);
if(!image) {
fclose(IN);
free(pData);
return NULL;
}
/* if (numcmpts == 4U) {
image->comps[3].alpha = 1;
} */
/* set image offset and reference grid */
image->x0 = (uint32_t)parameters->image_offset_x0;
image->y0 = (uint32_t)parameters->image_offset_y0;
image->x1 = image->x0 + (Info_h.biWidth - 1U) * (uint32_t)parameters->subsampling_dx + 1U;
image->y1 = image->y0 + (Info_h.biHeight - 1U) * (uint32_t)parameters->subsampling_dy + 1U;
/* Read the data */
if (Info_h.biBitCount == 24 && Info_h.biCompression == 0) { /*RGB */
bmp24toimage(pData, stride, image);
}
else if (Info_h.biBitCount == 8 && Info_h.biCompression == 0) { /* RGB 8bpp Indexed */
bmp8toimage(pData, stride, image, pLUT);
}
else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { /*RLE8*/
bmp8toimage(pData, stride, image, pLUT);
}
else if (Info_h.biBitCount == 4 && Info_h.biCompression == 2) { /*RLE4*/
bmp8toimage(pData, stride, image, pLUT); /* RLE 4 gets decoded as 8 bits data for now */
}
else if (Info_h.biBitCount == 32 && Info_h.biCompression == 0) { /* RGBX */
bmpmask32toimage(pData, stride, image, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, 0x00000000U);
}
else if (Info_h.biBitCount == 32 && Info_h.biCompression == 3) { /* bitmask */
bmpmask32toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask, Info_h.biBlueMask, Info_h.biAlphaMask);
}
else if (Info_h.biBitCount == 16 && Info_h.biCompression == 0) { /* RGBX */
bmpmask16toimage(pData, stride, image, 0x7C00U, 0x03E0U, 0x001FU, 0x0000U);
}
else if (Info_h.biBitCount == 16 && Info_h.biCompression == 3) { /* bitmask */
if ((Info_h.biRedMask == 0U) && (Info_h.biGreenMask == 0U) && (Info_h.biBlueMask == 0U)) {
Info_h.biRedMask = 0xF800U;
Info_h.biGreenMask = 0x07E0U;
Info_h.biBlueMask = 0x001FU;
}
bmpmask16toimage(pData, stride, image, Info_h.biRedMask, Info_h.biGreenMask, Info_h.biBlueMask, Info_h.biAlphaMask);
}
else {
opj_image_destroy(image);
image = NULL;
fprintf(stderr, "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n", Info_h.biBitCount);
}
free(pData);
fclose(IN);
return image;
}
int imagetobmp(opj_image_t * image, const char *outfile) {
int w, h;
int i, pad;
FILE *fdest = NULL;
int adjustR, adjustG, adjustB;
if (image->comps[0].prec < 8) {
fprintf(stderr, "Unsupported number of components: %d\n", image->comps[0].prec);
return 1;
}
if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
&& image->comps[1].dx == image->comps[2].dx
&& image->comps[0].dy == image->comps[1].dy
&& image->comps[1].dy == image->comps[2].dy
&& image->comps[0].prec == image->comps[1].prec
&& image->comps[1].prec == image->comps[2].prec) {
/* -->> -->> -->> -->>
24 bits color
<<-- <<-- <<-- <<-- */
fdest = fopen(outfile, "wb");
if (!fdest) {
fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
return 1;
}
w = (int)image->comps[0].w;
h = (int)image->comps[0].h;
fprintf(fdest, "BM");
/* FILE HEADER */
/* ------------- */
fprintf(fdest, "%c%c%c%c",
(uint8_t) (h * w * 3 + 3 * h * (w % 2) + 54) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,((54) >> 16) & 0xff, ((54) >> 24) & 0xff);
/* INFO HEADER */
/* ------------- */
fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) ((w) & 0xff),
(uint8_t) ((w) >> 8) & 0xff,
(uint8_t) ((w) >> 16) & 0xff,
(uint8_t) ((w) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) ((h) & 0xff),
(uint8_t) ((h) >> 8) & 0xff,
(uint8_t) ((h) >> 16) & 0xff,
(uint8_t) ((h) >> 24) & 0xff);
fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) (3 * h * w + 3 * h * (w % 2)) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff,
(uint8_t) ((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
if (image->comps[0].prec > 8) {
adjustR = (int)image->comps[0].prec - 8;
printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
}
else
adjustR = 0;
if (image->comps[1].prec > 8) {
adjustG = (int)image->comps[1].prec - 8;
printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec);
}
else
adjustG = 0;
if (image->comps[2].prec > 8) {
adjustB = (int)image->comps[2].prec - 8;
printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec);
}
else
adjustB = 0;
for (i = 0; i < w * h; i++) {
uint8_t rc, gc, bc;
int r, g, b;
r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
r = ((r >> adjustR)+((r >> (adjustR-1))%2));
if(r > 255) r = 255; else if(r < 0) r = 0;
rc = (uint8_t)r;
g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
g = ((g >> adjustG)+((g >> (adjustG-1))%2));
if(g > 255) g = 255; else if(g < 0) g = 0;
gc = (uint8_t)g;
b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
b = ((b >> adjustB)+((b >> (adjustB-1))%2));
if(b > 255) b = 255; else if(b < 0) b = 0;
bc = (uint8_t)b;
fprintf(fdest, "%c%c%c", bc, gc, rc);
if ((i + 1) % w == 0) {
for (pad = (3 * w) % 4 ? 4 - (3 * w) % 4 : 0; pad > 0; pad--) /* ADD */
fprintf(fdest, "%c", 0);
}
}
fclose(fdest);
} else { /* Gray-scale */
/* -->> -->> -->> -->>
8 bits non code (Gray scale)
<<-- <<-- <<-- <<-- */
fdest = fopen(outfile, "wb");
if (!fdest) {
fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
return 1;
}
w = (int)image->comps[0].w;
h = (int)image->comps[0].h;
fprintf(fdest, "BM");
/* FILE HEADER */
/* ------------- */
fprintf(fdest, "%c%c%c%c", (uint8_t) (h * w + 54 + 1024 + h * (w % 2)) & 0xff,
(uint8_t) ((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff,
(uint8_t) ((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff,
(uint8_t) ((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff,
((54 + 1024) >> 16) & 0xff,
((54 + 1024) >> 24) & 0xff);
/* INFO HEADER */
/* ------------- */
fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) ((w) & 0xff),
(uint8_t) ((w) >> 8) & 0xff,
(uint8_t) ((w) >> 16) & 0xff,
(uint8_t) ((w) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) ((h) & 0xff),
(uint8_t) ((h) >> 8) & 0xff,
(uint8_t) ((h) >> 16) & 0xff,
(uint8_t) ((h) >> 24) & 0xff);
fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff);
fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (uint8_t) (h * w + h * (w % 2)) & 0xff,
(uint8_t) ((h * w + h * (w % 2)) >> 8) & 0xff,
(uint8_t) ((h * w + h * (w % 2)) >> 16) & 0xff,
(uint8_t) ((h * w + h * (w % 2)) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff);
if (image->comps[0].prec > 8) {
adjustR = (int)image->comps[0].prec - 8;
printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
}else
adjustR = 0;
for (i = 0; i < 256; i++) {
fprintf(fdest, "%c%c%c%c", i, i, i, 0);
}
for (i = 0; i < w * h; i++) {
int r;
r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];
r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
r = ((r >> adjustR)+((r >> (adjustR-1))%2));
if(r > 255) r = 255; else if(r < 0) r = 0;
fprintf(fdest, "%c", (uint8_t)r);
if ((i + 1) % w == 0) {
for (pad = w % 4 ? 4 - w % 4 : 0; pad > 0; pad--) /* ADD */
fprintf(fdest, "%c", 0);
}
}
fclose(fdest);
}
return 0;
}

View File

@@ -0,0 +1,496 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2014, Professor Benoit Macq
* Copyright (c) 2001-2003, David Janssens
* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux
* Copyright (c) 2003-2014, Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2015, Matthieu Darbois
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_config.h"
#ifndef HAVE_LIBPNG
# error HAVE_LIBPNG_NOT_DEFINED
#endif /* HAVE_LIBPNG */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <zlib.h>
#include <png.h>
#include "openjpeg.h"
#include "convert.h"
#define PNG_MAGIC "\x89PNG\x0d\x0a\x1a\x0a"
#define MAGIC_SIZE 8
/* PNG allows bits per sample: 1, 2, 4, 8, 16 */
static void convert_16u32s_C1R(const png_byte* pSrc, png_int_32* pDst, size_t length)
{
size_t i;
for (i = 0; i < length; i++) {
png_int_32 val0 = *pSrc++;
png_int_32 val1 = *pSrc++;
pDst[i] = val0 << 8 | val1;
}
}
opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
{
png_structp png = NULL;
png_infop info = NULL;
double gamma;
int bit_depth, interlace_type,compression_type, filter_type;
png_uint_32 i;
png_uint_32 width, height = 0U;
int color_type;
FILE *reader = NULL;
png_byte** rows = NULL;
png_int_32* row32s = NULL;
/* j2k: */
opj_image_t *image = NULL;
opj_image_cmptparm_t cmptparm[4];
png_uint_32 nr_comp;
png_byte sigbuf[8];
convert_XXx32s_C1R cvtXXTo32s = NULL;
convert_32s_CXPX cvtCxToPx = NULL;
png_int_32* planes[4];
if((reader = fopen(read_idf, "rb")) == NULL)
{
fprintf(stderr,"pngtoimage: can not open %s\n",read_idf);
return NULL;
}
if(fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
|| memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0)
{
fprintf(stderr,"pngtoimage: %s is no valid PNG file\n",read_idf);
goto fin;
}
if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL)) == NULL)
goto fin;
if((info = png_create_info_struct(png)) == NULL)
goto fin;
if(setjmp(png_jmpbuf(png)))
goto fin;
png_init_io(png, reader);
png_set_sig_bytes(png, MAGIC_SIZE);
png_read_info(png, info);
if(png_get_IHDR(png, info, &width, &height,
&bit_depth, &color_type, &interlace_type,
&compression_type, &filter_type) == 0)
goto fin;
/* png_set_expand():
* expand paletted images to RGB, expand grayscale images of
* less than 8-bit depth to 8-bit depth, and expand tRNS chunks
* to alpha channels.
*/
if(color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_expand(png);
}
if(png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_expand(png);
}
/* We might wan't to expand background */
/*
if(png_get_valid(png, info, PNG_INFO_bKGD)) {
png_color_16p bgnd;
png_get_bKGD(png, info, &bgnd);
png_set_background(png, bgnd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
}
*/
if( !png_get_gAMA(png, info, &gamma))
gamma = 1.0;
/* we're not displaying but converting, screen gamma == 1.0 */
png_set_gamma(png, 1.0, gamma);
png_read_update_info(png, info);
color_type = png_get_color_type(png, info);
switch (color_type) {
case PNG_COLOR_TYPE_GRAY:
nr_comp = 1;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
nr_comp = 2;
break;
case PNG_COLOR_TYPE_RGB:
nr_comp = 3;
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
nr_comp = 4;
break;
default:
fprintf(stderr,"pngtoimage: colortype %d is not supported\n", color_type);
goto fin;
}
cvtCxToPx = convert_32s_CXPX_LUT[nr_comp];
bit_depth = png_get_bit_depth(png, info);
switch (bit_depth) {
case 1:
case 2:
case 4:
case 8:
cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth];
break;
case 16: /* 16 bpp is specific to PNG */
cvtXXTo32s = convert_16u32s_C1R;
break;
default:
fprintf(stderr,"pngtoimage: bit depth %d is not supported\n", bit_depth);
goto fin;
}
rows = (png_byte**)calloc(height+1, sizeof(png_byte*));
for(i = 0; i < height; ++i)
rows[i] = (png_byte*)malloc(png_get_rowbytes(png,info));
png_read_image(png, rows);
/* Create image */
memset(cmptparm, 0, sizeof(cmptparm));
for(i = 0; i < nr_comp; ++i)
{
cmptparm[i].prec = (png_uint_32)bit_depth;
/* bits_per_pixel: 8 or 16 */
cmptparm[i].bpp = (png_uint_32)bit_depth;
cmptparm[i].sgnd = 0;
cmptparm[i].dx = (png_uint_32)params->subsampling_dx;
cmptparm[i].dy = (png_uint_32)params->subsampling_dy;
cmptparm[i].w = (png_uint_32)width;
cmptparm[i].h = (png_uint_32)height;
}
image = opj_image_create(nr_comp, &cmptparm[0], (nr_comp > 2U) ? CLRSPC_SRGB : CLRSPC_GRAY);
if(image == NULL) goto fin;
image->x0 = (png_uint_32)params->image_offset_x0;
image->y0 = (png_uint_32)params->image_offset_y0;
image->x1 = (png_uint_32)(image->x0 + (width - 1) * (png_uint_32)params->subsampling_dx + 1 + image->x0);
image->y1 = (png_uint_32)(image->y0 + (height - 1) * (png_uint_32)params->subsampling_dy + 1 + image->y0);
row32s = (png_int_32 *)malloc((size_t)width * nr_comp * sizeof(png_int_32));
if(row32s == NULL) goto fin;
/* Set alpha channel */
/* image->comps[nr_comp-1U].alpha = 1U - (nr_comp & 1U); */
for(i = 0; i < nr_comp; i++)
{
planes[i] = image->comps[i].data;
}
for(i = 0; i < height; ++i)
{
cvtXXTo32s(rows[i], row32s, (size_t)width * nr_comp);
cvtCxToPx(row32s, planes, width);
planes[0] += width;
planes[1] += width;
planes[2] += width;
planes[3] += width;
}
fin:
if(rows)
{
for(i = 0; i < height; ++i)
free(rows[i]);
free(rows);
}
if (row32s) {
free(row32s);
}
if(png)
png_destroy_read_struct(&png, &info, NULL);
fclose(reader);
return image;
}/* pngtoimage() */
static void convert_32s16u_C1R(const png_int_32* pSrc, png_byte* pDst, size_t length)
{
size_t i;
for (i = 0; i < length; i++) {
png_uint_32 val = (png_uint_32)pSrc[i];
*pDst++ = (png_byte)(val >> 8);
*pDst++ = (png_byte)val;
}
}
int imagetopng(opj_image_t * image, const char *write_idf)
{
FILE * volatile writer = NULL;
png_structp png = NULL;
png_infop info = NULL;
png_bytep volatile row_buf = NULL;
int nr_comp, color_type;
volatile int prec;
png_color_8 sig_bit;
png_int_32 const* planes[4];
int i;
png_int_32* volatile buffer32s = NULL;
volatile int fails = 1;
memset(&sig_bit, 0, sizeof(sig_bit));
prec = (int)image->comps[0].prec;
planes[0] = image->comps[0].data;
nr_comp = (int)image->numcomps;
if (nr_comp > 4) {
nr_comp = 4;
}
for (i = 1; i < nr_comp; ++i) {
if (image->comps[0].dx != image->comps[i].dx) {
break;
}
if (image->comps[0].dy != image->comps[i].dy) {
break;
}
if (image->comps[0].prec != image->comps[i].prec) {
break;
}
if (image->comps[0].sgnd != image->comps[i].sgnd) {
break;
}
planes[i] = image->comps[i].data;
}
if (i != nr_comp) {
fprintf(stderr,"imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n");
fprintf(stderr,"\tAborting\n");
return 1;
}
for (i = 0; i < nr_comp; ++i) {
clip_component(&(image->comps[i]), image->comps[0].prec);
}
if(prec > 8 && prec < 16)
{
for (i = 0; i < nr_comp; ++i) {
scale_component(&(image->comps[i]), 16);
}
prec = 16;
}
else if(prec < 8 && nr_comp > 1)/* GRAY_ALPHA, RGB, RGB_ALPHA */
{
for (i = 0; i < nr_comp; ++i) {
scale_component(&(image->comps[i]), 8);
}
prec = 8;
} else if((prec > 1) && (prec < 8) && ((prec == 6) || ((prec & 1)==1))) { /* GRAY with non native precision */
if ((prec == 5) || (prec == 6)) {
prec = 8;
} else {
prec++;
}
for (i = 0; i < nr_comp; ++i) {
scale_component(&(image->comps[i]), (png_uint_32)prec);
}
}
if(prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16)
{
fprintf(stderr,"imagetopng: can not create %s\n\twrong bit_depth %d\n", write_idf, prec);
return fails;
}
writer = fopen(write_idf, "wb");
if(writer == NULL) return fails;
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
* you can supply NULL for the last three parameters. We also check that
* the library version is compatible with the one used at compile time,
* in case we are using dynamically linked libraries. REQUIRED.
*/
png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
/*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
if(png == NULL) goto fin;
/* Allocate/initialize the image information data. REQUIRED
*/
info = png_create_info_struct(png);
if(info == NULL) goto fin;
/* Set error handling. REQUIRED if you are not supplying your own
* error handling functions in the png_create_write_struct() call.
*/
if(setjmp(png_jmpbuf(png))) goto fin;
/* I/O initialization functions is REQUIRED
*/
png_init_io(png, writer);
/* Set the image information here. Width and height are up to 2^31,
* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
* REQUIRED
*
* ERRORS:
*
* color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
* color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
* color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
* color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
*
*/
png_set_compression_level(png, Z_BEST_COMPRESSION);
if(nr_comp >= 3) /* RGB(A) */
{
color_type = PNG_COLOR_TYPE_RGB;
sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec;
}
else /* GRAY(A) */
{
color_type = PNG_COLOR_TYPE_GRAY;
sig_bit.gray = (png_byte)prec;
}
if((nr_comp & 1) == 0) /* ALPHA */
{
color_type |= PNG_COLOR_MASK_ALPHA;
sig_bit.alpha = (png_byte)prec;
}
png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_set_sBIT(png, info, &sig_bit);
/* png_set_gamma(png, 2.2, 1./2.2); */
/* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */
png_write_info(png, info);
/* setup conversion */
{
size_t rowStride;
png_size_t png_row_size;
png_row_size = png_get_rowbytes(png, info);
rowStride = ((size_t)image->comps[0].w * (size_t)nr_comp * (size_t)prec + 7U) / 8U;
if (rowStride != (size_t)png_row_size) {
fprintf(stderr, "Invalid PNG row size\n");
goto fin;
}
row_buf = (png_bytep)malloc(png_row_size);
if (row_buf == NULL) {
fprintf(stderr, "Can't allocate memory for PNG row\n");
goto fin;
}
buffer32s = (png_int_32*)malloc((size_t)image->comps[0].w * (size_t)nr_comp * sizeof(png_int_32));
if (buffer32s == NULL) {
fprintf(stderr, "Can't allocate memory for interleaved 32s row\n");
goto fin;
}
}
/* convert */
{
size_t width= image->comps[0].w;
int y;
convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp];
convert_32sXXx_C1R cvt32sToPack = NULL;
png_int_32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0;
png_bytep row_buf_cpy = row_buf;
png_int_32* buffer32s_cpy = buffer32s;
switch (prec) {
case 1:
case 2:
case 4:
case 8:
cvt32sToPack = convert_32sXXu_C1R_LUT[prec];
break;
case 16:
cvt32sToPack = convert_32s16u_C1R;
break;
default:
/* never here */
break;
}
for(y = 0; y < image->comps[0].h; ++y)
{
cvtPxToCx(planes, buffer32s_cpy, width, adjust);
cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (size_t)nr_comp);
png_write_row(png, row_buf_cpy);
planes[0] += width;
planes[1] += width;
planes[2] += width;
planes[3] += width;
}
}
png_write_end(png, info);
fails = 0;
fin:
if(png) {
png_destroy_write_struct(&png, &info);
}
if(row_buf) {
free(row_buf);
}
if(buffer32s) {
free(buffer32s);
}
fclose(writer);
if(fails) (void)remove(write_idf); /* ignore return value */
return fails;
}/* imagetopng() */

View File

@@ -0,0 +1,633 @@
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2014, Professor Benoit Macq
* Copyright (c) 2001-2003, David Janssens
* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux
* Copyright (c) 2003-2014, Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2015, Matthieu Darbois
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef HAVE_LIBTIFF
# error HAVE_LIBTIFF_NOT_DEFINED
#endif /* HAVE_LIBTIFF */
#include <tiffio.h>
#include "openjpeg.h"
#include "convert.h"
/* -->> -->> -->> -->>
TIFF IMAGE FORMAT
<<-- <<-- <<-- <<-- */
static void tif_32sto10u(const int32* pSrc, uint8* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)3U); i+=4U) {
uint32 src0 = (uint32)pSrc[i+0];
uint32 src1 = (uint32)pSrc[i+1];
uint32 src2 = (uint32)pSrc[i+2];
uint32 src3 = (uint32)pSrc[i+3];
*pDst++ = (uint8)(src0 >> 2);
*pDst++ = (uint8)(((src0 & 0x3U) << 6) | (src1 >> 4));
*pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 6));
*pDst++ = (uint8)(((src2 & 0x3FU) << 2) | (src3 >> 8));
*pDst++ = (uint8)(src3);
}
if (length & 3U) {
uint32 src0 = (uint32)pSrc[i+0];
uint32 src1 = 0U;
uint32 src2 = 0U;
length = length & 3U;
if (length > 1U) {
src1 = (uint32)pSrc[i+1];
if (length > 2U) {
src2 = (uint32)pSrc[i+2];
}
}
*pDst++ = (uint8)(src0 >> 2);
*pDst++ = (uint8)(((src0 & 0x3U) << 6) | (src1 >> 4));
if (length > 1U) {
*pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 6));
if (length > 2U) {
*pDst++ = (uint8)(((src2 & 0x3FU) << 2));
}
}
}
}
static void tif_32sto12u(const int32* pSrc, uint8* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)1U); i+=2U) {
uint32 src0 = (uint32)pSrc[i+0];
uint32 src1 = (uint32)pSrc[i+1];
*pDst++ = (uint8)(src0 >> 4);
*pDst++ = (uint8)(((src0 & 0xFU) << 4) | (src1 >> 8));
*pDst++ = (uint8)(src1);
}
if (length & 1U) {
uint32 src0 = (uint32)pSrc[i+0];
*pDst++ = (uint8)(src0 >> 4);
*pDst++ = (uint8)(((src0 & 0xFU) << 4));
}
}
static void tif_32sto14u(const int32* pSrc, uint8* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)3U); i+=4U) {
uint32 src0 = (uint32)pSrc[i+0];
uint32 src1 = (uint32)pSrc[i+1];
uint32 src2 = (uint32)pSrc[i+2];
uint32 src3 = (uint32)pSrc[i+3];
*pDst++ = (uint8)(src0 >> 6);
*pDst++ = (uint8)(((src0 & 0x3FU) << 2) | (src1 >> 12));
*pDst++ = (uint8)(src1 >> 4);
*pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 10));
*pDst++ = (uint8)(src2 >> 2);
*pDst++ = (uint8)(((src2 & 0x3U) << 6) | (src3 >> 8));
*pDst++ = (uint8)(src3);
}
if (length & 3U) {
uint32 src0 = (uint32)pSrc[i+0];
uint32 src1 = 0U;
uint32 src2 = 0U;
length = length & 3U;
if (length > 1U) {
src1 = (uint32)pSrc[i+1];
if (length > 2U) {
src2 = (uint32)pSrc[i+2];
}
}
*pDst++ = (uint8)(src0 >> 6);
*pDst++ = (uint8)(((src0 & 0x3FU) << 2) | (src1 >> 12));
if (length > 1U) {
*pDst++ = (uint8)(src1 >> 4);
*pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 10));
if (length > 2U) {
*pDst++ = (uint8)(src2 >> 2);
*pDst++ = (uint8)(((src2 & 0x3U) << 6));
}
}
}
}
static void tif_32sto16u(const int32* pSrc, uint16* pDst, size_t length)
{
size_t i;
for (i = 0; i < length; ++i) {
pDst[i] = (uint16)pSrc[i];
}
}
int imagetotif(opj_image_t * image, const char *outfile)
{
int width, height;
int bps,adjust, sgnd;
int tiPhoto;
TIFF *tif;
tdata_t buf;
tsize_t strip_size;
int32 i, numcomps;
size_t rowStride;
int32* buffer32s = NULL;
int32 const* planes[4];
convert_32s_PXCX cvtPxToCx = NULL;
convert_32sXXx_C1R cvt32sToTif = NULL;
bps = image->comps[0].prec;
planes[0] = image->comps[0].data;
numcomps = image->numcomps;
if (numcomps > 2) {
tiPhoto = PHOTOMETRIC_RGB;
if (numcomps > 4) {
numcomps = 4;
}
} else {
tiPhoto = PHOTOMETRIC_MINISBLACK;
}
for (i = 1; i < numcomps; ++i) {
if (image->comps[0].dx != image->comps[i].dx) {
break;
}
if (image->comps[0].dy != image->comps[i].dy) {
break;
}
if (image->comps[0].prec != image->comps[i].prec) {
break;
}
if (image->comps[0].sgnd != image->comps[i].sgnd) {
break;
}
planes[i] = image->comps[i].data;
}
if (i != numcomps) {
fprintf(stderr,"imagetotif: All components shall have the same subsampling, same bit depth.\n");
fprintf(stderr,"\tAborting\n");
return 1;
}
if((bps > 16) || ((bps != 1) && (bps & 1))) bps = 0;
if(bps == 0)
{
fprintf(stderr,"imagetotif: Bits=%d, Only 1, 2, 4, 6, 8, 10, 12, 14 and 16 bits implemented\n",bps);
fprintf(stderr,"\tAborting\n");
return 1;
}
tif = TIFFOpen(outfile, "wb");
if (!tif)
{
fprintf(stderr, "imagetotif:failed to open %s for writing\n", outfile);
return 1;
}
for (i = 0; i < numcomps; ++i) {
clip_component(&(image->comps[i]), image->comps[0].prec);
}
cvtPxToCx = convert_32s_PXCX_LUT[numcomps];
switch (bps) {
case 1:
case 2:
case 4:
case 6:
case 8:
cvt32sToTif = convert_32sXXu_C1R_LUT[bps];
break;
case 10:
cvt32sToTif = tif_32sto10u;
break;
case 12:
cvt32sToTif = tif_32sto12u;
break;
case 14:
cvt32sToTif = tif_32sto14u;
break;
case 16:
cvt32sToTif = (convert_32sXXx_C1R)tif_32sto16u;
break;
default:
/* never here */
break;
}
sgnd = (int)image->comps[0].sgnd;
adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0;
width = (int)image->comps[0].w;
height = (int)image->comps[0].h;
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, numcomps);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, tiPhoto);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
strip_size = TIFFStripSize(tif);
rowStride = ((size_t)width * numcomps * (size_t)bps + 7U) / 8U;
if (rowStride != (size_t)strip_size) {
fprintf(stderr, "Invalid TIFF strip size\n");
TIFFClose(tif);
return 1;
}
buf = _TIFFmalloc(strip_size);
if (buf == NULL) {
TIFFClose(tif);
return 1;
}
buffer32s = (int32 *)malloc((size_t)width * numcomps * sizeof(int32));
if (buffer32s == NULL) {
_TIFFfree(buf);
TIFFClose(tif);
return 1;
}
for (i = 0; i < image->comps[0].h; ++i) {
cvtPxToCx(planes, buffer32s, (size_t)width, adjust);
cvt32sToTif(buffer32s, (uint8 *)buf, (size_t)width * numcomps);
(void)TIFFWriteEncodedStrip(tif, i, (void*)buf, strip_size);
planes[0] += width;
planes[1] += width;
planes[2] += width;
planes[3] += width;
}
_TIFFfree((void*)buf);
TIFFClose(tif);
free(buffer32s);
return 0;
}/* imagetotif() */
static void tif_10uto32s(const uint8* pSrc, int32* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)3U); i+=4U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
uint32 val2 = *pSrc++;
uint32 val3 = *pSrc++;
uint32 val4 = *pSrc++;
pDst[i+0] = (int32)((val0 << 2) | (val1 >> 6));
pDst[i+1] = (int32)(((val1 & 0x3FU) << 4) | (val2 >> 4));
pDst[i+2] = (int32)(((val2 & 0xFU) << 6) | (val3 >> 2));
pDst[i+3] = (int32)(((val3 & 0x3U) << 8) | val4);
}
if (length & 3U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
length = length & 3U;
pDst[i+0] = (int32)((val0 << 2) | (val1 >> 6));
if (length > 1U) {
uint32 val2 = *pSrc++;
pDst[i+1] = (int32)(((val1 & 0x3FU) << 4) | (val2 >> 4));
if (length > 2U) {
uint32 val3 = *pSrc++;
pDst[i+2] = (int32)(((val2 & 0xFU) << 6) | (val3 >> 2));
}
}
}
}
static void tif_12uto32s(const uint8* pSrc, int32* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)1U); i+=2U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
uint32 val2 = *pSrc++;
pDst[i+0] = (int32)((val0 << 4) | (val1 >> 4));
pDst[i+1] = (int32)(((val1 & 0xFU) << 8) | val2);
}
if (length & 1U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
pDst[i+0] = (int32)((val0 << 4) | (val1 >> 4));
}
}
static void tif_14uto32s(const uint8* pSrc, int32* pDst, size_t length)
{
size_t i;
for (i = 0; i < (length & ~(size_t)3U); i+=4U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
uint32 val2 = *pSrc++;
uint32 val3 = *pSrc++;
uint32 val4 = *pSrc++;
uint32 val5 = *pSrc++;
uint32 val6 = *pSrc++;
pDst[i+0] = (int32)((val0 << 6) | (val1 >> 2));
pDst[i+1] = (int32)(((val1 & 0x3U) << 12) | (val2 << 4) | (val3 >> 4));
pDst[i+2] = (int32)(((val3 & 0xFU) << 10) | (val4 << 2) | (val5 >> 6));
pDst[i+3] = (int32)(((val5 & 0x3FU) << 8) | val6);
}
if (length & 3U) {
uint32 val0 = *pSrc++;
uint32 val1 = *pSrc++;
length = length & 3U;
pDst[i+0] = (int32)((val0 << 6) | (val1 >> 2));
if (length > 1U) {
uint32 val2 = *pSrc++;
uint32 val3 = *pSrc++;
pDst[i+1] = (int32)(((val1 & 0x3U) << 12) | (val2 << 4) | (val3 >> 4));
if (length > 2U) {
uint32 val4 = *pSrc++;
uint32 val5 = *pSrc++;
pDst[i+2] = (int32)(((val3 & 0xFU) << 10) | (val4 << 2) | (val5 >> 6));
}
}
}
}
/* seems that libtiff decodes this to machine endianness */
static void tif_16uto32s(const uint16* pSrc, int32* pDst, size_t length)
{
size_t i;
for (i = 0; i < length; i++) {
pDst[i] = pSrc[i];
}
}
/*
* libtiff/tif_getimage.c : 1,2,4,8,16 bitspersample accepted
* CINEMA : 12 bit precision
*/
opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
{
int subsampling_dx = parameters->subsampling_dx;
int subsampling_dy = parameters->subsampling_dy;
TIFF *tif;
tdata_t buf;
tstrip_t strip;
tsize_t strip_size;
int j, currentPlane, numcomps = 0, w, h;
OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN;
opj_image_cmptparm_t cmptparm[4]; /* RGBA */
opj_image_t *image = NULL;
int has_alpha = 0;
unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC;
unsigned int tiWidth, tiHeight;
opj_bool is_cinema = (parameters->cp_cinema != OFF) ? OPJ_TRUE : OPJ_FALSE;
convert_XXx32s_C1R cvtTifTo32s = NULL;
convert_32s_CXPX cvtCxToPx = NULL;
int32* buffer32s = NULL;
int32* planes[4];
size_t rowStride;
tif = TIFFOpen(filename, "r");
if(!tif)
{
fprintf(stderr, "tiftoimage:Failed to open %s for reading\n", filename);
return 0;
}
tiBps = tiPhoto = tiSf = tiSpp = tiPC = 0;
tiWidth = tiHeight = 0;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &tiWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &tiHeight);
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiBps);
TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &tiSf);
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &tiSpp);
TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &tiPhoto);
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &tiPC);
w= (int)tiWidth;
h= (int)tiHeight;
if((tiBps > 16U) || ((tiBps != 1U) && (tiBps & 1U))) {
fprintf(stderr,"tiftoimage: Bits=%d, Only 1, 2, 4, 6, 8, 10, 12, 14 and 16 bits implemented\n",tiBps);
fprintf(stderr,"\tAborting\n");
TIFFClose(tif);
return NULL;
}
if(tiPhoto != PHOTOMETRIC_MINISBLACK && tiPhoto != PHOTOMETRIC_RGB) {
fprintf(stderr,"tiftoimage: Bad color format %d.\n\tOnly RGB(A) and GRAY(A) has been implemented\n",(int) tiPhoto);
fprintf(stderr,"\tAborting\n");
TIFFClose(tif);
return NULL;
}
switch (tiBps) {
case 1:
case 2:
case 4:
case 6:
case 8:
cvtTifTo32s = convert_XXu32s_C1R_LUT[tiBps];
break;
/* others are specific to TIFF */
case 10:
cvtTifTo32s = tif_10uto32s;
break;
case 12:
cvtTifTo32s = tif_12uto32s;
break;
case 14:
cvtTifTo32s = tif_14uto32s;
break;
case 16:
cvtTifTo32s = (convert_XXx32s_C1R)tif_16uto32s;
break;
default:
/* never here */
break;
}
{/* From: tiff-4.0.x/libtiff/tif_getimage.c : */
uint16* sampleinfo;
uint16 extrasamples;
TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
&extrasamples, &sampleinfo);
if(extrasamples >= 1)
{
switch(sampleinfo[0])
{
case EXTRASAMPLE_UNSPECIFIED:
/* Workaround for some images without correct info about alpha channel
*/
if(tiSpp > 3)
has_alpha = 1;
break;
case EXTRASAMPLE_ASSOCALPHA: /* data pre-multiplied */
case EXTRASAMPLE_UNASSALPHA: /* data not pre-multiplied */
has_alpha = 1;
break;
}
}
else /* extrasamples == 0 */
if(tiSpp == 4 || tiSpp == 2) has_alpha = 1;
}
/* initialize image components */
memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
if ((tiPhoto == PHOTOMETRIC_RGB) && (is_cinema) && (tiBps != 12U)) {
fprintf(stdout,"WARNING:\n"
"Input image bitdepth is %d bits\n"
"TIF conversion has automatically rescaled to 12-bits\n"
"to comply with cinema profiles.\n",
tiBps);
} else {
is_cinema = 0U;
}
if(tiPhoto == PHOTOMETRIC_RGB) /* RGB(A) */
{
numcomps = 3 + has_alpha;
color_space = CLRSPC_SRGB;
}
else if (tiPhoto == PHOTOMETRIC_MINISBLACK) /* GRAY(A) */
{
numcomps = 1 + has_alpha;
color_space = CLRSPC_GRAY;
}
cvtCxToPx = convert_32s_CXPX_LUT[numcomps];
if (tiPC == PLANARCONFIG_SEPARATE) {
cvtCxToPx = convert_32s_CXPX_LUT[1]; /* override */
tiSpp = 1U; /* consider only one sample per plane */
}
for(j = 0; j < numcomps; j++)
{
cmptparm[j].prec = tiBps;
cmptparm[j].bpp = tiBps;
cmptparm[j].dx = (uint32)subsampling_dx;
cmptparm[j].dy = (uint32)subsampling_dy;
cmptparm[j].w = (uint32)w;
cmptparm[j].h = (uint32)h;
}
image = opj_image_create((uint32)numcomps, &cmptparm[0], color_space);
if(!image)
{
TIFFClose(tif);
return NULL;
}
/* set image offset and reference grid */
image->x0 = (uint32)parameters->image_offset_x0;
image->y0 = (uint32)parameters->image_offset_y0;
image->x1 = !image->x0 ? (uint32)(w - 1) * (uint32)subsampling_dx + 1 :
image->x0 + (uint32)(w - 1) * (uint32)subsampling_dx + 1;
image->y1 = !image->y0 ? (uint32)(h - 1) * (uint32)subsampling_dy + 1 :
image->y0 + (uint32)(h - 1) * (uint32)subsampling_dy + 1;
for(j = 0; j < numcomps; j++)
{
planes[j] = image->comps[j].data;
}
/* image->comps[numcomps - 1].alpha = (uint16)(1 - (numcomps & 1)); */
strip_size = TIFFStripSize(tif);
buf = _TIFFmalloc(strip_size);
if (buf == NULL) {
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}
rowStride = ((size_t)w * tiSpp * tiBps + 7U) / 8U;
buffer32s = (int32 *)malloc((size_t)w * tiSpp * sizeof(int32));
if (buffer32s == NULL) {
_TIFFfree(buf);
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}
strip = 0;
currentPlane = 0;
do
{
planes[0] = image->comps[currentPlane].data; /* to manage planar data */
h= (int)tiHeight;
/* Read the Image components */
for(; (h > 0) && (strip < TIFFNumberOfStrips(tif)); strip++)
{
const uint8 *dat8;
size_t ssize;
ssize = (size_t)TIFFReadEncodedStrip(tif, strip, buf, strip_size);
dat8 = (const uint8*)buf;
while (ssize >= rowStride) {
cvtTifTo32s(dat8, buffer32s, (size_t)w * tiSpp);
cvtCxToPx(buffer32s, planes, (size_t)w);
planes[0] += w;
planes[1] += w;
planes[2] += w;
planes[3] += w;
dat8 += rowStride;
ssize -= rowStride;
h--;
}
}
currentPlane++;
} while ((tiPC == PLANARCONFIG_SEPARATE) && (currentPlane < numcomps));
free(buffer32s);
_TIFFfree(buf);
TIFFClose(tif);
if (is_cinema) {
for (j=0; j < numcomps; ++j) {
scale_component(&(image->comps[j]), 12);
}
}
return image;
}/* tiftoimage() */

View File

@@ -591,7 +591,9 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param
{"POC",REQ_ARG, NULL ,'P'},
{"ROI",REQ_ARG, NULL ,'R'},
{"jpip",NO_ARG, NULL, 'J'},
{0,0,0,0} /* GNU getopt_long requirement */
#ifdef USE_SYSTEM_GETOPT
{0,0,0,0} /* GNU getopt_long requirement */
#endif
};
/* parse the command line */
@@ -601,7 +603,7 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param
#endif /* USE_JPWL */
"h";
totlen=sizeof(long_option)-1;
totlen=sizeof(long_option);
img_fol->set_out_format=0;
raw_cp->rawWidth = 0;
@@ -1391,10 +1393,10 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param
/* ------------------------------------------------------ */
default:
fprintf(stderr, "ERROR -> Command line not valid\n");
return 1;
}
default:
fprintf(stderr, "[WARNING] An invalid option has been ignored\n");
break;
}
}while(c != -1);
/* check for possible errors */

View File

@@ -201,13 +201,15 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i
int totlen, c;
opj_option_t long_option[]={
{"ImgDir",REQ_ARG, NULL ,'y'},
#ifdef USE_SYSTEM_GETOPT
{0,0,0,0} /* GNU getopt_long requirement */
#endif
};
const char optlist[] = "i:o:h";
OPJ_ARG_NOT_USED(indexfilename);
totlen=sizeof(long_option)-1;
totlen=sizeof(long_option);
img_fol->set_out_format = 0;
do {
#ifdef USE_SYSTEM_GETOPT
@@ -265,7 +267,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i
/* ----------------------------------------------------- */
default:
fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, opj_optarg);
fprintf(stderr,"[WARNING] An invalid option has been ignored\n");
break;
}
}while(c != -1);
@@ -357,6 +359,11 @@ int main(int argc, char *argv[])
return 1;
}
/* j2k_dump focuses on j2k codestream and skips JP2 boxes */
parameters.flags = 1;
/* j2k_dump shall not actually decode packets (parsing codestream is enough). */
parameters.cp_limit_decoding = DECODE_ALL_BUT_PACKETS;
/* Initialize reading of directory */
if(img_fol.set_imgdir==1){
num_images=get_num_images(img_fol.imgdirpath);
@@ -452,7 +459,7 @@ int main(int argc, char *argv[])
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
/* decode the stream and fill the image structure */
if (*indexfilename) /* If need to extract codestream information*/
if (*indexfilename) /* If need to extract codestream information*/
image = opj_decode_with_info(dinfo, cio, &cstr_info);
else
image = opj_decode(dinfo, cio);
@@ -501,7 +508,7 @@ int main(int argc, char *argv[])
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
/* decode the stream and fill the image structure */
if (*indexfilename) /* If need to extract codestream information*/
if (*indexfilename) /* If need to extract codestream information*/
image = opj_decode_with_info(dinfo, cio, &cstr_info);
else
image = opj_decode(dinfo, cio);

View File

@@ -85,6 +85,40 @@ typedef struct img_folder{
}img_fol_t;
typedef enum opj_prec_mode
{
OPJ_PREC_MODE_CLIP,
OPJ_PREC_MODE_SCALE
} opj_precision_mode;
typedef struct opj_prec
{
int prec;
opj_precision_mode mode;
}opj_precision;
typedef struct opj_decompress_params
{
/** core library parameters */
opj_dparameters_t core;
/** input file name */
char infile[OPJ_PATH_LEN];
/** output file name */
char outfile[OPJ_PATH_LEN];
/** input file format 0: J2K, 1: JP2, 2: JPT */
int decod_format;
/** output file format 0: PGX, 1: PxM, 2: BMP */
int cod_format;
opj_precision* precision;
int nb_precision;
/* force output colorspace to RGB */
int force_rgb;
/* upsample components according to their dx/dy values */
int upsample;
}opj_decompress_parameters;
static void decode_help_display(void) {
fprintf(stdout,"HELP for j2k_to_image\n----\n\n");
fprintf(stdout,"- the -h option displays this help information on screen\n\n");
@@ -128,6 +162,18 @@ static void decode_help_display(void) {
fprintf(stdout," are decoded.\n");
fprintf(stdout," -x \n");
fprintf(stdout," Create an index file *.Idx (-x index_name.Idx) \n");
fprintf(stdout," -p <comp 0 precision>[C|S][,<comp 1 precision>[C|S][,...]]\n");
fprintf(stdout," OPTIONAL\n");
fprintf(stdout," Force the precision (bit depth) of components.\n");
fprintf(stdout," There shall be at least 1 value. Theres no limit on the number of values (comma separated, last values ignored if too much values).\n");
fprintf(stdout," If there are less values than components, the last value is used for remaining components.\n");
fprintf(stdout," If 'C' is specified (default), values are clipped.\n");
fprintf(stdout," If 'S' is specified, values are scaled.\n");
fprintf(stdout," A 0 value can be specified (meaning original bit depth).\n");
fprintf(stdout," -force-rgb\n");
fprintf(stdout," Force output image colorspace to RGB\n");
fprintf(stdout," -upsample\n");
fprintf(stdout," Downsampled components will be upsampled to image size\n");
fprintf(stdout,"\n");
/* UniPG>> */
#ifdef USE_JPWL
@@ -144,6 +190,111 @@ static void decode_help_display(void) {
/* -------------------------------------------------------------------------- */
static opj_bool parse_precision(const char* option, opj_decompress_parameters* parameters)
{
const char* l_remaining = option;
opj_bool l_result = OPJ_TRUE;
/* reset */
if (parameters->precision) {
free(parameters->precision);
parameters->precision = NULL;
}
parameters->nb_precision = 0U;
for(;;)
{
int prec;
char mode;
char comma;
int count;
count = sscanf(l_remaining, "%d%c%c", &prec, &mode, &comma);
if (count == 1) {
mode = 'C';
count++;
}
if ((count == 2) || (mode==',')) {
if (mode==',') {
mode = 'C';
}
comma=',';
count = 3;
}
if (count == 3) {
if ((prec < 1) || (prec > 32)) {
fprintf(stderr,"Invalid precision %d in precision option %s\n", prec, option);
l_result = OPJ_FALSE;
break;
}
if ((mode != 'C') && (mode != 'S')) {
fprintf(stderr,"Invalid precision mode %c in precision option %s\n", mode, option);
l_result = OPJ_FALSE;
break;
}
if (comma != ',') {
fprintf(stderr,"Invalid character %c in precision option %s\n", comma, option);
l_result = OPJ_FALSE;
break;
}
if (parameters->precision == NULL) {
/* first one */
parameters->precision = (opj_precision *)malloc(sizeof(opj_precision));
if (parameters->precision == NULL) {
fprintf(stderr,"Could not allocate memory for precision option\n");
l_result = OPJ_FALSE;
break;
}
} else {
int l_new_size = parameters->nb_precision + 1U;
opj_precision* l_new;
if (l_new_size == 0U) {
fprintf(stderr,"Could not allocate memory for precision option\n");
l_result = OPJ_FALSE;
break;
}
l_new = (opj_precision *)realloc(parameters->precision, l_new_size * sizeof(opj_precision));
if (l_new == NULL) {
fprintf(stderr,"Could not allocate memory for precision option\n");
l_result = OPJ_FALSE;
break;
}
parameters->precision = l_new;
}
parameters->precision[parameters->nb_precision].prec = prec;
switch (mode) {
case 'C':
parameters->precision[parameters->nb_precision].mode = OPJ_PREC_MODE_CLIP;
break;
case 'S':
parameters->precision[parameters->nb_precision].mode = OPJ_PREC_MODE_SCALE;
break;
default:
break;
}
parameters->nb_precision++;
l_remaining = strchr(l_remaining, ',');
if (l_remaining == NULL) {
break;
}
l_remaining += 1;
} else {
fprintf(stderr,"Could not parse precision option %s\n", option);
l_result = OPJ_FALSE;
break;
}
}
return l_result;
}
/* -------------------------------------------------------------------------- */
static int get_num_images(char *imgdirpath){
DIR *dir;
struct dirent* content;
@@ -211,7 +362,7 @@ static int get_file_format(char *filename) {
return -1;
}
static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters){
static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_decompress_parameters *parameters){
char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],outfilename[OPJ_PATH_LEN],temp_ofname[OPJ_PATH_LEN];
char *temp_p, temp1[OPJ_PATH_LEN]="";
@@ -237,16 +388,20 @@ static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_d
}
/* -------------------------------------------------------------------------- */
static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol, char *indexfilename) {
static int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol, char *indexfilename) {
/* parse the command line */
int totlen, c;
opj_option_t long_option[]={
{"ImgDir",REQ_ARG, NULL ,'y'},
{"OutFor",REQ_ARG, NULL ,'O'},
{"force-rgb", NO_ARG, NULL, 1},
{"upsample", NO_ARG, NULL, 1},
#ifdef USE_SYSTEM_GETOPT
{0,0,0,0} /* GNU getopt_long requirement */
#endif
};
const char optlist[] = "i:o:r:l:x:"
const char optlist[] = "i:o:r:l:x:p:"
/* UniPG>> */
#ifdef USE_JPWL
@@ -254,7 +409,10 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
#endif /* USE_JPWL */
/* <<UniPG */
"h" ;
totlen=sizeof(long_option) - 1;
long_option[2].flag = &(parameters->force_rgb);
long_option[3].flag = &(parameters->upsample);
totlen=sizeof(long_option);
img_fol->set_out_format = 0;
do {
#ifdef USE_SYSTEM_GETOPT
@@ -265,6 +423,8 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
if (c == -1)
break;
switch (c) {
case 0: /* long opt with flag */
break;
case 'i': /* input file */
{
char *infile = opj_optarg;
@@ -351,7 +511,7 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
case 'r': /* reduce option */
{
sscanf(opj_optarg, "%d", &parameters->cp_reduce);
sscanf(opj_optarg, "%d", &parameters->core.cp_reduce);
}
break;
@@ -360,7 +520,7 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
case 'l': /* layering option */
{
sscanf(opj_optarg, "%d", &parameters->cp_layer);
sscanf(opj_optarg, "%d", &parameters->core.cp_layer);
}
break;
@@ -387,6 +547,15 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
}
break;
/* ----------------------------------------------------- */
case 'p': /* Force precision */
{
if (!parse_precision(opj_optarg, parameters))
{
return 1;
}
}
break;
/* ----------------------------------------------------- */
/* UniPG>> */
#ifdef USE_JPWL
@@ -461,7 +630,7 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
/* ----------------------------------------------------- */
default:
fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, opj_optarg);
fprintf(stderr,"[WARNING] An invalid option has been ignored\n");
break;
}
}while(c != -1);
@@ -494,6 +663,32 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param
/* -------------------------------------------------------------------------- */
static void set_default_parameters(opj_decompress_parameters* parameters)
{
if (parameters) {
memset(parameters, 0, sizeof(opj_decompress_parameters));
/* default decoding parameters (command line specific) */
parameters->decod_format = -1;
parameters->cod_format = -1;
/* default decoding parameters (core) */
opj_set_default_decoder_parameters(&(parameters->core));
}
}
static void destroy_parameters(opj_decompress_parameters* parameters)
{
if (parameters) {
if (parameters->precision) {
free(parameters->precision);
parameters->precision = NULL;
}
}
}
/* -------------------------------------------------------------------------- */
/**
sample error callback expecting a FILE* client object
*/
@@ -518,8 +713,233 @@ static void info_callback(const char *msg, void *client_data) {
/* -------------------------------------------------------------------------- */
static opj_image_t* convert_gray_to_rgb(opj_image_t* original)
{
int compno;
opj_image_t* l_new_image = NULL;
opj_image_cmptparm_t* l_new_components = NULL;
l_new_components = (opj_image_cmptparm_t*)malloc((original->numcomps + 2U) * sizeof(opj_image_cmptparm_t));
if (l_new_components == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for RGB image!\n");
opj_image_destroy(original);
return NULL;
}
l_new_components[0].bpp = l_new_components[1].bpp = l_new_components[2].bpp = original->comps[0].bpp;
l_new_components[0].dx = l_new_components[1].dx = l_new_components[2].dx = original->comps[0].dx;
l_new_components[0].dy = l_new_components[1].dy = l_new_components[2].dy = original->comps[0].dy;
l_new_components[0].h = l_new_components[1].h = l_new_components[2].h = original->comps[0].h;
l_new_components[0].w = l_new_components[1].w = l_new_components[2].w = original->comps[0].w;
l_new_components[0].prec = l_new_components[1].prec = l_new_components[2].prec = original->comps[0].prec;
l_new_components[0].sgnd = l_new_components[1].sgnd = l_new_components[2].sgnd = original->comps[0].sgnd;
l_new_components[0].x0 = l_new_components[1].x0 = l_new_components[2].x0 = original->comps[0].x0;
l_new_components[0].y0 = l_new_components[1].y0 = l_new_components[2].y0 = original->comps[0].y0;
for(compno = 1; compno < original->numcomps; ++compno) {
l_new_components[compno+2].bpp = original->comps[compno].bpp;
l_new_components[compno+2].dx = original->comps[compno].dx;
l_new_components[compno+2].dy = original->comps[compno].dy;
l_new_components[compno+2].h = original->comps[compno].h;
l_new_components[compno+2].w = original->comps[compno].w;
l_new_components[compno+2].prec = original->comps[compno].prec;
l_new_components[compno+2].sgnd = original->comps[compno].sgnd;
l_new_components[compno+2].x0 = original->comps[compno].x0;
l_new_components[compno+2].y0 = original->comps[compno].y0;
}
l_new_image = opj_image_create(original->numcomps + 2, l_new_components, CLRSPC_SRGB);
free(l_new_components);
if (l_new_image == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for RGB image!\n");
opj_image_destroy(original);
return NULL;
}
l_new_image->x0 = original->x0;
l_new_image->x1 = original->x1;
l_new_image->y0 = original->y0;
l_new_image->y1 = original->y1;
l_new_image->comps[0].factor = l_new_image->comps[1].factor = l_new_image->comps[2].factor = original->comps[0].factor;
l_new_image->comps[0].resno_decoded = l_new_image->comps[1].resno_decoded = l_new_image->comps[2].resno_decoded = original->comps[0].resno_decoded;
memcpy(l_new_image->comps[0].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int));
memcpy(l_new_image->comps[1].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int));
memcpy(l_new_image->comps[2].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int));
for(compno = 1; compno < original->numcomps; ++compno) {
l_new_image->comps[compno+2].factor = original->comps[compno].factor;
l_new_image->comps[compno+2].resno_decoded = original->comps[compno].resno_decoded;
memcpy(l_new_image->comps[compno+2].data, original->comps[compno].data, original->comps[compno].w * original->comps[compno].h * sizeof(int));
}
opj_image_destroy(original);
return l_new_image;
}
/* -------------------------------------------------------------------------- */
static opj_image_t* upsample_image_components(opj_image_t* original)
{
opj_image_t* l_new_image = NULL;
opj_image_cmptparm_t* l_new_components = NULL;
opj_bool l_upsample_need = OPJ_FALSE;
int compno;
for (compno = 0; compno < original->numcomps; ++compno) {
if (original->comps[compno].factor > 0) {
fprintf(stderr, "ERROR -> j2k_to_image: -upsample not supported with reduction\n");
opj_image_destroy(original);
return NULL;
}
if ((original->comps[compno].dx > 1) || (original->comps[compno].dy > 1)) {
l_upsample_need = OPJ_TRUE;
break;
}
}
if (!l_upsample_need) {
return original;
}
/* Upsample is needed */
l_new_components = (opj_image_cmptparm_t*)malloc(original->numcomps * sizeof(opj_image_cmptparm_t));
if (l_new_components == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for upsampled components!\n");
opj_image_destroy(original);
return NULL;
}
for (compno = 0; compno < original->numcomps; ++compno) {
opj_image_cmptparm_t* l_new_cmp = &(l_new_components[compno]);
opj_image_comp_t* l_org_cmp = &(original->comps[compno]);
l_new_cmp->bpp = l_org_cmp->bpp;
l_new_cmp->prec = l_org_cmp->prec;
l_new_cmp->sgnd = l_org_cmp->sgnd;
l_new_cmp->x0 = original->x0;
l_new_cmp->y0 = original->y0;
l_new_cmp->dx = 1;
l_new_cmp->dy = 1;
l_new_cmp->w = l_org_cmp->w; /* should be original->x1 - original->x0 for dx==1 */
l_new_cmp->h = l_org_cmp->h; /* should be original->y1 - original->y0 for dy==0 */
if (l_org_cmp->dx > 1) {
l_new_cmp->w = original->x1 - original->x0;
}
if (l_org_cmp->dy > 1) {
l_new_cmp->h = original->y1 - original->y0;
}
}
l_new_image = opj_image_create(original->numcomps, l_new_components, original->color_space);
free(l_new_components);
if (l_new_image == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for upsampled components!\n");
opj_image_destroy(original);
return NULL;
}
l_new_image->x0 = original->x0;
l_new_image->x1 = original->x1;
l_new_image->y0 = original->y0;
l_new_image->y1 = original->y1;
for (compno = 0; compno < original->numcomps; ++compno) {
opj_image_comp_t* l_new_cmp = &(l_new_image->comps[compno]);
opj_image_comp_t* l_org_cmp = &(original->comps[compno]);
l_new_cmp->factor = l_org_cmp->factor;
l_new_cmp->resno_decoded = l_org_cmp->resno_decoded;
if ((l_org_cmp->dx > 1) || (l_org_cmp->dy > 1)) {
const int* l_src = l_org_cmp->data;
int* l_dst = l_new_cmp->data;
int y;
int xoff, yoff;
/* need to take into account dx & dy */
xoff = l_org_cmp->dx * l_org_cmp->x0 - original->x0;
yoff = l_org_cmp->dy * l_org_cmp->y0 - original->y0;
if ((xoff >= l_org_cmp->dx) || (yoff >= l_org_cmp->dy)) {
fprintf(stderr, "ERROR -> j2k_to_image: Invalid image/component parameters found when upsampling\n");
opj_image_destroy(original);
opj_image_destroy(l_new_image);
return NULL;
}
for (y = 0; y < yoff; ++y) {
memset(l_dst, 0, l_new_cmp->w * sizeof(int));
l_dst += l_new_cmp->w;
}
if(l_new_cmp->h > (l_org_cmp->dy - 1)) { /* check subtraction overflow for really small images */
for (; y < l_new_cmp->h - (l_org_cmp->dy - 1); y += l_org_cmp->dy) {
int x, dy;
int xorg;
xorg = 0;
for (x = 0; x < xoff; ++x) {
l_dst[x] = 0;
}
if (l_new_cmp->w > (l_org_cmp->dx - 1)) { /* check subtraction overflow for really small images */
for (; x < l_new_cmp->w - (l_org_cmp->dx - 1); x += l_org_cmp->dx, ++xorg) {
int dx;
for (dx = 0; dx < l_org_cmp->dx; ++dx) {
l_dst[x + dx] = l_src[xorg];
}
}
}
for (; x < l_new_cmp->w; ++x) {
l_dst[x] = l_src[xorg];
}
l_dst += l_new_cmp->w;
for (dy = 1; dy < l_org_cmp->dy; ++dy) {
memcpy(l_dst, l_dst - l_new_cmp->w, l_new_cmp->w * sizeof(int));
l_dst += l_new_cmp->w;
}
l_src += l_org_cmp->w;
}
}
if (y < l_new_cmp->h) {
int x;
int xorg;
xorg = 0;
for (x = 0; x < xoff; ++x) {
l_dst[x] = 0;
}
if (l_new_cmp->w > (l_org_cmp->dx - 1)) { /* check subtraction overflow for really small images */
for (; x < l_new_cmp->w - (l_org_cmp->dx - 1); x += l_org_cmp->dx, ++xorg) {
int dx;
for (dx = 0; dx < l_org_cmp->dx; ++dx) {
l_dst[x + dx] = l_src[xorg];
}
}
}
for (; x < l_new_cmp->w; ++x) {
l_dst[x] = l_src[xorg];
}
l_dst += l_new_cmp->w;
++y;
for (; y < l_new_cmp->h; ++y) {
memcpy(l_dst, l_dst - l_new_cmp->w, l_new_cmp->w * sizeof(int));
l_dst += l_new_cmp->w;
}
}
}
else {
memcpy(l_new_cmp->data, l_org_cmp->data, l_org_cmp->w * l_org_cmp->h * sizeof(int));
}
}
opj_image_destroy(original);
return l_new_image;
}
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv) {
opj_dparameters_t parameters; /* decompression parameters */
opj_decompress_parameters parameters; /* decompression parameters */
img_fol_t img_fol;
opj_event_mgr_t event_mgr; /* event manager */
opj_image_t *image = NULL;
@@ -541,7 +961,7 @@ int main(int argc, char **argv) {
event_mgr.info_handler = info_callback;
/* set decoding parameters to default values */
opj_set_default_decoder_parameters(&parameters);
set_default_parameters(&parameters);
/* Initialize indexfilename and img_fol */
*indexfilename = 0;
@@ -549,6 +969,7 @@ int main(int argc, char **argv) {
/* parse input and get user encoding parameters */
if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol, indexfilename) == 1) {
destroy_parameters(&parameters);
return 1;
}
@@ -562,6 +983,7 @@ int main(int argc, char **argv) {
dirptr->filename = (char**) malloc(num_images*sizeof(char*));
if(!dirptr->filename_buf){
destroy_parameters(&parameters);
return 1;
}
for(i=0;i<num_images;i++){
@@ -569,10 +991,12 @@ int main(int argc, char **argv) {
}
}
if(load_images(dirptr,img_fol.imgdirpath)==1){
destroy_parameters(&parameters);
return 1;
}
if (num_images==0){
fprintf(stdout,"Folder is empty\n");
destroy_parameters(&parameters);
return 1;
}
}else{
@@ -596,6 +1020,7 @@ int main(int argc, char **argv) {
fsrc = fopen(parameters.infile, "rb");
if (!fsrc) {
fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile);
destroy_parameters(&parameters);
return 1;
}
fseek(fsrc, 0, SEEK_END);
@@ -607,6 +1032,7 @@ int main(int argc, char **argv) {
free(src);
fclose(fsrc);
fprintf(stderr, "\nERROR: fread return a number of element different from the expected.\n");
destroy_parameters(&parameters);
return 1;
}
fclose(fsrc);
@@ -626,7 +1052,7 @@ int main(int argc, char **argv) {
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
/* setup the decoder decoding parameters using user parameters */
opj_setup_decoder(dinfo, &parameters);
opj_setup_decoder(dinfo, &parameters.core);
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
@@ -641,6 +1067,7 @@ int main(int argc, char **argv) {
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
free(src);
destroy_parameters(&parameters);
return 1;
}
@@ -669,7 +1096,7 @@ int main(int argc, char **argv) {
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
/* setup the decoder decoding parameters using the current image and user parameters */
opj_setup_decoder(dinfo, &parameters);
opj_setup_decoder(dinfo, &parameters.core);
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
@@ -684,6 +1111,7 @@ int main(int argc, char **argv) {
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
free(src);
destroy_parameters(&parameters);
return 1;
}
@@ -712,7 +1140,7 @@ int main(int argc, char **argv) {
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
/* setup the decoder decoding parameters using user parameters */
opj_setup_decoder(dinfo, &parameters);
opj_setup_decoder(dinfo, &parameters.core);
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
@@ -727,6 +1155,7 @@ int main(int argc, char **argv) {
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
free(src);
destroy_parameters(&parameters);
return 1;
}
@@ -753,20 +1182,89 @@ int main(int argc, char **argv) {
free(src);
src = NULL;
if(image->color_space == CLRSPC_SYCC)
{
color_sycc_to_rgb(image);
}
if(image->color_space == CLRSPC_SYCC)
{
color_sycc_to_rgb(image);
}
if(image->icc_profile_buf)
{
if(image->icc_profile_buf)
{
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
color_apply_icc_profile(image);
color_apply_icc_profile(image);
#endif
free(image->icc_profile_buf);
image->icc_profile_buf = NULL; image->icc_profile_len = 0;
}
free(image->icc_profile_buf);
image->icc_profile_buf = NULL; image->icc_profile_len = 0;
}
/* Force output precision */
/* ---------------------- */
if (parameters.precision != NULL)
{
int compno;
for (compno = 0; compno < image->numcomps; ++compno)
{
int precno = compno;
int prec;
if (precno >= parameters.nb_precision) {
precno = parameters.nb_precision - 1U;
}
prec = parameters.precision[precno].prec;
if (prec == 0) {
prec = image->comps[compno].prec;
}
switch (parameters.precision[precno].mode) {
case OPJ_PREC_MODE_CLIP:
clip_component(&(image->comps[compno]), prec);
break;
case OPJ_PREC_MODE_SCALE:
scale_component(&(image->comps[compno]), prec);
break;
default:
break;
}
}
}
/* Upsample components */
/* ------------------- */
if (parameters.upsample)
{
image = upsample_image_components(image);
if (image == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to upsample image components!\n");
destroy_parameters(&parameters);
opj_destroy_decompress(dinfo);
return EXIT_FAILURE;
}
}
/* Force RGB output */
/* ---------------- */
if (parameters.force_rgb)
{
switch (image->color_space) {
case CLRSPC_SRGB:
break;
case CLRSPC_GRAY:
image = convert_gray_to_rgb(image);
break;
default:
fprintf(stderr, "ERROR -> j2k_to_image: don't know how to convert image to RGB colorspace!\n");
opj_image_destroy(image);
image = NULL;
break;
}
if (image == NULL) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to convert to RGB image!\n");
destroy_parameters(&parameters);
opj_destroy_decompress(dinfo);
return EXIT_FAILURE;
}
}
/* create output image */
/* ------------------- */
@@ -852,6 +1350,7 @@ int main(int argc, char **argv) {
opj_image_destroy(image);
}
destroy_parameters(&parameters);
return 0;
}
/*end main*/

View File

@@ -46,31 +46,31 @@
#endif
/*--------------------------------------------------------
Matrix f<EFBFBD>r sYCC, Amendment 1 to IEC 61966-2-1
Y : 0.299 0.587 0.114 :R
Cb: -0.1687 -0.3312 0.5 :G
Cr: 0.5 -0.4187 -0.0812 :B
Inverse:
R: 1 -3.68213e-05 1.40199 :Y
G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
-----------------------------------------------------------*/
Matrix for sYCC, Amendment 1 to IEC 61966-2-1
Y : 0.299 0.587 0.114 :R
Cb: -0.1687 -0.3312 0.5 :G
Cr: 0.5 -0.4187 -0.0812 :B
Inverse:
R: 1 -3.68213e-05 1.40199 :Y
G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
-----------------------------------------------------------*/
static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
int *out_r, int *out_g, int *out_b)
int *out_r, int *out_g, int *out_b)
{
int r, g, b;
cb -= offset; cr -= offset;
r = y + (int)(1.402 * (float)cr);
if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
b = y + (int)(1.772 * (float)cb);
if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
}
@@ -79,185 +79,206 @@ static void sycc444_to_rgb(opj_image_t *img)
{
int *d0, *d1, *d2, *r, *g, *b;
const int *y, *cb, *cr;
int maxw, maxh, max, i, offset, upb;
i = img->comps[0].prec;
offset = 1<<(i - 1); upb = (1<<i)-1;
maxw = img->comps[0].w; maxh = img->comps[0].h;
unsigned int maxw, maxh, max, i;
int offset, upb;
upb = (int)img->comps[0].prec;
offset = 1<<(upb - 1); upb = (1<<upb)-1;
maxw = (unsigned int)img->comps[0].w; maxh = (unsigned int)img->comps[0].h;
max = maxw * maxh;
y = img->comps[0].data;
cb = img->comps[1].data;
cr = img->comps[2].data;
d0 = r = (int*)malloc(sizeof(int) * max);
d1 = g = (int*)malloc(sizeof(int) * max);
d2 = b = (int*)malloc(sizeof(int) * max);
for(i = 0; i < max; ++i)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++cb; ++cr; ++r; ++g; ++b;
}
d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
for(i = 0U; i < max; ++i)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++cb; ++cr; ++r; ++g; ++b;
}
free(img->comps[0].data); img->comps[0].data = d0;
free(img->comps[1].data); img->comps[1].data = d1;
free(img->comps[2].data); img->comps[2].data = d2;
}/* sycc444_to_rgb() */
static void sycc422_to_rgb(opj_image_t *img)
{
{
int *d0, *d1, *d2, *r, *g, *b;
const int *y, *cb, *cr;
int maxw, maxh, max, offset, upb;
int i, j;
i = img->comps[0].prec;
offset = 1<<(i - 1); upb = (1<<i)-1;
maxw = img->comps[0].w; maxh = img->comps[0].h;
unsigned int maxw, maxh, max;
int offset, upb;
unsigned int i, j;
upb = (int)img->comps[0].prec;
offset = 1<<(upb - 1); upb = (1<<upb)-1;
maxw = (unsigned int)img->comps[0].w; maxh = (unsigned int)img->comps[0].h;
max = maxw * maxh;
y = img->comps[0].data;
cb = img->comps[1].data;
cr = img->comps[2].data;
d0 = r = (int*)malloc(sizeof(int) * max);
d1 = g = (int*)malloc(sizeof(int) * max);
d2 = b = (int*)malloc(sizeof(int) * max);
for(i=0; i < maxh; ++i)
{
for(j=0; j < maxw; j += 2)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b; ++cb; ++cr;
}
}
d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
for(i=0U; i < maxh; ++i)
{
for(j=0U; j < (maxw & ~(unsigned int)1U); j += 2U)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b; ++cb; ++cr;
}
if (j < maxw) {
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b; ++cb; ++cr;
}
}
free(img->comps[0].data); img->comps[0].data = d0;
free(img->comps[1].data); img->comps[1].data = d1;
free(img->comps[2].data); img->comps[2].data = d2;
img->comps[1].w = maxw; img->comps[1].h = maxh;
img->comps[2].w = maxw; img->comps[2].h = maxh;
img->comps[1].dx = img->comps[0].dx;
img->comps[2].dx = img->comps[0].dx;
img->comps[1].dy = img->comps[0].dy;
img->comps[2].dy = img->comps[0].dy;
}/* sycc422_to_rgb() */
static void sycc420_to_rgb(opj_image_t *img)
{
int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
const int *y, *cb, *cr, *ny;
int maxw, maxh, max, offset, upb;
int i, j;
i = img->comps[0].prec;
offset = 1<<(i - 1); upb = (1<<i)-1;
maxw = img->comps[0].w; maxh = img->comps[0].h;
unsigned int maxw, maxh, max;
int offset, upb;
unsigned int i, j;
upb = (int)img->comps[0].prec;
offset = 1<<(upb - 1); upb = (1<<upb)-1;
maxw = (unsigned int)img->comps[0].w; maxh = (unsigned int)img->comps[0].h;
max = maxw * maxh;
y = img->comps[0].data;
cb = img->comps[1].data;
cr = img->comps[2].data;
d0 = r = (int*)malloc(sizeof(int) * max);
d1 = g = (int*)malloc(sizeof(int) * max);
d2 = b = (int*)malloc(sizeof(int) * max);
for(i=0; i < maxh; i += 2)
{
ny = y + maxw;
nr = r + maxw; ng = g + maxw; nb = b + maxw;
for(j=0; j < maxw; j += 2)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
++ny; ++nr; ++ng; ++nb;
sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
}
y += maxw; r += maxw; g += maxw; b += maxw;
}
d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
for(i=0U; i < (maxh & ~(unsigned int)1U); i += 2U)
{
ny = y + maxw;
nr = r + maxw; ng = g + maxw; nb = b + maxw;
for(j=0; j < (maxw & ~(unsigned int)1U); j += 2U)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
++ny; ++nr; ++ng; ++nb;
sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
}
if(j < maxw)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
}
y += maxw; r += maxw; g += maxw; b += maxw;
}
if(i < maxh)
{
for(j=0U; j < (maxw & ~(unsigned int)1U); j += 2U)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b;
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
++y; ++r; ++g; ++b; ++cb; ++cr;
}
if(j < maxw)
{
sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
}
}
free(img->comps[0].data); img->comps[0].data = d0;
free(img->comps[1].data); img->comps[1].data = d1;
free(img->comps[2].data); img->comps[2].data = d2;
img->comps[1].w = maxw; img->comps[1].h = maxh;
img->comps[2].w = maxw; img->comps[2].h = maxh;
img->comps[1].dx = img->comps[0].dx;
img->comps[2].dx = img->comps[0].dx;
img->comps[1].dy = img->comps[0].dy;
img->comps[2].dy = img->comps[0].dy;
}/* sycc420_to_rgb() */
void color_sycc_to_rgb(opj_image_t *img)
{
if(img->numcomps < 3)
{
img->color_space = CLRSPC_GRAY;
return;
}
if(img->numcomps < 3)
{
img->color_space = CLRSPC_GRAY;
return;
}
if((img->comps[0].dx == 1)
&& (img->comps[1].dx == 2)
&& (img->comps[2].dx == 2)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 2)
&& (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
{
sycc420_to_rgb(img);
}
&& (img->comps[1].dx == 2)
&& (img->comps[2].dx == 2)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 2)
&& (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
{
sycc420_to_rgb(img);
}
else
if((img->comps[0].dx == 1)
&& (img->comps[1].dx == 2)
&& (img->comps[2].dx == 2)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 1)
&& (img->comps[2].dy == 1))/* horizontal sub-sample only */
if((img->comps[0].dx == 1)
&& (img->comps[1].dx == 2)
&& (img->comps[2].dx == 2)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 1)
&& (img->comps[2].dy == 1))/* horizontal sub-sample only */
{
sycc422_to_rgb(img);
}
else
if((img->comps[0].dx == 1)
&& (img->comps[1].dx == 1)
&& (img->comps[2].dx == 1)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 1)
&& (img->comps[2].dy == 1))/* no sub-sample */
{
sycc444_to_rgb(img);
}
else
{
fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
__FILE__,__LINE__);
return;
}
sycc422_to_rgb(img);
}
else
if((img->comps[0].dx == 1)
&& (img->comps[1].dx == 1)
&& (img->comps[2].dx == 1)
&& (img->comps[0].dy == 1)
&& (img->comps[1].dy == 1)
&& (img->comps[2].dy == 1))/* no sub-sample */
{
sycc444_to_rgb(img);
}
else
{
fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__,__LINE__);
return;
}
img->color_space = CLRSPC_SRGB;
}/* color_sycc_to_rgb() */
#if defined(HAVE_LIBLCMS2) || defined(HAVE_LIBLCMS1)
@@ -286,178 +307,226 @@ void color_apply_icc_profile(opj_image_t *image)
int *r, *g, *b;
int prec, i, max, max_w, max_h;
OPJ_COLOR_SPACE oldspace;
in_prof =
cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
in_prof =
cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
#ifdef DEBUG_PROFILE
FILE *icm = fopen("debug.icm","wb");
fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
fclose(icm);
#endif
if(in_prof == NULL) return;
in_space = cmsGetPCS(in_prof);
(void)in_space;
out_space = cmsGetColorSpace(in_prof);
intent = cmsGetHeaderRenderingIntent(in_prof);
max_w = image->comps[0].w; max_h = image->comps[0].h;
prec = image->comps[0].prec;
(void)prec;
max_w = (int)image->comps[0].w;
max_h = (int)image->comps[0].h;
prec = (int)image->comps[0].prec;
oldspace = image->color_space;
if(out_space == cmsSigRgbData) /* enumCS 16 */
{
in_type = TYPE_RGB_16;
out_type = TYPE_RGB_16;
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
{
if( prec <= 8 )
{
in_type = TYPE_RGB_8;
out_type = TYPE_RGB_8;
}
else
{
in_type = TYPE_RGB_16;
out_type = TYPE_RGB_16;
}
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
else if(out_space == cmsSigGrayData) /* enumCS 17 */
{
in_type = TYPE_GRAY_8;
out_type = TYPE_RGB_8;
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
else if(out_space == cmsSigYCbCrData) /* enumCS 18 */
{
in_type = TYPE_YCbCr_16;
out_type = TYPE_RGB_16;
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
else
if(out_space == cmsSigGrayData) /* enumCS 17 */
{
in_type = TYPE_GRAY_8;
out_type = TYPE_RGB_8;
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
else
if(out_space == cmsSigYCbCrData) /* enumCS 18 */
{
in_type = TYPE_YCbCr_16;
out_type = TYPE_RGB_16;
out_prof = cmsCreate_sRGBProfile();
image->color_space = CLRSPC_SRGB;
}
else
{
{
#ifdef DEBUG_PROFILE
fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
"output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
__FILE__,__LINE__,out_space,
(out_space>>24) & 0xff,(out_space>>16) & 0xff,
(out_space>>8) & 0xff, out_space & 0xff);
fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
"output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
__FILE__,__LINE__,out_space,
(out_space>>24) & 0xff,(out_space>>16) & 0xff,
(out_space>>8) & 0xff, out_space & 0xff);
#endif
return;
}
return;
}
#ifdef DEBUG_PROFILE
fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
"\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
max_w,max_h, (void*)in_prof,(void*)out_prof);
fprintf(stderr,"\trender_intent (%u)\n\t"
"color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
" type: in(%u) out:(%u)\n",
intent,
in_space,
(in_space>>24) & 0xff,(in_space>>16) & 0xff,
(in_space>>8) & 0xff, in_space & 0xff,
out_space,
(out_space>>24) & 0xff,(out_space>>16) & 0xff,
(out_space>>8) & 0xff, out_space & 0xff,
in_type,out_type
);
fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
"\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
max_w,max_h, (void*)in_prof,(void*)out_prof);
fprintf(stderr,"\trender_intent (%u)\n\t"
"color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
" type: in(%u) out:(%u)\n",
intent,
in_space,
(in_space>>24) & 0xff,(in_space>>16) & 0xff,
(in_space>>8) & 0xff, in_space & 0xff,
out_space,
(out_space>>24) & 0xff,(out_space>>16) & 0xff,
(out_space>>8) & 0xff, out_space & 0xff,
in_type,out_type
);
#else
(void)prec;
(void)in_space;
#endif /* DEBUG_PROFILE */
transform = cmsCreateTransform(in_prof, in_type,
out_prof, out_type, intent, 0);
transform = cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0);
#ifdef HAVE_LIBLCMS2
/* Possible for: LCMS_VERSION >= 2000 :*/
/* Possible for: LCMS_VERSION >= 2000 :*/
cmsCloseProfile(in_prof);
cmsCloseProfile(out_prof);
#endif
if(transform == NULL)
{
{
#ifdef DEBUG_PROFILE
fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
"ICC Profile ignored.\n",__FILE__,__LINE__);
fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
"ICC Profile ignored.\n",__FILE__,__LINE__);
#endif
image->color_space = oldspace;
image->color_space = oldspace;
#ifdef HAVE_LIBLCMS1
cmsCloseProfile(in_prof);
cmsCloseProfile(out_prof);
cmsCloseProfile(in_prof);
cmsCloseProfile(out_prof);
#endif
return;
}
return;
}
if(image->numcomps > 2)/* RGB, RGBA */
{
unsigned short *inbuf, *outbuf, *in, *out;
max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned short);
in = inbuf = (unsigned short*)malloc(nr_samples);
out = outbuf = (unsigned short*)malloc(nr_samples);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*in++ = (unsigned short)*r++;
*in++ = (unsigned short)*g++;
*in++ = (unsigned short)*b++;
}
cmsDoTransform(transform, inbuf, outbuf, max);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*r++ = (int)*out++;
*g++ = (int)*out++;
*b++ = (int)*out++;
}
free(inbuf); free(outbuf);
}
{
if( prec <= 8 )
{
unsigned char *inbuf, *outbuf, *in, *out;
max = max_w * max_h;
nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
in = inbuf = (unsigned char*)malloc(nr_samples);
out = outbuf = (unsigned char*)malloc(nr_samples);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*in++ = (unsigned char)*r++;
*in++ = (unsigned char)*g++;
*in++ = (unsigned char)*b++;
}
cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*r++ = (int)*out++;
*g++ = (int)*out++;
*b++ = (int)*out++;
}
free(inbuf); free(outbuf);
}
else
{
unsigned short *inbuf, *outbuf, *in, *out;
max = max_w * max_h;
nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
in = inbuf = (unsigned short*)malloc(nr_samples);
out = outbuf = (unsigned short*)malloc(nr_samples);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*in++ = (unsigned short)*r++;
*in++ = (unsigned short)*g++;
*in++ = (unsigned short)*b++;
}
cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*r++ = (int)*out++;
*g++ = (int)*out++;
*b++ = (int)*out++;
}
free(inbuf); free(outbuf);
}
}
else /* GRAY, GRAYA */
{
unsigned char *in, *inbuf, *out, *outbuf;
max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned char);
in = inbuf = (unsigned char*)malloc(nr_samples);
out = outbuf = (unsigned char*)malloc(nr_samples);
image->comps = (opj_image_comp_t*)
realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
if(image->numcomps == 2)
image->comps[3] = image->comps[1];
image->comps[1] = image->comps[0];
image->comps[2] = image->comps[0];
image->comps[1].data = (int*)calloc(max, sizeof(int));
image->comps[2].data = (int*)calloc(max, sizeof(int));
image->numcomps += 2;
r = image->comps[0].data;
for(i = 0; i < max; ++i)
{
*in++ = (unsigned char)*r++;
}
cmsDoTransform(transform, inbuf, outbuf, max);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
}
free(inbuf); free(outbuf);
}/* if(image->numcomps */
{
unsigned char *in, *inbuf, *out, *outbuf;
max = max_w * max_h;
nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
in = inbuf = (unsigned char*)malloc(nr_samples);
out = outbuf = (unsigned char*)malloc(nr_samples);
image->comps = (opj_image_comp_t*)realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
if(image->numcomps == 2)
image->comps[3] = image->comps[1];
image->comps[1] = image->comps[0];
image->comps[2] = image->comps[0];
image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
image->numcomps += 2;
r = image->comps[0].data;
for(i = 0; i < max; ++i)
{
*in++ = (unsigned char)*r++;
}
cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
for(i = 0; i < max; ++i)
{
*r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
}
free(inbuf); free(outbuf);
}/* if(image->numcomps */
cmsDeleteTransform(transform);
#ifdef HAVE_LIBLCMS1
cmsCloseProfile(in_prof);
cmsCloseProfile(out_prof);

View File

@@ -1,6 +1,8 @@
# Makefile for the MJ2 codecs of the OpenJPEG library: frames_to_mj2, mj2_to_frames, extract_j2k_from_mj2 and wrap_j2k_in_mj2
if(NOT USE_SYSTEM_GETOPT)
SET(common_SRCS ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c)
endif()
# While mj2 executables do not use the API correctly, we do not link with the library but rather compile the sources files.
SET(OPJ_SRCS

View File

@@ -39,7 +39,9 @@ IF(UNIX)
TARGET_LINK_LIBRARIES(${OPENJPEG_LIBRARY_NAME} m)
ENDIF(UNIX)
SET_TARGET_PROPERTIES(${OPENJPEG_LIBRARY_NAME} PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES})
IF(${CMAKE_VERSION} VERSION_GREATER "2.8.11")
TARGET_COMPILE_OPTIONS(${OPENJPEG_LIBRARY_NAME} PRIVATE ${OPENJPEG_LIBRARY_COMPILE_OPTIONS})
ENDIF()
# Build the JPWL library ?
IF(BUILD_JPWL)
ADD_SUBDIRECTORY(jpwl)

View File

@@ -43,6 +43,26 @@ The functions in INT.H have for goal to realize operations on integers.
/** @name Exported functions (see also openjpeg.h) */
/*@{*/
/* ----------------------------------------------------------------------- */
#include <assert.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
#if defined(_WIN32)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#error unsupported platform
#endif
#endif
/**
Get the minimum of two integers
@return Returns a if a < b else b
@@ -84,15 +104,26 @@ Divide an integer and round upwards
@return Returns a divided by b
*/
static INLINE int int_ceildiv(int a, int b) {
return (a + b - 1) / b;
assert(b);
return (a + b - 1) / b;
}
/**
Divide an integer by a power of 2 and round upwards
@return Returns a divided by 2^b
*/
static INLINE int int_ceildivpow2(int a, int b) {
return (a + (1 << b) - 1) >> b;
return (int)((a + ((int64_t)1 << b) - 1) >> b);
}
/**
Divide a 64bits integer by a power of 2 and round upwards
@return Returns a divided by 2^b
*/
static INLINE int int64_ceildivpow2(int64_t a, int b) {
return (int)((a + ((int64_t)1 << b) - 1) >> b);
}
/**
Divide an integer by a power of 2 and round downwards
@return Returns a divided by 2^b

View File

@@ -247,6 +247,12 @@ Add tile header marker information
@param len length of marker segment
*/
static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len);
/**
Validate encoding parameters and image before actual encoding
@param j2k J2K handle
@param image IMAGE handle
*/
static opj_bool j2k_validate_encode( opj_j2k_t *j2k, opj_image_t *image);
/*@}*/
@@ -426,13 +432,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
opj_event_msg(j2k->cinfo, EVT_ERROR,
"invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n",
image->x0,image->x1,image->y0,image->y1);
j2k->state |= J2K_STATE_ERR;
return;
}
n_comps = (len - 36 - 2 ) / 3;
assert( (len - 36 - 2 ) % 3 == 0 );
image->numcomps = cio_read(cio, 2); /* Csiz */
assert( n_comps == image->numcomps );
image->numcomps = cio_read(cio, 2); /* Csiz */
if (((len - 36 - 2 ) % 3 != 0)||(n_comps != image->numcomps)) {
opj_event_msg(j2k->cinfo, EVT_ERROR,"invalid SIZ marker value\n");
j2k->state |= J2K_STATE_ERR;
return;
}
/* testcase 4035.pdf.SIGSEGV.d8b.3375 */
if (image->x0 > image->x1 || image->y0 > image->y1) {
@@ -1125,6 +1135,8 @@ static void j2k_read_poc(opj_j2k_t *j2k) {
poc->resno0 = cio_read(cio, 1); /* RSpoc_i */
poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2); /* CSpoc_i */
poc->layno1 = cio_read(cio, 2); /* LYEpoc_i */
/* make sure layer end is in acceptable bounds - issue 80*/
poc->layno1 = int_min(poc->layno1, (unsigned int) tcp->numlayers);
poc->resno1 = cio_read(cio, 1); /* REpoc_i */
poc->compno1 = int_min(
cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps); /* CEpoc_i */
@@ -1227,6 +1239,7 @@ static void j2k_read_ppm(opj_j2k_t *j2k) {
Z_ppm = cio_read(cio, 1); /* Z_ppm */
len -= 3;
while (len > 0) {
if (cp->ppm_previous == 0) {
N_ppm = cio_read(cio, 4); /* N_ppm */
@@ -1234,9 +1247,16 @@ static void j2k_read_ppm(opj_j2k_t *j2k) {
} else {
N_ppm = cp->ppm_previous;
}
/* issue 362-2863, issue 393 */
if (N_ppm < 0) {
j2k->state = J2K_STATE_ERR;
return;
}
j = cp->ppm_store;
if (Z_ppm == 0) { /* First PPM marker */
cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char));
if (Z_ppm == 0) { /* First PPM marker */
cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char));
cp->ppm_data_first = cp->ppm_data;
cp->ppm_len = N_ppm;
} else { /* NON-first PPM marker */
@@ -1710,6 +1730,8 @@ static void j2k_read_eoc(opj_j2k_t *j2k) {
}
/* if packets should not be decoded */
else {
opj_event_msg(j2k->cinfo, EVT_INFO, "Codestream parsing complete.\n");
opj_event_msg(j2k->cinfo, EVT_INFO, "Skipped actual packet decoding.\n");
for (i = 0; i < j2k->cp->tileno_size; i++) {
tileno = j2k->cp->tileno[i];
opj_free(j2k->tile_data[tileno]);
@@ -2448,6 +2470,9 @@ opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_code
cp = j2k->cp;
/* Parameters validation */
if (!j2k_validate_encode(j2k, image)) return OPJ_FALSE;
/* INDEX >> */
j2k->cstr_info = cstr_info;
if (cstr_info) {
@@ -2696,3 +2721,21 @@ static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsi
marker->len = len;
cstr_info->tile[tileno].marknum++;
}
static opj_bool j2k_validate_encode(opj_j2k_t *j2k, opj_image_t *image) {
int compno;
opj_bool is_valid = OPJ_TRUE;
/* preconditions */
assert(j2k != 00);
assert(image != 00);
/* PARAMETERS checking */
for (compno=0; compno < image->numcomps; compno++) {
is_valid &= (image->comps[compno].dx >= 1 && j2k->image->comps[compno].dx <= 255);
is_valid &= (image->comps[compno].dy >= 1 && j2k->image->comps[compno].dy <= 255);
}
return is_valid;
}

View File

@@ -26,8 +26,10 @@ ADD_LIBRARY(${OPENJPEG_LIBRARY_NAME}_JPWL ${JPWL_SRCS} ${OPENJPEG_SRCS})
IF(UNIX)
TARGET_LINK_LIBRARIES(${OPENJPEG_LIBRARY_NAME}_JPWL m)
ENDIF(UNIX)
SET_TARGET_PROPERTIES(${OPENJPEG_LIBRARY_NAME}_JPWL
PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES})
SET_TARGET_PROPERTIES(${OPENJPEG_LIBRARY_NAME}_JPWL PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES})
IF(${CMAKE_VERSION} VERSION_GREATER "2.8.11")
TARGET_COMPILE_OPTIONS(${OPENJPEG_LIBRARY_NAME}_JPWL PRIVATE ${OPENJPEG_LIBRARY_COMPILE_OPTIONS})
ENDIF()
# Install library
INSTALL(TARGETS ${OPENJPEG_LIBRARY_NAME}_JPWL

View File

@@ -46,6 +46,7 @@
OpenJPEG interface
==========================================================
*/
#include "opj_config.h"
#include "openjpeg.h"
/*

View File

@@ -340,12 +340,12 @@ static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) {
pi->dx = 0;
pi->dy = 0;
for (resno = 0; resno < comp->numresolutions; resno++) {
int dx, dy;
int64 dx, dy;
res = &comp->resolutions[resno];
dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
dx = comp->dx * (((int64) 1) << (res->pdx + comp->numresolutions - 1 - resno));
dy = comp->dy * (((int64) 1) << (res->pdy + comp->numresolutions - 1 - resno));
pi->dx = !pi->dx ? dx : pi->dx < dx ? pi->dx : dx;
pi->dy = !pi->dy ? dy : pi->dy < dy ? pi->dy : dy;
}
if (!pi->tp_on){
pi->poc.ty0 = pi->ty0;

View File

@@ -93,8 +93,8 @@ typedef struct opj_pi_iterator {
int numcomps;
/** Components*/
opj_pi_comp_t *comps;
int tx0, ty0, tx1, ty1;
int x, y, dx, dy;
int tx0, ty0, tx1, ty1;
int64 x, y, dx, dy;
} opj_pi_iterator_t;
/** @name Exported functions */

View File

@@ -276,10 +276,10 @@ void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int c
band->y1 = int_ceildivpow2(tilec->y1, levelno);
} else {
/* band border (global) */
band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
band->x0 = int64_ceildivpow2(tilec->x0 - ((int64_t)x0b << levelno), levelno + 1);
band->y0 = int64_ceildivpow2(tilec->y0 - ((int64_t)y0b << levelno), levelno + 1);
band->x1 = int64_ceildivpow2(tilec->x1 - ((int64_t)x0b << levelno), levelno + 1);
band->y1 = int64_ceildivpow2(tilec->y1 - ((int64_t)y0b << levelno), levelno + 1);
}
ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
@@ -789,10 +789,10 @@ void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp,
band->y1 = int_ceildivpow2(tilec->y1, levelno);
} else {
/* band border (global) */
band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
band->x0 = int64_ceildivpow2(tilec->x0 - ((int64_t)x0b << levelno), levelno + 1);
band->y0 = int64_ceildivpow2(tilec->y0 - ((int64_t)y0b << levelno), levelno + 1);
band->x1 = int64_ceildivpow2(tilec->x1 - ((int64_t)x0b << levelno), levelno + 1);
band->y1 = int64_ceildivpow2(tilec->y1 - ((int64_t)y0b << levelno), levelno + 1);
}
ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
@@ -988,7 +988,7 @@ void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
n = passno + 1;
continue;
}
if (dd / dr >= thresh)
if (thresh - (dd / dr) < DBL_EPSILON) /* do not rely on float equality, check with DBL_EPSILON margin */
n = passno + 1;
}
layer->numpasses = n - cblk->numpassesinlayers;
@@ -1433,10 +1433,12 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
return OPJ_FALSE;
}
else {
tcd->image->comps[compno].resno_decoded =
tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
tcd->image->comps[compno].resno_decoded = tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
}
}
else {
tcd->image->comps[compno].resno_decoded = tile->comps[compno].numresolutions - 1;
}
numres2decode = tcd->image->comps[compno].resno_decoded + 1;
if(numres2decode > 0){

View File

@@ -1,5 +1,5 @@
# Tests
INCLUDE_DIRECTORIES(
include_directories(
${OPENJPEG_SOURCE_DIR}/libopenjpeg
${OPENJPEG_SOURCE_DIR}/applications/codec
${OPENJPEG_SOURCE_DIR}/applications/common
@@ -9,50 +9,73 @@ INCLUDE_DIRECTORIES(
)
# First thing define the common source:
SET(comparePGXimages_SRCS comparePGXimages.c
set(compare_images_SRCS compare_images.c
${OPENJPEG_SOURCE_DIR}/applications/codec/convert.c
${OPENJPEG_SOURCE_DIR}/applications/codec/converttif.c
# ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
SET(compare_dump_files_SRCS compare_dump_files.c)
SET(compareRAWimages_SRCS compareRAWimages.c)
if(NOT USE_SYSTEM_GETOPT)
list(APPEND comparePGXimages_SRCS ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c)
list(APPEND compare_dump_files_SRCS ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c)
list(APPEND compareRAWimages_SRCS ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c)
list(APPEND compare_images_SRCS
${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
endif()
ADD_EXECUTABLE(comparePGXimages ${comparePGXimages_SRCS})
TARGET_LINK_LIBRARIES(comparePGXimages
set(compare_dump_files_SRCS compare_dump_files.c
#${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
if(NOT USE_SYSTEM_GETOPT)
list(APPEND compare_dump_files_SRCS
${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
endif()
set(compare_raw_files_SRCS compare_raw_files.c
#${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
if(NOT USE_SYSTEM_GETOPT)
list(APPEND compare_raw_files_SRCS
${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c
)
endif()
add_executable(compare_images ${compare_images_SRCS})
target_link_libraries(compare_images
${OPENJPEG_LIBRARY_NAME}
${PNG_LIBNAME} ${TIFF_LIBNAME}
)
# To support universal exe:
IF(ZLIB_FOUND AND APPLE)
TARGET_LINK_LIBRARIES(comparePGXimages z)
ELSe(ZLIB_FOUND AND APPLE)
TARGET_LINK_LIBRARIES(comparePGXimages ${Z_LIBNAME})
ENDIF(ZLIB_FOUND AND APPLE)
if(ZLIB_FOUND AND APPLE)
target_link_libraries(compare_images z)
else(ZLIB_FOUND AND APPLE)
target_link_libraries(compare_images ${Z_LIBNAME})
endif()
ADD_EXECUTABLE(compare_dump_files ${compare_dump_files_SRCS})
add_executable(compare_dump_files ${compare_dump_files_SRCS})
ADD_EXECUTABLE(compareRAWimages ${compareRAWimages_SRCS})
add_executable(compare_raw_files ${compare_raw_files_SRCS})
# No image send to the dashboard if lib PNG is not available.
IF(NOT HAVE_LIBPNG)
MESSAGE(WARNING "Lib PNG seems to be not available: if you want run the non-regression tests with images reported to the dashboard, you need it (try BUILD_THIRDPARTY)")
ENDIF(NOT HAVE_LIBPNG)
if(NOT HAVE_LIBPNG)
message(WARNING "Lib PNG seems to be not available: if you want run the non-regression tests with images reported to the dashboard, you need it (try BUILD_THIRDPARTY)")
endif()
ADD_SUBDIRECTORY(conformance)
ADD_SUBDIRECTORY(nonregression)
ADD_SUBDIRECTORY(unit)
add_subdirectory(conformance)
add_subdirectory(nonregression)
add_subdirectory(unit)
IF(BUILD_JPIP)
IF(JPIP_SERVER)
#SET(s "http://jpip.example.com/myFCGI?target=16.jp2&fsiz=170,170&cnew=http&type=jpp-stream")
SET(s "${JPIP_SERVER}?target=16.jp2&fsiz=170,170&cnew=http&type=jpp-stream")
SET(p "${CMAKE_CURRENT_BINARY_DIR}/jpip.dat")
SET(md5 "62b00c620fb0a600c5ffd413cada4674")
ADD_TEST(NAME TestJPIP1 COMMAND ${CMAKE_COMMAND} -DD_URL:STRING=${s} -DD_FILE:PATH=${p}
-DEXPECTED_MD5=${md5} -P ${PROJECT_SOURCE_DIR}/CMake/JPIPTestDriver.cmake)
ENDIF(JPIP_SERVER)
ENDIF(BUILD_JPIP)
if(BUILD_JPIP)
if(JPIP_SERVER)
#set(s "http://jpip.example.com/myFCGI?target=16.jp2&fsiz=170,170&cnew=http&type=jpp-stream")
set(s "${JPIP_SERVER}?target=16.jp2&fsiz=170,170&cnew=http&type=jpp-stream")
set(p "${CMAKE_CURRENT_BINARY_DIR}/jpip.dat")
set(md5 "d41d8cd98f00b204e9800998ecf8427e")
add_test(NAME TestJPIP1 COMMAND ${CMAKE_COMMAND} -DD_URL:STRING=${s} -DD_FILE:PATH=${p}
-DEXPECTED_MD5=${md5} -P ${PROJECT_SOURCE_DIR}/cmake/JPIPTestDriver.cmake)
endif()
endif()
add_executable(ppm2rgb3 ppm2rgb3.c)
#add_executable(pdf2jp2 pdf2jp2.c)

View File

@@ -1,236 +0,0 @@
/*
* Copyright (c) 2011, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* compareRAWimages.c
*
* Created on: 31 August 2011
* Author: mickael
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "opj_getopt.h"
void compareRAWimages_help_display(void);
typedef struct test_cmp_parameters
{
/** */
char* base_filename;
/** */
char* test_filename;
} test_cmp_parameters;
/*******************************************************************************
* Command line help function
*******************************************************************************/
void compareRAWimages_help_display(void) {
fprintf(stdout,"\nList of parameters for the comparePGX function \n");
fprintf(stdout,"\n");
fprintf(stdout," -b \t REQUIRED \t filename to the reference/baseline RAW image \n");
fprintf(stdout," -t \t REQUIRED \t filename to the test RAW image\n");
fprintf(stdout,"\n");
}
/*******************************************************************************
* Parse command line
*******************************************************************************/
int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
{
int sizemembasefile, sizememtestfile;
int index;
const char optlist[] = "b:t:";
int c;
/* Init parameters*/
param->base_filename = NULL;
param->test_filename = NULL;
opj_opterr = 0;
while ((c = opj_getopt(argc, argv, optlist)) != -1)
switch (c)
{
case 'b':
sizemembasefile = (int)strlen(opj_optarg)+1;
param->base_filename = (char*) malloc(sizemembasefile);
param->base_filename[0] = '\0';
strncpy(param->base_filename, opj_optarg, strlen(opj_optarg));
param->base_filename[strlen(opj_optarg)] = '\0';
/*printf("param->base_filename = %s [%d / %d]\n", param->base_filename, strlen(param->base_filename), sizemembasefile );*/
break;
case 't':
sizememtestfile = (int) strlen(opj_optarg) + 1;
param->test_filename = (char*) malloc(sizememtestfile);
param->test_filename[0] = '\0';
strncpy(param->test_filename, opj_optarg, strlen(opj_optarg));
param->test_filename[strlen(opj_optarg)] = '\0';
/*printf("param->test_filename = %s [%d / %d]\n", param->test_filename, strlen(param->test_filename), sizememtestfile);*/
break;
case '?':
if ((opj_optopt == 'b') || (opj_optopt == 't'))
fprintf(stderr, "Option -%c requires an argument.\n", opj_optopt);
else
if (isprint(opj_optopt)) fprintf(stderr, "Unknown option `-%c'.\n", opj_optopt);
else fprintf(stderr, "Unknown option character `\\x%x'.\n", opj_optopt);
return 1;
default:
fprintf(stderr, "WARNING -> this option is not valid \"-%c %s\"\n", c, opj_optarg);
break;
}
if (opj_optind != argc) {
for (index = opj_optind; index < argc; index++)
fprintf(stderr,"Non-option argument %s\n", argv[index]);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/*******************************************************************************
* MAIN
*******************************************************************************/
int main(int argc, char **argv)
{
test_cmp_parameters inParam;
FILE *file_test=NULL, *file_base=NULL;
unsigned char equal = 1;
/* Get parameters from command line*/
if (parse_cmdline_cmp(argc, argv, &inParam) == EXIT_FAILURE)
{
compareRAWimages_help_display();
/* Free Memory */
if (inParam.base_filename){
free(inParam.base_filename);
inParam.base_filename = NULL;
}
if (inParam.test_filename){
free(inParam.test_filename);
inParam.test_filename = NULL;
}
return EXIT_FAILURE;
}
file_test = fopen(inParam.test_filename, "rb");
if (!file_test) {
fprintf(stderr, "Failed to open %s for reading !!\n", inParam.test_filename);
/* Free Memory */
if (inParam.base_filename){
free(inParam.base_filename);
inParam.base_filename = NULL;
}
if (inParam.test_filename){
free(inParam.test_filename);
inParam.test_filename = NULL;
}
return EXIT_FAILURE;
}
file_base = fopen(inParam.base_filename, "rb");
if (!file_base) {
fprintf(stderr, "Failed to open %s for reading !!\n", inParam.base_filename);
/* Free Memory */
if (inParam.base_filename){
free(inParam.base_filename);
inParam.base_filename = NULL;
}
if (inParam.test_filename){
free(inParam.test_filename);
inParam.test_filename = NULL;
}
fclose(file_test);
return EXIT_FAILURE;
}
/* Read simultaneously the two files*/
while (equal)
{
unsigned char value_test = 0;
unsigned char eof_test = 0;
unsigned char value_base = 0;
unsigned char eof_base = 0;
/* Read one byte*/
if (!fread(&value_test, 1, 1, file_test)) {
eof_test = 1;
}
/* Read one byte*/
if (!fread(&value_base, 1, 1, file_base)) {
eof_base = 1;;
}
/* End of file reached by the two files?*/
if (eof_test && eof_base)
break;
/* End of file reached only by one file?*/
if (eof_test || eof_base)
{
fprintf(stdout,"Files have different sizes.\n");
equal = 0;
}
/* Binary values are equal?*/
if (value_test != value_base)
{
fprintf(stdout,"Binary values read in the file are different.\n");
equal = 0;
}
}
/* Free Memory */
if (inParam.base_filename){
free(inParam.base_filename);
inParam.base_filename = NULL;
}
if (inParam.test_filename){
free(inParam.test_filename);
inParam.test_filename = NULL;
}
fclose(file_test);
fclose(file_base);
if (equal)
{
fprintf(stdout,"---- TEST SUCCEED: Files are equal ----\n");
return EXIT_SUCCESS;
}
else
return EXIT_FAILURE;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,13 +29,13 @@
*
* Created on: 25 juil. 2011
* Author: mickael
* BASELINE MUST BE GENERATED BY UNIX PLATFORM REGARDING TO THE CRLF PROBLEM
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "opj_getopt.h"
@@ -50,7 +50,7 @@ typedef struct test_cmp_parameters
/*******************************************************************************
* Command line help function
*******************************************************************************/
void compare_dump_files_help_display(void) {
static void compare_dump_files_help_display(void) {
fprintf(stdout,"\nList of parameters for the compare_dump_files function \n");
fprintf(stdout,"\n");
fprintf(stdout," -b \t REQUIRED \t filename to the reference/baseline dump file \n");
@@ -60,9 +60,9 @@ void compare_dump_files_help_display(void) {
/*******************************************************************************
* Parse command line
*******************************************************************************/
int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
static int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
{
int sizemembasefile, sizememtestfile;
size_t sizemembasefile, sizememtestfile;
int index;
const char optlist[] = "b:t:";
int c;
@@ -76,43 +76,40 @@ int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
while ((c = opj_getopt(argc, argv, optlist)) != -1)
switch (c)
{
case 'b':
sizemembasefile = (int)strlen(opj_optarg)+1;
param->base_filename = (char*) malloc(sizemembasefile);
param->base_filename[0] = '\0';
strncpy(param->base_filename, opj_optarg, strlen(opj_optarg));
param->base_filename[strlen(opj_optarg)] = '\0';
/*printf("param->base_filename = %s [%d / %d]\n", param->base_filename, strlen(param->base_filename), sizemembasefile );*/
break;
case 't':
sizememtestfile = (int) strlen(opj_optarg) + 1;
param->test_filename = (char*) malloc(sizememtestfile);
param->test_filename[0] = '\0';
strncpy(param->test_filename, opj_optarg, strlen(opj_optarg));
param->test_filename[strlen(opj_optarg)] = '\0';
/*printf("param->test_filename = %s [%d / %d]\n", param->test_filename, strlen(param->test_filename), sizememtestfile);*/
break;
case '?':
if ( (opj_optopt == 'b') || (opj_optopt == 't') )
fprintf(stderr, "Option -%c requires an argument.\n", opj_optopt);
else
if (isprint(opj_optopt)) fprintf(stderr, "Unknown option `-%c'.\n", opj_optopt);
else fprintf(stderr, "Unknown option character `\\x%x'.\n", opj_optopt);
return 1;
default:
fprintf(stderr, "WARNING -> this option is not valid \"-%c %s\"\n", c, opj_optarg);
break;
case 'b':
sizemembasefile = strlen(opj_optarg) + 1;
param->base_filename = (char*) malloc(sizemembasefile);
strcpy(param->base_filename, opj_optarg);
/*printf("param->base_filename = %s [%d / %d]\n", param->base_filename, strlen(param->base_filename), sizemembasefile );*/
break;
case 't':
sizememtestfile = strlen(opj_optarg) + 1;
param->test_filename = (char*) malloc(sizememtestfile);
strcpy(param->test_filename, opj_optarg);
/*printf("param->test_filename = %s [%d / %d]\n", param->test_filename, strlen(param->test_filename), sizememtestfile);*/
break;
case '?':
if ( (opj_optopt == 'b') || (opj_optopt == 't') )
fprintf(stderr, "Option -%c requires an argument.\n", opj_optopt);
else
if (isprint(opj_optopt)) fprintf(stderr, "Unknown option `-%c'.\n", opj_optopt);
else fprintf(stderr, "Unknown option character `\\x%x'.\n", opj_optopt);
return 1;
default:
fprintf(stderr, "WARNING -> this option is not valid \"-%c %s\"\n", c, opj_optarg);
break;
}
if (opj_optind != argc)
{
for (index = opj_optind; index < argc; index++)
fprintf(stderr,"Non-option argument %s\n", argv[index]);
return EXIT_FAILURE;
return 1;
}
return EXIT_SUCCESS;
return 0;
}
/*******************************************************************************
* MAIN
*******************************************************************************/
@@ -120,33 +117,30 @@ int main(int argc, char **argv)
{
test_cmp_parameters inParam;
FILE *fbase=NULL, *ftest=NULL;
int chbase, chtest;
int same = 1;
unsigned long l=1, pos;
int same = 0;
char lbase[256];
char strbase[256];
char ltest[256];
char strtest[256];
if( parse_cmdline_cmp(argc, argv, &inParam) == EXIT_FAILURE )
if( parse_cmdline_cmp(argc, argv, &inParam) == 1 )
{
compare_dump_files_help_display();
if (!inParam.base_filename) free(inParam.base_filename);
if (!inParam.test_filename) free(inParam.test_filename);
return EXIT_FAILURE;
goto cleanup;
}
/* Display Parameters*/
printf("******Parameters********* \n");
printf(" base_filename = %s\n"
" test_filename = %s\n",
inParam.base_filename, inParam.test_filename);
" test_filename = %s\n",
inParam.base_filename, inParam.test_filename);
printf("************************* \n");
/* open base file */
printf("Try to open: %s for reading ... ", inParam.base_filename);
if((fbase = fopen(inParam.base_filename, "rb"))==NULL)
{
printf("Failed.\n");
free(inParam.base_filename);
free(inParam.test_filename);
return EXIT_FAILURE;
goto cleanup;
}
printf("Ok.\n");
@@ -154,105 +148,37 @@ int main(int argc, char **argv)
printf("Try to open: %s for reading ... ", inParam.test_filename);
if((ftest = fopen(inParam.test_filename, "rb"))==NULL)
{
printf("Failed.\n");
fclose(fbase);
free(inParam.base_filename);
free(inParam.test_filename);
return EXIT_FAILURE;
goto cleanup;
}
printf("Ok.\n");
pos=ftell(fbase);
while(!feof(fbase))
while (fgets(lbase, sizeof(lbase), fbase) && fgets(ltest,sizeof(ltest),ftest))
{
chbase = fgetc(fbase);
if(ferror(fbase))
int nbase = sscanf(lbase, "%255[^\r\n]", strbase);
int ntest = sscanf(ltest, "%255[^\r\n]", strtest);
assert( nbase != 255 && ntest != 255 );
if( nbase != 1 || ntest != 1 )
{
printf("Error reading base file.\n");
return EXIT_FAILURE;
fprintf(stderr, "could not parse line from files\n" );
goto cleanup;
}
chtest = fgetc(ftest);
if(ferror(ftest))
if( strcmp( strbase, strtest ) != 0 )
{
printf("Error reading test file.\n");
return EXIT_FAILURE;
}
/* CRLF problem (Baseline must be always generated by unix platform)*/
if (chbase == '\n' && chtest == '\r')
if (fgetc(ftest) == '\n')
chtest = '\n';
if(chbase != chtest)
{
size_t nbytes = 2048;
int CRLF_shift=1;
char *strbase, *strtest, *strbase_d, *strtest_d;
printf("Files differ at line %lu:\n", l);
fseek(fbase,pos,SEEK_SET);
/* Take into account CRLF characters when we write \n into
// dump file when we used WIN platform*/
#ifdef _WIN32
CRLF_shift = 2;
fseek(ftest,pos + l - 1,SEEK_SET);
#else
fseek(ftest,pos,SEEK_SET);
#endif
strbase = (char *) malloc(nbytes + 1);
strtest = (char *) malloc(nbytes + 1);
if (fgets(strbase, nbytes, fbase) == NULL)
fprintf(stderr,"\nWARNING: fgets return a NULL value");
else
{
if (fgets(strtest, nbytes, ftest) == NULL)
fprintf(stderr,"\nWARNING: fgets return a NULL value");
else
{
strbase_d = (char *) malloc(strlen(strbase)+1);
strtest_d = (char *) malloc(strlen(strtest)+1);
strncpy(strbase_d, strbase, strlen(strbase)-1);
strncpy(strtest_d, strtest, strlen(strtest)-CRLF_shift);
strbase_d[strlen(strbase)-1] = '\0';
strtest_d[strlen(strtest)-CRLF_shift] = '\0';
printf("<%s> vs. <%s>\n", strbase_d, strtest_d);
free(strbase_d);free(strtest_d);
}
}
free(strbase);free(strtest);
same = 0;
break;
}
else
{
if (chbase == '\n')
{
l++;
pos = ftell(fbase);
}
fprintf(stderr,"<%s> vs. <%s>\n", strbase, strtest);
goto cleanup;
}
}
same = 1;
printf("\n***** TEST SUCCEED: Files are the same. *****\n");
cleanup:
/*Close File*/
fclose(fbase);
fclose(ftest);
if(fbase) fclose(fbase);
if(ftest) fclose(ftest);
/* Free memory*/
free(inParam.base_filename);
free(inParam.test_filename);
if(same)
{
printf("\n***** TEST SUCCEED: Files are the same. *****\n");
return EXIT_SUCCESS;
}
else return EXIT_FAILURE;
return same ? EXIT_SUCCESS : EXIT_FAILURE;
}

File diff suppressed because it is too large Load Diff

193
tests/compare_raw_files.c Normal file
View File

@@ -0,0 +1,193 @@
/*
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* compare_raw_files.c
*
* Created on: 31 August 2011
* Author: mickael
*
* This is equivalent to the UNIX `cmp` command
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "opj_getopt.h"
typedef struct test_cmp_parameters
{
/** */
char* base_filename;
/** */
char* test_filename;
} test_cmp_parameters;
/*******************************************************************************
* Command line help function
*******************************************************************************/
static void compare_raw_files_help_display(void) {
fprintf(stdout,"\nList of parameters for the compare_raw_files function \n");
fprintf(stdout,"\n");
fprintf(stdout," -b \t REQUIRED \t filename to the reference/baseline RAW image \n");
fprintf(stdout," -t \t REQUIRED \t filename to the test RAW image\n");
fprintf(stdout,"\n");
}
/*******************************************************************************
* Parse command line
*******************************************************************************/
static int parse_cmdline_cmp(int argc, char **argv, test_cmp_parameters* param)
{
size_t sizemembasefile, sizememtestfile;
int index;
const char optlist[] = "b:t:";
int c;
/* Init parameters*/
param->base_filename = NULL;
param->test_filename = NULL;
opj_opterr = 0;
while ((c = opj_getopt(argc, argv, optlist)) != -1)
switch (c)
{
case 'b':
sizemembasefile = strlen(opj_optarg)+1;
free(param->base_filename); /* handle dup option */
param->base_filename = (char*) malloc(sizemembasefile);
strcpy(param->base_filename, opj_optarg);
/*printf("param->base_filename = %s [%d / %d]\n", param->base_filename, strlen(param->base_filename), sizemembasefile );*/
break;
case 't':
sizememtestfile = strlen(opj_optarg) + 1;
free(param->test_filename); /* handle dup option */
param->test_filename = (char*) malloc(sizememtestfile);
strcpy(param->test_filename, opj_optarg);
/*printf("param->test_filename = %s [%d / %d]\n", param->test_filename, strlen(param->test_filename), sizememtestfile);*/
break;
case '?':
if ((opj_optopt == 'b') || (opj_optopt == 't'))
fprintf(stderr, "Option -%c requires an argument.\n", opj_optopt);
else
if (isprint(opj_optopt)) fprintf(stderr, "Unknown option `-%c'.\n", opj_optopt);
else fprintf(stderr, "Unknown option character `\\x%x'.\n", opj_optopt);
return 1;
default:
fprintf(stderr, "WARNING -> this option is not valid \"-%c %s\"\n", c, opj_optarg);
break;
}
if (opj_optind != argc) {
for (index = opj_optind; index < argc; index++)
fprintf(stderr,"Non-option argument %s\n", argv[index]);
return 1;
}
return 0;
}
/*******************************************************************************
* MAIN
*******************************************************************************/
int main(int argc, char **argv)
{
int pos = 0;
test_cmp_parameters inParam;
FILE *file_test=NULL, *file_base=NULL;
unsigned char equal = 0U; /* returns error by default */
/* Get parameters from command line*/
if (parse_cmdline_cmp(argc, argv, &inParam))
{
compare_raw_files_help_display();
goto cleanup;
}
file_test = fopen(inParam.test_filename, "rb");
if (!file_test) {
fprintf(stderr, "Failed to open %s for reading !!\n", inParam.test_filename);
goto cleanup;
}
file_base = fopen(inParam.base_filename, "rb");
if (!file_base) {
fprintf(stderr, "Failed to open %s for reading !!\n", inParam.base_filename);
goto cleanup;
}
/* Read simultaneously the two files*/
equal = 1U;
while (equal)
{
unsigned char value_test = 0;
unsigned char eof_test = 0;
unsigned char value_base = 0;
unsigned char eof_base = 0;
/* Read one byte*/
if (!fread(&value_test, 1, 1, file_test)) {
eof_test = 1;
}
/* Read one byte*/
if (!fread(&value_base, 1, 1, file_base)) {
eof_base = 1;
}
/* End of file reached by the two files?*/
if (eof_test && eof_base)
break;
/* End of file reached only by one file?*/
if (eof_test || eof_base)
{
fprintf(stdout,"Files have different sizes.\n");
equal = 0;
}
/* Binary values are equal?*/
if (value_test != value_base)
{
fprintf(stdout,"Binary values read in the file are different %x vs %x at position %d.\n", value_test, value_base, pos);
equal = 0;
}
pos++;
}
if(equal) fprintf(stdout,"---- TEST SUCCEED: Files are equal ----\n");
cleanup:
if(file_test) fclose(file_test);
if(file_base) fclose(file_base);
/* Free Memory */
free(inParam.base_filename);
free(inParam.test_filename);
return equal ? EXIT_SUCCESS : EXIT_FAILURE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
# NON-REGRESSION TESTS ON THIS DATASET LOCATED ${OPJ_DATA_ROOT}/input/nonregression
cmake_minimum_required(VERSION 2.8.7)
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Temporary)
SET(TEMP ${CMAKE_CURRENT_BINARY_DIR}/Temporary)
@@ -8,19 +10,130 @@ SET(INPUT_NR ${OPJ_DATA_ROOT}/input/nonregression)
SET(INPUT_NR_PATH ${INPUT_NR})
SET(TEMP_PATH ${TEMP})
set(INPUT_CONF_PATH ${OPJ_DATA_ROOT}/input/conformance)
# need kdu_expand if possible
find_package(KAKADU)
# need jpylyzer if possible
find_package(JPYLYZER)
#########################################################################
# GENERATION OF THE TEST SUITE
# GENERATION OF THE TEST SUITE (DUMP)
# Dump all files with the selected extension inside the input directory
# technically j2k_dump should simply parse these one, since syntax is ok.
set(BLACKLIST_JPEG2000_TMP
2539.pdf.SIGFPE.706.1712.jp2
0290cb77c5df21828fa74cf2ab2c84d8.SIGFPE.d25.31.jp2
26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2
4035.pdf.SIGSEGV.d8b.3375.jp2
3635.pdf.asan.77.2930.jp2
issue165.jp2
#edf_c2_1103421.jp2
edf_c2_1178956.jp2
edf_c2_1000290.jp2
#edf_c2_1000691.jp2 # ok
#edf_c2_20.jp2 #looks ok as per kdu_jp2info
edf_c2_1377017.jp2
edf_c2_1002767.jp2
#edf_c2_10025.jp2
edf_c2_1000234.jp2
edf_c2_225881.jp2
edf_c2_1000671.jp2
#edf_c2_1013627.jp2 # weird box, but kdu_jp2info ok
edf_c2_1015644.jp2
edf_c2_101463.jp2
edf_c2_1674177.jp2
edf_c2_1673169.jp2
issue429.jp2
issue427-null-image-size.jp2
issue427-illegal-tile-offset.jp2
)
# Define a list of file which should be gracefully rejected:
set(BLACKLIST_JPEG2000
${BLACKLIST_JPEG2000_TMP}
broken1.jp2
broken2.jp2
broken3.jp2
broken4.jp2
gdal_fuzzer_assert_in_opj_j2k_read_SQcd_SQcc.patch.jp2
gdal_fuzzer_check_comp_dx_dy.jp2
gdal_fuzzer_check_number_of_tiles.jp2
gdal_fuzzer_unchecked_numresolutions.jp2
mem-b2ace68c-1381.jp2
1851.pdf.SIGSEGV.ce9.948.jp2
1888.pdf.asan.35.988.jp2
issue362-2863.jp2 #kdu_jp2info ok
issue362-2866.jp2
issue362-2894.jp2
issue400.jp2 #kdu_jp2info ok
issue364-38.jp2
issue364-903.jp2 #kdu_jp2info ok
issue393.jp2 #kdu_jp2info ok
issue408.jp2 #kdu_jp2info ok
issue420.jp2 #kdu_jp2info ok
27ac957758a35d00d6765a0c86350d9c.SIGFPE.d25.537.jpc #kdu_jp2info crash
3672da2f1f67bbecad27d7181b4e9d7c.SIGFPE.d25.805.jpc #kdu_jp2info crash
issue476.jp2 #kdu_jp2info ok
issue475.jp2 #kdu_jp2info ok
issue413.jp2 #kdu_jp2info ok
)
file(GLOB_RECURSE OPJ_DATA_NR_LIST
"${INPUT_NR}/*.j2k"
"${INPUT_NR}/*.j2c"
"${INPUT_NR}/*.jp2"
"${INPUT_NR}/*.jpc"
#"${INPUT_NR}/*.jpx"
)
foreach(INPUT_FILENAME ${OPJ_DATA_NR_LIST})
get_filename_component(INPUT_FILENAME_NAME ${INPUT_FILENAME} NAME)
#get_filename_component(INPUT_FILENAME_NAME_WE ${INPUT_FILENAME_NAME} NAME_WE)
# cannot use longest extension function, since some name contains multiples
# dots. Instead write out own shortest extension function:
string(FIND ${INPUT_FILENAME_NAME} "." SHORTEST_EXT_POS REVERSE)
string(SUBSTRING ${INPUT_FILENAME_NAME} 0 ${SHORTEST_EXT_POS} INPUT_FILENAME_NAME_WE)
string(REGEX MATCH ${INPUT_FILENAME_NAME} bad_jpeg2000 ${BLACKLIST_JPEG2000})
# Dump the input image
add_test(NAME NR-${INPUT_FILENAME_NAME}-dump
COMMAND j2k_dump
-i ${INPUT_FILENAME}
-o ${TEMP}/${INPUT_FILENAME_NAME}.txt
)
if(bad_jpeg2000)
set_tests_properties(NR-${INPUT_FILENAME_NAME}-dump
PROPERTIES WILL_FAIL TRUE)
else()
# Compare the dump output with the baseline
add_test(NAME NR-${INPUT_FILENAME_NAME}-compare_dump2base
COMMAND compare_dump_files
-b ${BASELINE_NR}/opj_${INPUT_FILENAME_NAME_WE}.txt
-t ${TEMP}/${INPUT_FILENAME_NAME}.txt
)
set_tests_properties(NR-${INPUT_FILENAME_NAME}-compare_dump2base
PROPERTIES DEPENDS
NR-${INPUT_FILENAME_NAME}-dump)
endif()
endforeach()
#########################################################################
# GENERATION OF THE TEST SUITE (DECODE AND ENCODE)
# Read one and more input file(s) (located in ${OPJ_DATA_ROOT}/input/nonregression)
# to know which files processed and with which options.
# Configure the test suite file:
CONFIGURE_FILE("test_suite.ctest.in"
"${CMAKE_CURRENT_BINARY_DIR}/test_suite.ctest"
@ONLY)
"${CMAKE_CURRENT_BINARY_DIR}/test_suite.ctest"
@ONLY)
# Read the file into a list
FILE(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/test_suite.ctest OPJ_TEST_CMD_LINE_LIST)
@@ -29,22 +142,23 @@ FILE(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/test_suite.ctest OPJ_TEST_CMD_LINE_LIST
FILE(GLOB TEST_SUITE_FILES *.ctest.in)
IF (TEST_SUITE_FILES)
FOREACH(TEST_SUITE_FILE ${TEST_SUITE_FILES})
# Avoid to process the official test suite
SET(FILE_ALREADY_READ 0)
STRING(REGEX MATCH "test_suite.ctest.in$" FILE_ALREADY_READ ${TEST_SUITE_FILE})
get_filename_component(TEST_SUITE_FILENAME ${TEST_SUITE_FILE} NAME)
string(REGEX MATCH "^test_suite.ctest.in$" FILE_ALREADY_READ ${TEST_SUITE_FILENAME})
IF(NOT FILE_ALREADY_READ)
# Configure the additional test suite file:
GET_FILENAME_COMPONENT(TEST_SUITE_FILE_SUB ${TEST_SUITE_FILE} NAME_WE)
CONFIGURE_FILE("${TEST_SUITE_FILE}"
"${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUITE_FILE_SUB}.ctest"
@ONLY)
"${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUITE_FILE_SUB}.ctest"
@ONLY)
# Read the additional file into a list
FILE(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/${TEST_SUITE_FILE_SUB}.ctest OPJ_TEST_CMD_LINE_LIST_TEMP)
# Append the list of command
SET(OPJ_TEST_CMD_LINE_LIST ${OPJ_TEST_CMD_LINE_LIST} ${OPJ_TEST_CMD_LINE_LIST_TEMP})
ENDIF(NOT FILE_ALREADY_READ)
ENDFOREACH(TEST_SUITE_FILE)
@@ -56,11 +170,12 @@ ELSE(TEST_SUITE_FILES)
ENDIF(TEST_SUITE_FILES)
set(nonregression_filenames_used)
# Parse the command line found in the file(s)
SET(IT_TEST_ENC 0)
SET(IT_TEST_DEC 0)
FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
SET(IGNORE_LINE_FOUND 0)
# Replace space by ; to generate a list
@@ -68,40 +183,43 @@ FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
# Check if the first argument begin by the comment sign
LIST(GET CMD_ARG_LIST 0 EXE_NAME)
STRING(REGEX MATCH "^#" IGNORE_LINE_FOUND ${EXE_NAME})
IF(IGNORE_LINE_FOUND)
if(EXE_NAME)
STRING(REGEX MATCH "^#" IGNORE_LINE_FOUND ${EXE_NAME})
endif()
IF(IGNORE_LINE_FOUND OR NOT EXE_NAME)
#MESSAGE( STATUS "Current line is ignored: ${OPJ_TEST_CMD_LINE}")
ELSE(IGNORE_LINE_FOUND)
# Check if the first argument begin by the failed sign
SET(FAILED_TEST_FOUND 0)
STRING(REGEX MATCH "^!" FAILED_TEST_FOUND ${EXE_NAME})
IF (FAILED_TEST_FOUND)
# Manage the different cases with the failed sign to remove the first argument which must be image_to_j2k
SET(FAILED_TEST_FOUND_1 0)
STRING(REGEX MATCH "^!image_to_j2k$|^!j2k_to_image$" FAILED_TEST_FOUND_1 ${EXE_NAME})
IF (FAILED_TEST_FOUND_1)
LIST(REMOVE_AT CMD_ARG_LIST 0)
ELSE (FAILED_TEST_FOUND_1)
SET(FAILED_TEST_FOUND_2 0)
LIST(GET CMD_ARG_LIST 1 EXE_NAME)
STRING(REGEX MATCH "^image_to_j2k$|^j2k_to_image$" FAILED_TEST_FOUND_2 ${EXE_NAME})
IF (FAILED_TEST_FOUND_2)
LIST(REMOVE_AT CMD_ARG_LIST 0)
LIST(REMOVE_AT CMD_ARG_LIST 0)
ELSE (FAILED_TEST_FOUND_2)
MESSAGE( FATAL_ERROR "${EXE_NAME} is not the right executable name to encode file (try to use image_to_j2k or j2k_to_image)")
ENDIF (FAILED_TEST_FOUND_2)
@@ -112,11 +230,11 @@ FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
STRING(REGEX MATCH "^image_to_j2k$|^j2k_to_image$" EXE_NAME_FOUND ${EXE_NAME})
IF(EXE_NAME_FOUND)
STRING(REGEX MATCH "image_to_j2k" ENC_TEST_FOUND ${EXE_NAME})
ELSE(EXE_NAME_FOUND)
MESSAGE( FATAL_ERROR "${EXE_NAME} is not the right executable name to encode file (try to use image_to_j2k)")
ENDIF(EXE_NAME_FOUND)
@@ -124,15 +242,15 @@ FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
LIST(REMOVE_AT CMD_ARG_LIST 0)
ENDIF (FAILED_TEST_FOUND)
# Parse the argument list to find the input filename and output filename
SET(CMD_ARG_LIST_2 "")
SET(ARG_POS 0)
SET(INPUT_ARG_POS 0)
SET(OUTPUT_ARG_POS 0)
FOREACH(CMD_ARG_ELT ${CMD_ARG_LIST})
math(EXPR ARG_POS "${ARG_POS}+1" )
STRING(COMPARE EQUAL ${CMD_ARG_ELT} "-i" INPUT_ARG_FOUND)
@@ -148,9 +266,9 @@ FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
ENDIF(OUTPUT_ARG_FOUND)
LIST (APPEND CMD_ARG_LIST_2 ${CMD_ARG_ELT})
ENDFOREACH(CMD_ARG_ELT)
LIST(GET CMD_ARG_LIST_2 ${INPUT_ARG_POS} INPUT_FILENAME)
GET_FILENAME_COMPONENT(INPUT_FILENAME_NAME ${INPUT_FILENAME} NAME)
GET_FILENAME_COMPONENT(INPUT_FILENAME_NAME_WE ${INPUT_FILENAME_NAME} NAME_WE)
@@ -163,125 +281,164 @@ FOREACH(OPJ_TEST_CMD_LINE ${OPJ_TEST_CMD_LINE_LIST})
# ENCODER TEST SUITE
IF(ENC_TEST_FOUND)
math(EXPR IT_TEST_ENC "${IT_TEST_ENC}+1" )
# Encode an image into the jpeg2000 format
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode
COMMAND image_to_j2k
${CMD_ARG_LIST_2}
math(EXPR IT_TEST_ENC "${IT_TEST_ENC}+1" )
# Encode an image into the jpeg2000 format
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode
COMMAND image_to_j2k
${CMD_ARG_LIST_2}
)
IF(FAILED_TEST_FOUND)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode PROPERTIES WILL_FAIL TRUE)
ELSE(FAILED_TEST_FOUND)
# Dump the encoding file
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump
COMMAND j2k_dump
-i ${OUTPUT_FILENAME}
-o ${OUTPUT_FILENAME}-ENC-${IT_TEST_ENC}.txt
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode)
IF(FAILED_TEST_FOUND)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode PROPERTIES WILL_FAIL TRUE)
ELSE(FAILED_TEST_FOUND)
# Dump the encoding file
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump
COMMAND j2k_dump
# Compare the dump file with the baseline
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dump2base
COMMAND compare_dump_files
-b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.txt
-t ${OUTPUT_FILENAME}-ENC-${IT_TEST_ENC}.txt
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dump2base
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump)
# Decode the encoding file with kakadu expand command
IF (KDU_EXPAND_EXECUTABLE)
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref
COMMAND ${KDU_EXPAND_EXECUTABLE}
-i ${OUTPUT_FILENAME}
-o ${OUTPUT_FILENAME}-ENC-${IT_TEST_ENC}.txt
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode)
# Compare the dump file with the baseline
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dump2base
COMMAND compare_dump_files
-b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.txt
-t ${OUTPUT_FILENAME}-ENC-${IT_TEST_ENC}.txt
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dump2base
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-dump)
# Decode the encoding file with kakadu expand command
IF (KDU_EXPAND_EXECUTABLE)
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref
COMMAND ${KDU_EXPAND_EXECUTABLE}
-i ${OUTPUT_FILENAME}
-o ${OUTPUT_FILENAME}.raw
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode)
# Compare the decoding file with baseline generated from the kdu_expand and baseline.j2k
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base
COMMAND compareRAWimages
-b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.raw
-t ${OUTPUT_FILENAME}.raw
-o ${OUTPUT_FILENAME}.raw
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref)
ENDIF()
ENDIF(FAILED_TEST_FOUND)
# DECODER TEST SUITE
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode)
# Compare the decoding file with baseline generated from the kdu_expand and baseline.j2k
ADD_TEST(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base
COMMAND compare_raw_files
-b ${BASELINE_NR}/opj_${OUTPUT_FILENAME_NAME_WE}-ENC-${IT_TEST_ENC}.raw
-t ${OUTPUT_FILENAME}.raw
)
SET_TESTS_PROPERTIES(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-compare_dec-ref-out2base
PROPERTIES DEPENDS
NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-decode-ref)
ENDIF()
# Test the encoded file is a valid JP2 file
if (JPYLYZER_EXECUTABLE)
if (${OUTPUT_FILENAME} MATCHES "\\.jp2$")
add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-jpylyser
COMMAND ${JPYLYZER_EXECUTABLE}
${OUTPUT_FILENAME}
)
set_tests_properties(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-jpylyser PROPERTIES
DEPENDS NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode
PASS_REGULAR_EXPRESSION "<isValidJP2>True</isValidJP2>"
)
endif()
endif(JPYLYZER_EXECUTABLE)
# If lossless compression (simple test is 4 arguments), decompress & compare
list(LENGTH CMD_ARG_LIST_2 ARG_COUNT)
if (ARG_COUNT EQUAL 4)
# can we compare with the input image ?
if (${INPUT_FILENAME_NAME} MATCHES "\\.tif$")
add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-decode
COMMAND j2k_to_image -i ${OUTPUT_FILENAME} -o ${OUTPUT_FILENAME}.lossless.tif
)
set_tests_properties(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-decode PROPERTIES
DEPENDS NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-encode
)
add_test(NAME NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-compare
COMMAND compare_images -b ${INPUT_FILENAME} -t ${OUTPUT_FILENAME}.lossless.tif -n 1 -d
)
set_tests_properties(NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-compare PROPERTIES
DEPENDS NR-ENC-${INPUT_FILENAME_NAME}-${IT_TEST_ENC}-lossless-decode
)
endif()
endif()
endif()
# DECODER TEST SUITE
ELSE(ENC_TEST_FOUND)
string(FIND ${INPUT_FILENAME} "nonregression" nr_pos)
if(${nr_pos} GREATER 0)
list(APPEND nonregression_filenames_used ${INPUT_FILENAME_NAME})
endif()
math(EXPR IT_TEST_DEC "${IT_TEST_DEC}+1" )
# Decode the input image
ADD_TEST(NAME NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-decode
COMMAND j2k_to_image
${CMD_ARG_LIST_2}
)
)
IF(FAILED_TEST_FOUND)
SET_TESTS_PROPERTIES(NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-decode PROPERTIES WILL_FAIL TRUE)
ELSE(FAILED_TEST_FOUND)
# if not failed, check against registered md5:
add_test(NAME NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-decode-md5 COMMAND ${CMAKE_COMMAND}
-DREFFILE:STRING=${CMAKE_CURRENT_SOURCE_DIR}/md5refs.txt
-DFILENAME:STRING=${INPUT_FILENAME_NAME}
-DOUTFILENAME:STRING=${OUTPUT_FILENAME}
-P ${CMAKE_CURRENT_SOURCE_DIR}/checkmd5refs.cmake)
# FIXME: add a compare2base function base on raw which
# can output png diff files if necesary
# ADD_TEST(NAME NR-${filename}-compare2base
# COMMAND comparePGXimages
# -b ${BASELINE_NR}/opj_${filenameRef}
# -t ${TEMP}/${filename}.pgx
# -n ${nbComponents}
# -d
# -s b_t_
# )
set_tests_properties(NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-decode-md5
PROPERTIES DEPENDS NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-decode
)
# FIXME: add a compare2base function base on raw which
# can output png diff files if necesary
# add_test(NR-${filename}-compare2base
# ${EXECUTABLE_OUTPUT_PATH}/compare_images
# -b ${BASELINE_NR}/opj_${filenameRef}
# -t ${TEMP}/${filename}.pgx
# -n ${nbComponents}
# -d
# -s b_t_
# )
#
# SET_TESTS_PROPERTIES(NR-${filename}-compare2base
# PROPERTIES DEPENDS
# NR-${filename}-decode)
# Dump the input image
ADD_TEST(NAME NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-dump
COMMAND j2k_dump
-i ${INPUT_FILENAME}
-o ${TEMP}/${INPUT_FILENAME_NAME}.txt
)
# Compare the dump output with the baseline
ADD_TEST(NAME NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-compare_dump2base
COMMAND compare_dump_files
-b ${BASELINE_NR}/opj_${INPUT_FILENAME_NAME_WE}.txt
-t ${TEMP}/${INPUT_FILENAME_NAME}.txt
)
SET_TESTS_PROPERTIES(NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-compare_dump2base
PROPERTIES DEPENDS
NR-DEC-${INPUT_FILENAME_NAME}-${IT_TEST_DEC}-dump)
# PROPERTIES DEPENDS
# NR-${filename}-decode)
ENDIF(FAILED_TEST_FOUND)
ENDIF(ENC_TEST_FOUND)
ENDIF(IGNORE_LINE_FOUND)
ENDIF()
ENDFOREACH(OPJ_TEST_CMD_LINE)
ENDIF()
ENDIF()
ENDFOREACH()
set(existing_filenames)
foreach(f ${OPJ_DATA_NR_LIST})
get_filename_component(ff ${f} NAME)
list(APPEND existing_filenames ${ff})
endforeach()
if(existing_filenames)
list(REMOVE_ITEM existing_filenames ${nonregression_filenames_used})
endif()
# keep track of new addition:
# if we reach here, then a J2K files was added but no test is present in
# test_suite.ctest.in:
foreach(found_but_no_test ${existing_filenames})
add_test(NAME Found-But-No-Test-${found_but_no_test} COMMAND ${CMAKE_COMMAND} -E echo "${found_but_no_test}")
set_tests_properties(Found-But-No-Test-${found_but_no_test} PROPERTIES WILL_FAIL TRUE)
endforeach()

View File

@@ -16,40 +16,40 @@
# decoding process that the output would be bitwise different (while PSNR would
# be kept identical).
#message("0: ${REFFILE}")
#message("1: ${CMAKE_CURRENT_BINARY_DIR}")
#message("2: ${FILENAME}")
file(GLOB globfiles "Temporary/${FILENAME}*.pgx" )
#message("6: ${globfiles}")
# Another more conventional approach is to store the generated output from
# openjpeg however storing the full generated output is generally useless since
# we do not really care about the exact pixel value, we simply need to known
# when a code change impact output generation. furthermore storing the
# complete generated output file, tends to make the svn:/openjpeg-data really
# big.
# REFFILE follow what md5sum -c would expect as input:
# This script expect two inputs
# REFFILE: Path to the md5sum.txt file
# OUTFILENAME: The name of the generated file we want to check The script will
# check whether a PGX or a PNG file was generated in the test suite (computed
# from OUTFILENAME)
get_filename_component(OUTFILENAME_NAME ${OUTFILENAME} NAME)
string(FIND ${OUTFILENAME_NAME} "." SHORTEST_EXT_POS REVERSE)
string(SUBSTRING ${OUTFILENAME_NAME} 0 ${SHORTEST_EXT_POS} OUTFILENAME_NAME_WE)
file(GLOB globfiles "Temporary/${OUTFILENAME_NAME_WE}*.pgx" "Temporary/${OUTFILENAME_NAME_WE}*.png" "Temporary/${OUTFILENAME_NAME_WE}*.tif")
if(NOT globfiles)
message(SEND_ERROR "Could not find output PGX files: ${OUTFILENAME_NAME_WE}")
endif()
# REFFILE follow what `md5sum -c` would expect as input:
file(READ ${REFFILE} variable)
#string(REGEX REPLACE "\r?\n" ";" variable "${variable}")
foreach(pgxfullpath ${globfiles})
file(MD5 ${pgxfullpath} output)
get_filename_component(pgxfile ${pgxfullpath} NAME)
#message("8: ${pgxfile}")
execute_process(
COMMAND ${CMAKE_COMMAND} -E md5sum ${pgxfile}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Temporary
RESULT_VARIABLE res
OUTPUT_VARIABLE output
ERROR_VARIABLE error_output
OUTPUT_STRIP_TRAILING_WHITESPACE # important
)
# Pass the output back to ctest
if(res)
message(SEND_ERROR "md5 could not be computed, it failed with value ${res}. Output was: ${error_output}")
endif()
#message("3: ${output}")
#message("4: ${variable}")
string(REGEX MATCH "[0-9a-f]+ ${pgxfile}" output_var "${variable}")
#message("5: ${output_var}")
set(output "${output} ${pgxfile}")
if("${output_var}" STREQUAL "${output}")
#message("6: eqal")
message(STATUS "equal: [${output_var}] vs [${output}]")
else()
message(SEND_ERROR "not equal: [${output_var}] vs [${output}]")
endif()

View File

@@ -11,13 +11,25 @@ b8f473c07ba5ebfc195bdd53c3b3b97f buxR.j2k_0.pgx
05c062aca83d13b8095460f38a690a08 Cannotreaddatawithnosizeknown.j2k_0.pgx
6276da0ec5fac44d683d3468b290331d cthead1.j2k_0.pgx
8afcac9a696cc8d753b0eb9f4ae692ff CT_Phillips_JPEG2K_Decompr_Problem.j2k_0.pgx
04d35ab6160c9029549f72358df984da file409752_0.pgx
2813bd6fdc2c306b91b3da3688b8bf49 file409752_1.pgx
e273e2aaea4a4fc1b2cf7c09c53c3cc6 file409752_2.pgx
04d35ab6160c9029549f72358df984da file409752.jp2_0.pgx
2813bd6fdc2c306b91b3da3688b8bf49 file409752.jp2_1.pgx
e273e2aaea4a4fc1b2cf7c09c53c3cc6 file409752.jp2_2.pgx
05c062aca83d13b8095460f38a690a08 illegalcolortransform.j2k_0.pgx
cb28787aa7c223f03e6acad71e244108 issue104_jpxstream.jp2_0.pgx
cb28787aa7c223f03e6acad71e244108 issue104_jpxstream.jp2_1.pgx
cb28787aa7c223f03e6acad71e244108 issue104_jpxstream.jp2_2.pgx
c74edbb49e132b2cfc1eaf7908197b17 issue134.jp2_0.pgx
16fe8ed450da10a6aaae4cf6f467fc21 issue134.jp2_1.pgx
c6091c07bf0ff221008dfb60d893cdff issue134.jp2_2.pgx
cccccccccccccccccccccccccccccccc issue135.j2k_0.pgx
cccccccccccccccccccccccccccccccc issue135.j2k_1.pgx
cccccccccccccccccccccccccccccccc issue135.j2k_2.pgx
aa7461b31e14641586803b23b7fb04f2 issue142.j2k_0.pgx
a809006e7a0c1eed68bc86c96af43fe3 issue142.j2k_1.pgx
74f7a7a194a74a947245b843c62c4054 issue142.j2k_2.pgx
c44662b1f7fe01caa2ebf3ad62948e3e issue171.jp2_0.pgx
f70e8a4e5dbefeb44d50edd79b6c4cf6 issue171.jp2_1.pgx
18bc167a1c851db2fd9f8c7af3289134 issue171.jp2_2.pgx
adda4f5e46845b96dd3df14a76aa7229 issue188_beach_64bitsbox.jp2_0.pgx
90a9709c166019d1e101e7b96d257ed9 issue188_beach_64bitsbox.jp2_1.pgx
37e23d2df06ee60bf0f9f5e1c16054d8 issue188_beach_64bitsbox.jp2_2.pgx
@@ -28,7 +40,15 @@ de992d54d59032eb07d21983dbe8155b issue205.jp2_3.pgx
8fae7a39e459409f64e4529d2214087a issue206_image-000.jp2_0.pgx
555a504a93c9a14f61c894da3b393e87 issue206_image-000.jp2_1.pgx
5f06b7c45446ae20c22cada46478a9dc issue206_image-000.jp2_2.pgx
6e40cbf1dbf7db68ff7975a7a99362b9 issue208.jp2_0.pgx
822f330a38c053130c707cadd31d3b41 issue208.jp2_1.pgx
60316fb101af743c0f3e24924365b178 issue208.jp2_2.pgx
a0823d21d9de699353a3bd1adb23bd1c issue211.jp2_0.pgx
1820161df26c360a62d11800d6cf173f issue211.jp2_1.pgx
e1807db57b5f5192c4b77b83e8b5c477 issue228.j2k_0.pgx
e58242abc2c6d44df187397c55e6fbff issue254.jp2_0.pgx
e58242abc2c6d44df187397c55e6fbff issue254.jp2_1.pgx
e58242abc2c6d44df187397c55e6fbff issue254.jp2_2.pgx
4093cc34d838780b35a8be410247fa7f j2k32.j2k_0.pgx
ce4e556aaa0844b92a92c35c200fc43e j2k32.j2k_1.pgx
ea926520f990640862f3fe6616097613 j2k32.j2k_2.pgx
@@ -36,6 +56,9 @@ ea926520f990640862f3fe6616097613 j2k32.j2k_2.pgx
12a8a4668315d9ae27969991251ce85f kodak_2layers_lrcp.j2c_0.pgx
56d0b0c547d6d5bb12f0c36e88722b11 kodak_2layers_lrcp.j2c_1.pgx
48ba092fb40090c160bbd08bdf7bdbf2 kodak_2layers_lrcp.j2c_2.pgx
12a8a4668315d9ae27969991251ce85f kodak_2layers_lrcp-l2.j2c_0.pgx
56d0b0c547d6d5bb12f0c36e88722b11 kodak_2layers_lrcp-l2.j2c_1.pgx
48ba092fb40090c160bbd08bdf7bdbf2 kodak_2layers_lrcp-l2.j2c_2.pgx
05c062aca83d13b8095460f38a690a08 MarkerIsNotCompliant.j2k_0.pgx
ff73d2bd32951d9e55b02186aac24aff Marrin.jp2_0.pgx
55ce884dd2346af6a5172a434ee578fa Marrin.jp2_1.pgx
@@ -74,6 +97,58 @@ fdad26b1e078aa32bd4b77a5f44da43c orb-blue10-lin-jp2.jp2_2.pgx
7442756e83571c0e87493e03f12b2d34 orb-blue10-win-jp2.jp2_1.pgx
5f99ff2aeb17e167fe7049bcf339d0b3 orb-blue10-win-jp2.jp2_2.pgx
fe028d56d6c7aaee87239a115093412a orb-blue10-win-jp2.jp2_3.pgx
03bd6de1f4e9924f2dcff8d4edaab718 p0_04_1.j2k.png
7898b580781d69fda800016378bab80c p0_04_2.j2k.png
e7cde963434e37ba00e128efb7e5c5c3 p0_04_3.j2k.png
a486db59bf5e7c39275aaf62304cf0b7 p0_04_4.j2k.png
59a08fe073e52a778128f22feffcdaf8 p0_04_5.j2k.png
c6f01ceef58442fed6a6af181b27ff06 p0_04_6_1.j2k.png
c3cbab7a2a5bf6b10f67afdd4e125120 p0_04_6_2.j2k.png
04457ca5d9bde5700140cedf8cf2aeea p0_04_6_3.j2k.png
dac32a0a17d0cc4e4f67d49767fc54c1 p0_04_6_4.j2k.png
ef27ff4ff2f6d7d3919808d7378bf119 p0_04_6_5.j2k.png
44ac3a7d98c90f5ab24b6801a601faa9 p0_04_6.j2k.png
bd0f12125f8e3f367dae1c6179f52212 p0_04.j2k.png
ff00bc86aa73a8266e381c5428c17c28 p1_04_10.j2k.png
72a6b3b455c6b3397f95cdf40ead75a0 p1_04_11.j2k.png
060809d8a5969f162f3b662adc3cbccb p1_04_12.j2k.png
92d8168db18cf51d108b0fc1a4f0aeea p1_04_13.j2k.png
bd5650ff4c977e42e4d84304c92222a0 p1_04_14.j2k.png
3920307d5b6cb855065f144b7683609b p1_04_15.j2k.png
1e94024252ca36e86b09e37370005ad0 p1_04_16.j2k.png
d271f149dc89c4d897fbd935189b159b p1_04_17_t63.j2k.png
060809d8a5969f162f3b662adc3cbccb p1_04_17_t63_r2.j2k.png
c92cb973e7dc716830ddf3d257e93fb3 p1_04_18.t12.j2k.png
c9b66b78895609fb0250ca5bd2e89c1d p1_04_19_t12_r1.j2k.png
68e1408710e68669f434937714fd5623 p1_04_1.j2k.png
d271f149dc89c4d897fbd935189b159b p1_04_2.j2k.png
9583a4c09567d8b67d23c5857ca10dc5 p1_04_3.j2k.png
6f405d502508b37f6133342ab2e7876c p1_04_4.j2k.png
4f084579cba30bec1cc9d89e55e99c5a p1_04_5.j2k.png
cd5326c62fa50d68b0d8f08bc3da617c p1_04_6.j2k.png
e50b0e1c1d28f0a40ad9d5c64a4b1cf4 p1_04.j2k.png
b367ad625d2a44a066b3cdd291da619c p1_06_10_1.j2k.png
0bc2db37548e0f6e342af2ea86380300 p1_06_10_2.j2k.png
32415e97cb64b4fda976c883bbb16103 p1_06_10.j2k.png
32415e97cb64b4fda976c883bbb16103 p1_06_11.j2k.png
3a99df46b0fbf7a9e7703d2b0e7355a5 p1_06_1.j2k.png
2702da6fca94765767365c7d80933ee2 p1_06_2.j2k.png
bb8d24257705393e5536fa77bdeb362c p1_06_3.j2k.png
9add0b9211f51ae2da1d01588ed3f9cf p1_06_4.j2k.png
5d037fefa22029a90d8e3ac82246a2e1 p1_06_5.j2k.png
821d1c176a2908136f5246599a47c462 p1_06_6.j2k.png
9d4cf96edeae63e461bff66d8c0b7b82 p1_06_7_1.j2k.png
6d6713374c1e443539a02f82baad5c98 p1_06_7_2.j2k.png
8317d23c60a0e891405339e0d9848efa p1_06_7_3.j2k.png
aa4a63ad4322a92c7f4d5a7f29ad0723 p1_06_7_4.j2k.png
e8748d54c7696069e14501c85d6f6638 p1_06_7_5.j2k.png
b367ad625d2a44a066b3cdd291da619c p1_06_7_6.j2k.png
93c72c4eaffdf0c3081a00e1d21829f6 p1_06_7.j2k.png
024d2b209513c21438f9b5c60b7d945d p1_06_9_1.j2k.png
c3f42d42eef90d42a98ad27d0612af9f p1_06_9_2.j2k.png
2702da6fca94765767365c7d80933ee2 p1_06_9_3.j2k.png
695444198428363c61871586add6d666 p1_06_9.j2k.png
c494419005e8aae82f46d3f48da6caf1 p1_06.j2k.png
371aa0a7ff40a73b45f1fa41e210d1db pacs.ge.j2k_0.pgx
6ae110e1fb5a869af3dbc5fbc735b0bd relax.jp2_0.pgx
518a8f28dacc034982507f43763b88dd relax.jp2_1.pgx
@@ -82,3 +157,121 @@ cdb1d69eb48ffd8545751326b86d9d7e test_lossless.j2k_0.pgx
a37e7e5811d7c0c7adb61582790ccd33 text_GBR.jp2_0.pgx
fc2173be54954a146b4e2887ee14be06 text_GBR.jp2_1.pgx
14108b4fb8d9126750db0424417ed17d text_GBR.jp2_2.pgx
a73bec4d6d82c8a64203e8fdf893b86d issue412.jp2_0.pgx
a73bec4d6d82c8a64203e8fdf893b86d issue428.jp2_0.pgx
2354cf24a1cc5e4a3b72896b333ba361 issue412.jp2_1.pgx
2354cf24a1cc5e4a3b72896b333ba361 issue428.jp2_1.pgx
77d707ff949371e561e13a8d720108b5 issue412.jp2_2.pgx
77d707ff949371e561e13a8d720108b5 issue428.jp2_2.pgx
2fc600f30ec0bc013befb1874e7adaeb issue414.jp2_0.pgx
354f9bb4668717d5c814cda354ec2b43 issue414.jp2_1.pgx
8b96a253937c4c7dd6b41b4aa11367d9 issue414.jp2_2.pgx
ec6886229ffaeaddfe22ce02b7a75e15 issue414.jp2_3.pgx
6aa5c69c83d6f4d5d65968f34f9bc2a3 issue414.jp2_4.pgx
00f34217ad2f88f4d4e1c5cd0d2c4329 issue399.j2k_0.pgx
d8fb69def2a48a3686483c4353544f4b issue411-ycc444.jp2_0.pgx
d2911f75ed1758057f9b1bf26bcb2400 issue411-ycc444.jp2_1.pgx
f7c23ee589ceda07ffb77a83018606cc issue411-ycc444.jp2_2.pgx
7e5e5546ae7ab4e9257ec30185ff9155 issue411-ycc422.jp2_0.pgx
d5ecef537edf294af83826763c0cf860 issue411-ycc422.jp2_1.pgx
3a8d91d7cf3e8887dd0d29beac030620 issue411-ycc422.jp2_2.pgx
07480962d25b3d8cce18096648963c8a issue411-ycc420.jp2_0.pgx
149a69831b42401f20b8f7492ef99d97 issue411-ycc420.jp2_1.pgx
ec8d1c99db9763a8ba489df4f41dda53 issue411-ycc420.jp2_2.pgx
3c7ff2e4bdae849167be36589f32bcd5 issue458.jp2_0.pgx
f004b48eafb2e52529cc9c7b6a3ff5d2 issue458.jp2_1.pgx
3127bd0a591d113c3c2428c8d2c14ec8 issue458.jp2_2.pgx
dacaf60e4c430916a8c2a9ebec32e71c issue458.jp2_3.pgx
d33fb5dbddb9b9b4438eb51fa27445a3 issue495.jp2_0.pgx
27db8c35e12a5d5eb94d403d2aae2909 issue495.jp2_1.pgx
97da625d2f2d0b75bf891d8083ce8bfb issue495.jp2_2.pgx
86729c5f2b74b2dfd42cb0d8e47aef79 a1_mono_tif-1.tif
fa9b7b896536b25a7a1d8eeeacb59141 a1_mono_tif-10.tif
b0ee13aa90ca4421e09a3b7b41f410c0 a1_mono_tif-12.tif
4699894fedd3758727d8288cd7adb56c a1_mono_tif-14.tif
4ad682c58e63d3223914c10a6656c8ae a1_mono_tif-16.tif
22c2fa09a4d7b9fade6a3cddc6c6a4dc a1_mono_tif-2.tif
996c5e67a663218be90e86bff8ecad89 a1_mono_tif-4.tif
7f451a5ac89915c5cdc023fd8c813a3c a1_mono_tif-6.tif
c3ebfcf478b1c4fc786748813f2b5d53 a1_mono_tif-8.tif
31650ec40241737634179fff6ad306f8 basn4a08_tif-1.tif
abf884080bcfbf58c044a9d86bfa5e5d basn4a08_tif-10.tif
916d97c098d9792993cc91fee4a83f77 basn4a08_tif-12.tif
57643174986481d336db6ddf04b970df basn4a08_tif-14.tif
fb5cf848d63c61dc485c87c9246ee9c7 basn4a08_tif-16.tif
5d7b01d98c82ad563bb28c2d83484a2a basn4a08_tif-2.tif
2401cebbb1d5494fcbe0d899484c342d basn4a08_tif-4.tif
6dbeb5b708bbde76e204c0887da61f6b basn4a08_tif-6.tif
dc40cc1da6de28e7e973c8ba796ca189 basn4a08_tif-8.tif
59e32c45591fd3bb44fe99381a116ba1 basn6a08_tif-1.tif
630e6fb6deba0b3efd93b610561d607a basn6a08_tif-10.tif
765555e75e59de27f7b2177d04f36bc1 basn6a08_tif-12.tif
62384c112d5fe40aefd0a9b0b9a4bcc6 basn6a08_tif-14.tif
d725d41557658a28ab31dff74e2467fa basn6a08_tif-16.tif
96d91df6b10e866ea26ebbf0b8ddc7da basn6a08_tif-2.tif
a324032339808d5fe85d6e354f14c183 basn6a08_tif-4.tif
d60864a6a5c8a49a202d98ae6f5165c7 basn6a08_tif-6.tif
c3e93f61125f82a9832d0b9440468034 basn6a08_tif-8.tif
cfe04d15cf9d615fc36357dcb3b3956b p0_14_tif-1.tif
9ad87e7fddc77ac85e2e92509bee2365 p0_14_tif-10.tif
38e67f9d573e61166761d5eee0104448 p0_14_tif-12.tif
77486f0468694b94290d0b55361498a0 p0_14_tif-14.tif
51be675689949dd08b6ee1427af3eb4a p0_14_tif-16.tif
3e34e94bd8f7380c8d159676fee9ea57 p0_14_tif-2.tif
b6f71c941e3a5b8d2547792ccec58d54 p0_14_tif-4.tif
81fcdd90917efb95aed94c6522d1c188 p0_14_tif-6.tif
6808377b760b4ef3559ba8b14ed9b91a p0_14_tif-8.tif
dd15b3d487d36a3682be0679300a4319 issue235.jp2_0.pgx
b9cd6dc76b141fb1fec15f50c1f70e01 issue235.jp2_1.pgx
3edef2ae197ef30b08deda1b28825399 issue235.jp2_2.pgx
b6a84b3215333efc80326715f9078c58 a1_mono_png-1.png
88f96456667b8b3fd69c406fe40636b5 a1_mono_png-10.png
077148452a9506a2337afa2777c57834 a1_mono_png-12.png
c4eee75c1da8d43e1510cb36326f948b a1_mono_png-14.png
b22b7badb943c5c375b7c55032f49def a1_mono_png-16.png
c7e209abe0d4c5ec1407bfe2cfa932de a1_mono_png-2.png
313d1e2d0d41231003587d3061b6119f a1_mono_png-4.png
d92241d97e8603509027176dd3b3168a a1_mono_png-6.png
a86b3b0720229491ce82556d3fc97bf3 a1_mono_png-8.png
159d1413263e2183e50ecc8dc7487b98 basn4a08_png-1.png
cc501ac5219200ed5d7d33df907d3390 basn4a08_png-10.png
9006ec767be7645c1808eef4e8c6ee7a basn4a08_png-12.png
df3484a4ecfaddc1f62d4bf202944ad5 basn4a08_png-14.png
699c25624e99c72fd45cfdb5660920c2 basn4a08_png-16.png
95090b2194e811e8c490e12632e8a5f3 basn4a08_png-2.png
c66f969b198eff8ddf663a3ccbb8e272 basn4a08_png-4.png
02484627d57e7bcb45d3c1bff11a4687 basn4a08_png-6.png
3bf91c974abc17e520c6a5efa883a58a basn4a08_png-8.png
cd6b948268967b1e9b54d60607b8de0a basn6a08_png-1.png
549e7a5566f37f7e08030cfa2aee8994 basn6a08_png-10.png
d9e6472bc020607327cd082464d03616 basn6a08_png-12.png
54e9b4d5e3fadd939a54722f05cadbe9 basn6a08_png-14.png
94bba5bebc9e9209f2af13c6dd5a2c12 basn6a08_png-16.png
16a9287d409a1c80158973f95eb3c04e basn6a08_png-2.png
4065c615d124289bd06cd9c9bfb4adab basn6a08_png-4.png
3235c0b759dd47e0c2df5bc9ac827e70 basn6a08_png-6.png
0db8bf6fa69191c20936701ef365b82a basn6a08_png-8.png
d3c82c8552f2e47c179372933725c8d7 p0_14_png-1.png
7bce012868556bd04e5c0567b67d2896 p0_14_png-10.png
d66fe6bbe653a18e60416e0cda1b1949 p0_14_png-12.png
b3f01308ae57518ff157c926563b01b2 p0_14_png-14.png
629bc0a76c5454e875eab9cacc653dfd p0_14_png-16.png
fc2844a9f3c8e924e349180ba9e122dd p0_14_png-2.png
428c7a19b9df4120d35b5df7fafdf253 p0_14_png-4.png
0c1cc85c051dd95394d06103c8d9bbef p0_14_png-6.png
230e4968cb445b222ee2095014ba1d26 p0_14_png-8.png
5a6131ad9ea5d191ffcdf6435be89cb4 v4dwt_interleave_h.gsr105.j2k_0.pgx
4426ed46f75a45782c551d82818b9e60 dwt_interleave_h.gsr105.jp2_0.pgx
382e7297e062d729a7a7726e964f1a0a dwt_interleave_h.gsr105.jp2_1.pgx
64c1027db97421e348f823178b5d9c4b dwt_interleave_h.gsr105.jp2_2.pgx
63bf755af5a1f8a478d65079dc7c8964 issue205-tif.jp2.tif
b01ed87dbac424bc820b2ac590e4884e issue236-ESYCC-CDEF.jp2_0.pgx
2635cc00b1e18ef11adcba09e845d459 issue236-ESYCC-CDEF.jp2_1.pgx
f9c95d0aec2f6e7b814fa1d09edcdbda issue236-ESYCC-CDEF.jp2_2.pgx
5f0c1d5c5127c1eabb86a5e0112f139b issue559-eci-090-CIELab.jp2_0.pgx
cdae87485eaada56be3671eec39452e6 issue559-eci-090-CIELab.jp2_1.pgx
e163102afcc857cf001337178241f518 issue559-eci-090-CIELab.jp2_2.pgx
b004b2e08b0dfb217c131b353cf157eb issue559-eci-091-CIELab.jp2_0.pgx
2400da6b8ed6b1747b9913af544580f9 issue559-eci-091-CIELab.jp2_1.pgx
cf73dda887967928dbcf5cc87ab204cc issue559-eci-091-CIELab.jp2_2.pgx

View File

@@ -29,16 +29,126 @@ image_to_j2k -i @INPUT_NR_PATH@/Bretagne2.ppm -o @TEMP_PATH@/Bretagne2_4.j2k -d
image_to_j2k -i @INPUT_NR_PATH@/Cevennes1.bmp -o @TEMP_PATH@/Cevennes1.j2k -r 10
image_to_j2k -i @INPUT_NR_PATH@/Cevennes2.ppm -o @TEMP_PATH@/Cevennes2.jp2 -r 50
image_to_j2k -i @INPUT_NR_PATH@/Rome.bmp -o @TEMP_PATH@/Rome.jp2 -q 30,35,50 -p LRCP -n 3
image_to_j2k -i @INPUT_NR_PATH@/X_4_2K_24_185_CBR_WB_000.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000.j2k -cinema2K 24
image_to_j2k -i @INPUT_NR_PATH@/X_5_2K_24_235_CBR_STEM24_000.tif -o @TEMP_PATH@/X_5_2K_24_235_CBR_STEM24_000.j2k -cinema2K 24
image_to_j2k -i @INPUT_NR_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000.tif -o @TEMP_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000.j2k -cinema2K 24
# related to issue 5
image_to_j2k -i @INPUT_NR_PATH@/random-issue-0005.tif -o @TEMP_PATH@/random-issue-0005.tif.j2k
# related to issue 62
image_to_j2k -i @INPUT_NR_PATH@/tmp-issue-0062.raw -o @TEMP_PATH@/tmp-issue-0062-u.raw.j2k -F 512,512,1,16,u
image_to_j2k -i @INPUT_NR_PATH@/tmp-issue-0062.raw -o @TEMP_PATH@/tmp-issue-0062-s.raw.j2k -F 512,512,1,16,s
image_to_j2k -i @INPUT_NR_PATH@/X_4_2K_24_185_CBR_WB_000.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_C2K_24.j2k -cinema2K 24
image_to_j2k -i @INPUT_NR_PATH@/X_5_2K_24_235_CBR_STEM24_000.tif -o @TEMP_PATH@/X_5_2K_24_235_CBR_STEM24_000_C2K_24.j2k -cinema2K 24
image_to_j2k -i @INPUT_NR_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000.tif -o @TEMP_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000_C2K_24.j2k -cinema2K 24
image_to_j2k -i @INPUT_NR_PATH@/X_4_2K_24_185_CBR_WB_000.tif -o @TEMP_PATH@/X_4_2K_24_185_CBR_WB_000_C2K_48.j2k -cinema2K 48
image_to_j2k -i @INPUT_NR_PATH@/X_5_2K_24_235_CBR_STEM24_000.tif -o @TEMP_PATH@/X_5_2K_24_235_CBR_STEM24_000_C2K_48.j2k -cinema2K 48
image_to_j2k -i @INPUT_NR_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000.tif -o @TEMP_PATH@/X_6_2K_24_FULL_CBR_CIRCLE_000_C2K_48.j2k -cinema2K 48
#not implemented in 1.5
!image_to_j2k -i @INPUT_NR_PATH@/ElephantDream_4K.tif -o @TEMP_PATH@/ElephantDream_4K_C4K.j2k -cinema4K
# issue 141
image_to_j2k -i @INPUT_NR_PATH@/issue141.rawl -o @TEMP_PATH@/issue141.rawl.j2k -F 2048,32,1,16,u
image_to_j2k -i @INPUT_NR_PATH@/issue141.rawl -o @TEMP_PATH@/issue141-I.rawl.j2k -F 2048,32,1,16,u -I
# issue 46:
image_to_j2k -i @INPUT_NR_PATH@/Bretagne2.ppm -o @TEMP_PATH@/Bretagne2_5.j2k -c [64,64]
# issue 316
image_to_j2k -i @INPUT_NR_PATH@/issue316.png -o @TEMP_PATH@/issue316.png.jp2
# issue 416 (cdef for png with alpha) + issue 436 (MCT norm read buffer overflow for num comp > 3 + Issue 215 number of decomp levels
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn6a08.png -o @TEMP_PATH@/basn6a08.png.jp2 -n 6
# issue 322 limited tif support
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-01.tif -o @TEMP_PATH@/flower-minisblack-01.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-02.tif -o @TEMP_PATH@/flower-minisblack-02.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-04.tif -o @TEMP_PATH@/flower-minisblack-04.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-06.tif -o @TEMP_PATH@/flower-minisblack-06.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-08.tif -o @TEMP_PATH@/flower-minisblack-08.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-10.tif -o @TEMP_PATH@/flower-minisblack-10.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-12.tif -o @TEMP_PATH@/flower-minisblack-12.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-14.tif -o @TEMP_PATH@/flower-minisblack-14.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-16.tif -o @TEMP_PATH@/flower-minisblack-16.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-02.tif -o @TEMP_PATH@/flower-rgb-contig-02.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-04.tif -o @TEMP_PATH@/flower-rgb-contig-04.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-08.tif -o @TEMP_PATH@/flower-rgb-contig-08.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-10.tif -o @TEMP_PATH@/flower-rgb-contig-10.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-12.tif -o @TEMP_PATH@/flower-rgb-contig-12.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-14.tif -o @TEMP_PATH@/flower-rgb-contig-14.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-16.tif -o @TEMP_PATH@/flower-rgb-contig-16.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-02.tif -o @TEMP_PATH@/flower-rgb-planar-02.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-04.tif -o @TEMP_PATH@/flower-rgb-planar-04.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-08.tif -o @TEMP_PATH@/flower-rgb-planar-08.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-10.tif -o @TEMP_PATH@/flower-rgb-planar-10.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-12.tif -o @TEMP_PATH@/flower-rgb-planar-12.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-14.tif -o @TEMP_PATH@/flower-rgb-planar-14.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-16.tif -o @TEMP_PATH@/flower-rgb-planar-16.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/basn6a08.tif -o @TEMP_PATH@/basn6a08.tif.jp2
image_to_j2k -i @INPUT_NR_PATH@/basn4a08.tif -o @TEMP_PATH@/basn4a08.tif.jp2
# issue 203 BMP Files not handled properly
image_to_j2k -i @INPUT_NR_PATH@/issue203-8bpp-width1.bmp -o @TEMP_PATH@/issue203-8bpp-width1.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-rle8.bmp -o @TEMP_PATH@/issue203-rle8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-y8.bmp -o @TEMP_PATH@/issue203-32x32-y8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-33x33-y8.bmp -o @TEMP_PATH@/issue203-33x33-y8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-34x34-y8.bmp -o @TEMP_PATH@/issue203-34x34-y8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-35x35-y8.bmp -o @TEMP_PATH@/issue203-35x35-y8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgr.bmp -o @TEMP_PATH@/issue203-32x32-bgr.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-33x33-bgr.bmp -o @TEMP_PATH@/issue203-33x33-bgr.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-34x34-bgr.bmp -o @TEMP_PATH@/issue203-34x34-bgr.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-35x35-bgr.bmp -o @TEMP_PATH@/issue203-35x35-bgr.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-y-rle8.bmp -o @TEMP_PATH@/issue203-32x32-y-rle8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgr-rle8.bmp -o @TEMP_PATH@/issue203-32x32-bgr-rle8.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-y-rle4.bmp -o @TEMP_PATH@/issue203-32x32-y-rle4.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgr-rle4.bmp -o @TEMP_PATH@/issue203-32x32-bgr-rle4.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgra.bmp -o @TEMP_PATH@/issue203-32x32-bgra.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgrx.bmp -o @TEMP_PATH@/issue203-32x32-bgrx.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgr16.bmp -o @TEMP_PATH@/issue203-32x32-bgr16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-33x33-bgr16.bmp -o @TEMP_PATH@/issue203-33x33-bgr16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgra16.bmp -o @TEMP_PATH@/issue203-32x32-bgra16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-33x33-bgra16.bmp -o @TEMP_PATH@/issue203-33x33-bgra16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-32x32-bgrx16.bmp -o @TEMP_PATH@/issue203-32x32-bgrx16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-33x33-bgrx16.bmp -o @TEMP_PATH@/issue203-33x33-bgrx16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-127x64-bgr16.bmp -o @TEMP_PATH@/issue203-127x64-bgr16.bmp.jp2
image_to_j2k -i @INPUT_NR_PATH@/issue203-127x64-bgrx.bmp -o @TEMP_PATH@/issue203-127x64-bgrx.bmp.jp2
# issue 571 Lossless is not lossless on linux x86
image_to_j2k -i @INPUT_NR_PATH@/issue571.tif -o @TEMP_PATH@/issue571.tif.j2k
# issue 536 (PNG images are always read as RGB(A) images) + issue 264 (convert.c is unmaintainable)
# Test all images from pngsuite
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn0g01.png -o @TEMP_PATH@/basn0g01.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn0g02.png -o @TEMP_PATH@/basn0g02.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn0g04.png -o @TEMP_PATH@/basn0g04.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn0g08.png -o @TEMP_PATH@/basn0g08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn0g16.png -o @TEMP_PATH@/basn0g16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn2c08.png -o @TEMP_PATH@/basn2c08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn2c16.png -o @TEMP_PATH@/basn2c16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn3p01.png -o @TEMP_PATH@/basn3p01.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn3p02.png -o @TEMP_PATH@/basn3p02.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn3p04.png -o @TEMP_PATH@/basn3p04.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn3p08.png -o @TEMP_PATH@/basn3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn4a08.png -o @TEMP_PATH@/basn4a08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn4a16.png -o @TEMP_PATH@/basn4a16.png.jp2
# already done image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn6a08.png -o @TEMP_PATH@/basn6a08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn6a16.png -o @TEMP_PATH@/basn6a16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbbn0g01.png -o @TEMP_PATH@/ftbbn0g01.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbbn0g02.png -o @TEMP_PATH@/ftbbn0g02.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbbn0g04.png -o @TEMP_PATH@/ftbbn0g04.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbbn2c16.png -o @TEMP_PATH@/ftbbn2c16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbbn3p08.png -o @TEMP_PATH@/ftbbn3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbgn2c16.png -o @TEMP_PATH@/ftbgn2c16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbgn3p08.png -o @TEMP_PATH@/ftbgn3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbrn2c08.png -o @TEMP_PATH@/ftbrn2c08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbwn0g16.png -o @TEMP_PATH@/ftbwn0g16.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbwn3p08.png -o @TEMP_PATH@/ftbwn3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftbyn3p08.png -o @TEMP_PATH@/ftbyn3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftp0n0g08.png -o @TEMP_PATH@/ftp0n0g08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftp0n2c08.png -o @TEMP_PATH@/ftp0n2c08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftp0n3p08.png -o @TEMP_PATH@/ftp0n3p08.png.jp2
image_to_j2k -i @INPUT_NR_PATH@/pngsuite/ftp1n3p08.png -o @TEMP_PATH@/ftp1n3p08.png.jp2
# DECODER TEST SUITE
j2k_to_image -i @INPUT_NR_PATH@/Bretagne2.j2k -o @TEMP_PATH@/Bretagne2.j2k.pgx
j2k_to_image -i @INPUT_NR_PATH@/_00042.j2k -o @TEMP_PATH@/_00042.j2k.pgx
j2k_to_image -i @INPUT_NR_PATH@/123.j2c -o @TEMP_PATH@/123.j2c.pgx
# The 4 following tests should failed (kakadu indicates that they are corrupted)
!j2k_to_image -i @INPUT_NR_PATH@/broken.jp2 -o @TEMP_PATH@/broken.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/broken1.jp2 -o @TEMP_PATH@/broken1.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/broken2.jp2 -o @TEMP_PATH@/broken2.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/broken3.jp2 -o @TEMP_PATH@/broken3.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/broken4.jp2 -o @TEMP_PATH@/broken4.jp2.pgx
@@ -153,3 +263,254 @@ j2k_to_image -i @INPUT_NR_PATH@/issue226.j2k -o @TEMP_PATH@/is
!j2k_to_image -i @INPUT_NR_PATH@/edf_c2_101463.jp2 -o @TEMP_PATH@/edf_c2_101463.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/edf_c2_1674177.jp2 -o @TEMP_PATH@/edf_c2_1674177.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/edf_c2_1673169.jp2 -o @TEMP_PATH@/edf_c2_1673169.jp2.pgx
# issue 296
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.78.2734.0.jp2 -o @TEMP_PATH@/3459.pdf.asan.78.2734.0.jp2.pgx
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.78.2734.1.jp2 -o @TEMP_PATH@/3459.pdf.asan.78.2734.1.jp2.pgx
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.78.2734.2.jp2 -o @TEMP_PATH@/3459.pdf.asan.78.2734.2.jp2.pgx
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.6c.2734.0.jp2 -o @TEMP_PATH@/3459.pdf.asan.6c.2734.0.jp2.pgx
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.6c.2734.1.jp2 -o @TEMP_PATH@/3459.pdf.asan.6c.2734.1.jp2.pgx
#!j2k_to_image -i @INPUT_NR_PATH@/3459.pdf.asan.6c.2734.2.jp2 -o @TEMP_PATH@/3459.pdf.asan.6c.2734.2.jp2.pgx
# issue 362 (from pdfium fuzz engine)
# Invalid PPM Marker
!j2k_to_image -i @INPUT_NR_PATH@/issue362-2863.jp2 -o @TEMP_PATH@/issue362-2863.jp2.pgx
# Invalid ftyp box size
!j2k_to_image -i @INPUT_NR_PATH@/issue362-2866.jp2 -o @TEMP_PATH@/issue362-2866.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/issue362-2894.jp2 -o @TEMP_PATH@/issue362-2894.jp2.pgx
# issue 363 (from pdfium fuzz engine)
# Invalid Tile part length
!j2k_to_image -i @INPUT_NR_PATH@/issue363-4723.jp2 -o @TEMP_PATH@/issue363-4723.jp2.pgx
# Invalid Marker length
!j2k_to_image -i @INPUT_NR_PATH@/issue363-4740.jp2 -o @TEMP_PATH@/issue363-4740.jp2.pgx
!j2k_to_image -i @INPUT_NR_PATH@/issue363-4792.jp2 -o @TEMP_PATH@/issue363-4792.jp2.pgx
# issue 390 (from pdfium fuzz engine) Invalid segment size
!j2k_to_image -i @INPUT_NR_PATH@/issue390.jp2 -o @TEMP_PATH@/issue390.jp2.pgx
# issue 391 (from pdfium fuzz engine) Invalid segment size
!j2k_to_image -i @INPUT_NR_PATH@/issue391.jp2 -o @TEMP_PATH@/issue391.jp2.pgx
# issue 400 (from pdfium fuzz engine) Unknown Scod value in COD marker
!j2k_to_image -i @INPUT_NR_PATH@/issue400.jp2 -o @TEMP_PATH@/issue400.jp2.pgx
# issue 413 (from pdfium fuzz engine) Unknown progression order in COD marker
!j2k_to_image -i @INPUT_NR_PATH@/issue413.jp2 -o @TEMP_PATH@/issue413.jp2.pgx
# issue 364 (from pdfium fuzz engine)
# Inconsistent box length for jp2 box
!j2k_to_image -i @INPUT_NR_PATH@/issue364-38.jp2 -o @TEMP_PATH@/issue364-38.jp2.pgx
# No ihdr box
!j2k_to_image -i @INPUT_NR_PATH@/issue364-903.jp2 -o @TEMP_PATH@/issue364-903.jp2.pgx
# issue 393 (from pdfium fuzz engine) Zppm found twice
!j2k_to_image -i @INPUT_NR_PATH@/issue393.jp2 -o @TEMP_PATH@/issue393.jp2.pgx
# issue 395 (from pdfium fuzz engine) Stream too short
!j2k_to_image -i @INPUT_NR_PATH@/issue395.jp2 -o @TEMP_PATH@/issue395.jp2.pgx
# issue 397 (from pdfium fuzz engine) Incomplete channel definitions.
!j2k_to_image -i @INPUT_NR_PATH@/issue397.jp2 -o @TEMP_PATH@/issue397.jp2.pgx
# issue 399 (from pdfium fuzz engine) Incomplete channel definitions.
j2k_to_image -i @INPUT_NR_PATH@/issue399.j2k -o @TEMP_PATH@/issue399.j2k.pgx
# issue 408 (from pdfium fuzz engine) No COD marker in main j2k header.
!j2k_to_image -i @INPUT_NR_PATH@/issue408.jp2 -o @TEMP_PATH@/issue408.jp2.pgx
# issue 412 Palette image with cdef fails to decompress.
j2k_to_image -i @INPUT_NR_PATH@/issue412.jp2 -o @TEMP_PATH@/issue412.jp2.pgx
# issue 428 Palette image with cdef fails to decompress properly.
j2k_to_image -i @INPUT_NR_PATH@/issue412.jp2 -o @TEMP_PATH@/issue428.jp2.pgx -t 0
# issue 414 Image with per channel alpha (cdef) does not decode properly.
j2k_to_image -i @INPUT_NR_PATH@/issue414.jp2 -o @TEMP_PATH@/issue414.jp2.pgx
# issue 418 (from pdfium fuzz engine) Tile part length size inconsistent with stream length.
!j2k_to_image -i @INPUT_NR_PATH@/issue418.jp2 -o @TEMP_PATH@/issue418.jp2.pgx
# issue 420 (from pdfium fuzz engine) Illegal custom precinct exponent.
!j2k_to_image -i @INPUT_NR_PATH@/issue420.jp2 -o @TEMP_PATH@/issue420.jp2.pgx
# issue 422 (rework of issue 411). ycc with odd width/height
j2k_to_image -i @INPUT_NR_PATH@/issue411-ycc444.jp2 -o @TEMP_PATH@/issue411-ycc444.jp2.pgx
j2k_to_image -i @INPUT_NR_PATH@/issue411-ycc422.jp2 -o @TEMP_PATH@/issue411-ycc422.jp2.pgx
j2k_to_image -i @INPUT_NR_PATH@/issue411-ycc420.jp2 -o @TEMP_PATH@/issue411-ycc420.jp2.pgx
# issue 429 (from pdfium fuzz engine) 0 entries in PCLR box.
!j2k_to_image -i @INPUT_NR_PATH@/issue429.jp2 -o @TEMP_PATH@/issue429.jp2.pgx
# issue 432 (from pdfium fuzz engine) Overflow in tcd tilec data size computation.
!j2k_to_image -i @INPUT_NR_PATH@/issue432.jp2 -o @TEMP_PATH@/issue432.jp2.pgx
# issue 427 image width is 0
!j2k_to_image -i @INPUT_NR_PATH@/issue427-null-image-size.jp2 -o @TEMP_PATH@/issue427-null-image-size.jp2.pgx
# issue 427 illegal tile offset
!j2k_to_image -i @INPUT_NR_PATH@/issue427-illegal-tile-offset.jp2 -o @TEMP_PATH@/issue427-illegal-tile-offset.jp2.pgx
# issue 458 component precision upscaling
j2k_to_image -i @INPUT_NR_PATH@/issue458.jp2 -o @TEMP_PATH@/issue458.jp2.pgx
# issue 476 Multiple COD in MH
!j2k_to_image -i @INPUT_NR_PATH@/issue476.jp2 -o @TEMP_PATH@/issue476.jp2.pgx
# issue 475 Invalid number of layers
!j2k_to_image -i @INPUT_NR_PATH@/issue475.jp2 -o @TEMP_PATH@/issue475.jp2.pgx
# issue 495 Overflow op_image_comp_header_updat
j2k_to_image -i @INPUT_NR_PATH@/issue495.jp2 -o @TEMP_PATH@/issue495.jp2.pgx
# OPTIONS NOT IMPLEMENTED >
# # decode with specific area
# # prec=12; nb_c=1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04.j2k.png -d 0,0,1024,1024
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_1.j2k.png -d 512,640,640,768
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_2.j2k.png -d 896,896,1024,1024
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_3.j2k.png -d 100,500,300,800
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_4.j2k.png -d 260,520,360,600
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_5.j2k.png -d 260,520,360,660
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_6.j2k.png -d 360,520,400,600
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_10.j2k.png -d 0,0,1024,1024 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_11.j2k.png -d 512,640,640,768 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_12.j2k.png -d 896,896,1024,1024 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_13.j2k.png -d 100,500,300,800 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_14.j2k.png -d 260,520,360,600 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_15.j2k.png -d 260,520,360,660 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_16.j2k.png -d 360,520,400,600 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_17_t63.j2k.png -t 63
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_17_t63_r2.j2k.png -t 63 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_18.t12.j2k.png -t 12
# j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_19_t12_r1.j2k.png -t 12 -r 1
# # prec=8; nb_c=3
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06.j2k.png -d 0,0,12,12
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_1.j2k.png -d 1,8,8,11
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_2.j2k.png -d 9,9,12,12
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_3.j2k.png -d 10,4,12,10
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_4.j2k.png -d 3,3,9,9
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_5.j2k.png -d 4,4,7,7
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_6.j2k.png -d 4,4,5,5
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7.j2k.png -d 0,0,12,12 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_1.j2k.png -d 1,8,8,11 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_2.j2k.png -d 9,9,12,12 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_3.j2k.png -d 10,4,12,10 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_4.j2k.png -d 3,3,9,9 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_5.j2k.png -d 4,4,7,7 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_7_6.j2k.png -d 4,4,5,5 -r 1
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_8_6.j2k.png -d 9,9,12,12 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_9.j2k.png -t 0
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_9_1.j2k.png -t 5
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_9_2.j2k.png -t 9
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_9_3.j2k.png -t 15
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_10.j2k.png -t 0 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_10_1.j2k.png -t 5 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_10_2.j2k.png -t 9 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_10_3.j2k.png -t 15 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_11.j2k.png -r 4
# # prec=4; nb_c=3 ; signd=yes
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04.j2k.png -d 0,0,256,256
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_1.j2k.png -d 128,0,256,128
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_2.j2k.png -d 50,10,120,200
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_3.j2k.png -d 10,150,190,210
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_4.j2k.png -d 100,80,200,150
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_5.j2k.png -d 150,20,200,50
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6.j2k.png -d 0,0,256,256 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6_1.j2k.png -d 128,0,256,128 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6_2.j2k.png -d 50,10,120,200 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6_3.j2k.png -d 10,150,190,210 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6_4.j2k.png -d 100,80,200,150 -r 2
# j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04_6_5.j2k.png -d 150,20,200,50 -r 2
# # prec=8; nb_c=1 ; non standard origin (image offset and tile offset); sample sep: 2x1
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01.j2k.png -d 5,128,127,226
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_1.j2k.png -d 5,128,122,99
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_2.j2k.png -d 50,10,120,200
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_3.j2k.png -d 10,150,190,210
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_4.j2k.png -d 100,80,200,150
# #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_5.j2k.png -d 150,20,200,50
# < NOT IMPLEMENTED
# issue 322 limited tif support
# GRAYSCALE
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-1.tif -p 1S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-2.tif -p 2S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-4.tif -p 4S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-6.tif -p 6S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-8.tif -p 8S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-10.tif -p 10S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-12.tif -p 12S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-14.tif -p 14S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-16.tif -p 16S
# GRAYSCALE ALPHA
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-1.tif -p 1S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-2.tif -p 2S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-4.tif -p 4S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-6.tif -p 6S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-8.tif -p 8S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-10.tif -p 10S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-12.tif -p 12S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-14.tif -p 14S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-16.tif -p 16S
# RGB
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-1.tif -p 1S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-2.tif -p 2S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-4.tif -p 4S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-6.tif -p 6S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-8.tif -p 8S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-10.tif -p 10S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-12.tif -p 12S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-14.tif -p 14S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-16.tif -p 16S
# RGBA
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-1.tif -p 1S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-2.tif -p 2S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-4.tif -p 4S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-6.tif -p 6S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-8.tif -p 8S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-10.tif -p 10S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-12.tif -p 12S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-14.tif -p 14S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-16.tif -p 16S
#issue 235 CMAP outside jp2h box. CMAP is buggy
j2k_to_image -i @INPUT_NR_PATH@/issue235.jp2 -o @TEMP_PATH@/issue235.jp2.pgx
# issue 264, add checks for png
# GRAYSCALE
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-1.png -p 1S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-2.png -p 2S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-4.png -p 4S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-6.png -p 6S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-8.png -p 8S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-10.png -p 10S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-12.png -p 12S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-14.png -p 14S
j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_png-16.png -p 16S
# GRAYSCALE ALPHA
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-1.png -p 1S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-2.png -p 2S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-4.png -p 4S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-6.png -p 6S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-8.png -p 8S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-10.png -p 10S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-12.png -p 12S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-14.png -p 14S
j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_png-16.png -p 16S
# RGB
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-1.png -p 1S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-2.png -p 2S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-4.png -p 4S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-6.png -p 6S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-8.png -p 8S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-10.png -p 10S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-12.png -p 12S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-14.png -p 14S
j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_png-16.png -p 16S
# RGBA
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-1.png -p 1S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-2.png -p 2S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-4.png -p 4S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-6.png -p 6S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-8.png -p 8S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-10.png -p 10S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-12.png -p 12S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-14.png -p 14S
j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_png-16.png -p 16S
# issue 388
!j2k_to_image -i @INPUT_NR_PATH@/v4dwt_interleave_h.gsr105.j2k -o @TEMP_PATH@/v4dwt_interleave_h.gsr105.j2k.pgx
j2k_to_image -i @INPUT_NR_PATH@/dwt_interleave_h.gsr105.jp2 -o @TEMP_PATH@/dwt_interleave_h.gsr105.jp2.pgx
# PR 559 : CMYK tif output
j2k_to_image -i @INPUT_NR_PATH@/issue205.jp2 -o @TEMP_PATH@/issue205-tif.jp2.tif
# issue 236: esYCC colorspace
j2k_to_image -i @INPUT_NR_PATH@/issue236-ESYCC-CDEF.jp2 -o @TEMP_PATH@/issue236-ESYCC-CDEF.jp2.pgx
# issue 326 + PR 559: CIELab colorspace
j2k_to_image -i @INPUT_NR_PATH@/issue559-eci-090-CIELab.jp2 -o @TEMP_PATH@/issue559-eci-090-CIELab.jp2.pgx
j2k_to_image -i @INPUT_NR_PATH@/issue559-eci-091-CIELab.jp2 -o @TEMP_PATH@/issue559-eci-091-CIELab.jp2.pgx

142
tests/pdf2jp2.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2014, Mathieu Malaterre <mathieu.malaterre@voxxl.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Extract all JP2 files contained within a PDF file.
*
* Technically you could simply use mutool, eg:
*
* $ mutool show -be -o obj58.jp2 Bug691816.pdf 58
*
* to extract a given JP2 file from within a PDF
* However it happens sometimes that the PDF is itself corrupted, this tools is
* a lame PDF parser which only extract stream contained in JPXDecode box
* only work on linux since I need memmem function
*/
/*
* Add support for other signatures:
*
* obj<</Subtype/Image/Length 110494/Filter/JPXDecode/BitsPerComponent 8/ColorSpace/DeviceRGB/Width 712/Height 1052>>stream
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
int main(int argc, char *argv[])
{
#define NUMJP2 32
int i, c = 0;
long offets[NUMJP2];
char buffer[512];
#define BUFLEN 4096
int cont = 1;
FILE *f;
size_t nread;
char haystack[BUFLEN];
const char needle[] = "JPXDecode";
const size_t nlen = strlen( needle );
const size_t flen = BUFLEN - nlen;
char *fpos = haystack + nlen;
const char *filename;
if( argc < 2 ) return 1;
filename = argv[1];
memset( haystack, 0, nlen );
f = fopen( filename, "rb" );
while( cont )
{
const char *ret;
size_t hlen;
nread = fread(fpos, 1, flen, f);
hlen = nlen + nread;
ret = memmem( haystack, hlen, needle, nlen);
if( ret )
{
const long cpos = ftell(f);
const ptrdiff_t diff = ret - haystack;
assert( diff >= 0 );
/*fprintf( stdout, "Found it: %lx\n", (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff);*/
offets[c++] = (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff;
}
cont = (nread == flen);
memcpy( haystack, haystack + nread, nlen );
}
assert( feof( f ) );
for( i = 0; i < c; ++i )
{
int s, len = 0;
char *r;
const int ret = fseek(f, offets[i], SEEK_SET);
assert( ret == 0 );
r = fgets(buffer, sizeof(buffer), f);
assert( r );
/*fprintf( stderr, "DEBUG: %s", r );*/
s = sscanf(r, "JPXDecode]/Length %d/Width %*d/BitsPerComponent %*d/Height %*d", &len);
if( s == 0 )
{ // try again harder
const int ret = fseek(f, offets[i] - 40, SEEK_SET); // 40 is magic number
assert( ret == 0 );
r = fgets(buffer, sizeof(buffer), f);
assert( r );
const char needle2[] = "/Length";
char * s2 = strstr(buffer, needle2);
s = sscanf(s2, "/Length %d/", &len);
}
if( s == 1 )
{
FILE *jp2;
int j;
char jp2fn[512];
sprintf( jp2fn, "%s.%d.jp2", filename, i );
jp2 = fopen( jp2fn, "wb" );
for( j = 0; j < len; ++j )
{
int v = fgetc(f);
int ret2 = fputc(v, jp2);
assert( ret2 != EOF );
}
fclose( jp2 );
#if 0
/* TODO need to check we reached endstream */
r = fgets(buffer, sizeof(buffer), f);
fprintf( stderr, "DEBUG: [%s]", r );
r = fgets(buffer, sizeof(buffer), f);
fprintf( stderr, "DEBUG: [%s]", r );
#endif
}
}
fclose(f);
return 0;
}

139
tests/ppm2rgb3.c Normal file
View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 2014, Mathieu Malaterre <mathieu.malaterre@voxxl.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Technically on UNIX, one can simply call `ppmtorgb3`, but on my system it
* did not work. So I had to write my own.
*/
#include <stdio.h> /* fprintf */
#include <string.h> /* strcmp */
#include <stdlib.h> /* malloc */
static const char magic[] = "P6";
static int readheader( FILE *ppm, int *X, int *Y, int *bpp )
{
char buffer[256];
char strbuffer[256];
char *line;
int n;
*X = *Y = *bpp = 0;
line = fgets(buffer, sizeof(buffer), ppm);
if( !line ) return 0;
n = sscanf(buffer, "%255[^\r\n]", strbuffer);
if( n != 1 ) return 0;
if( strcmp(strbuffer, magic ) != 0 ) return 0;
/* skip comments */
while( fgets(buffer, sizeof(buffer), ppm) && *buffer == '#' )
{
}
n = sscanf(buffer, "%d %d", X,Y);
if( n != 2 ) return 0;
line = fgets(buffer, sizeof(buffer), ppm);
if( !line ) return 0;
n = sscanf(buffer, "%d", bpp);
if( n != 1 ) return 0;
if( *bpp != 255 ) return 0;
return 1;
}
static int writeoutput( const char *fn, FILE *ppm, int X, int Y, int bpp )
{
FILE *outf[] = {NULL, NULL, NULL};
int i, x, y = 0;
char outfn[256];
static const char *exts[3] = {
"red",
"grn",
"blu"
};
char *image_line = NULL;
int ok = 0;
/* write single comp as PGM: P5 */
for( i = 0; i < 3; ++i )
{
#ifdef _MSC_VER
#define snprintf _snprintf /* Visual Studio */
#endif
snprintf( outfn, sizeof(outfn), "%s.%s.pgm", fn, exts[i] );
outf[i] = fopen( outfn, "wb" );
if( !outf[i] ) goto cleanup;
/* write header */
fprintf( outf[i], "P5\n" );
fprintf( outf[i], "%d %d\n", X, Y );
fprintf( outf[i], "%d\n", bpp );
}
/* write pixel data */
image_line = (char*)malloc( (size_t)X * 3 * sizeof(char) );
if( !image_line ) goto cleanup;
while( fread(image_line, sizeof(char), (size_t)X * 3, ppm) == (size_t)X * 3 )
{
for( x = 0; x < X; ++x )
for( i = 0; i < 3; ++i )
if( fputc( image_line[3*x+i], outf[i] ) == EOF ) goto cleanup;
++y;
}
if( y == Y )
ok = 1;
cleanup:
free(image_line);
for( i = 0; i < 3; ++i )
if( outf[i] ) fclose( outf[i] );
return ok;
}
int main(int argc, char *argv[])
{
const char *fn;
FILE *ppm = NULL;
int X, Y, bpp;
int ok = 0;
if( argc < 2 )
{
fprintf( stderr, "%s input.ppm\n", argv[0] );
goto cleanup;
}
fn = argv[1];
ppm = fopen( fn, "rb" );
if( !readheader( ppm, &X, &Y, &bpp ) ) goto cleanup;
if( !writeoutput(fn, ppm, X, Y, bpp ) ) goto cleanup;
ok = 1;
cleanup:
if(ppm) fclose(ppm);
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -1,9 +1,17 @@
# UNIT TESTS
# UNIT TESTS
add_executable(testempty1 testempty1.c)
add_executable(testempty2 testempty2.c)
target_link_libraries(testempty1 openjpeg)
target_link_libraries(testempty2 openjpeg)
include_directories(
${OPENJPEG_BINARY_DIR}/libopenjpeg # opj_config.h
${OPENJPEG_SOURCE_DIR}/libopenjpeg
)
add_test(NAME testempty1 COMMAND testempty1)
add_test(NAME testempty2 COMMAND testempty2)
set(unit_test
testempty0
testempty1
testempty2
)
foreach(ut ${unit_test})
add_executable(${ut} ${ut}.c)
target_link_libraries(${ut} openjpeg)
add_test(NAME ${ut} COMMAND ${ut})
endforeach()

7
tests/unit/testempty0.c Normal file
View File

@@ -0,0 +1,7 @@
#include "openjpeg.h"
int main(int argc, char **argv) {
(void)argc;
(void)argv;
return 0;
}

View File

@@ -111,6 +111,15 @@ int main(int argc, char *argv[])
cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
assert( cio );
bSuccess = opj_encode(cinfo, cio, image, NULL);
if( !bSuccess )
{
opj_cio_close(cio);
opj_destroy_compress(cinfo);
opj_image_destroy(image);
return 0;
}
assert( bSuccess );
codestream_length = (size_t)cio_tell(cio);

View File

@@ -115,6 +115,15 @@ int main(int argc, char *argv[])
cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
assert( cio );
bSuccess = opj_encode(cinfo, cio, image, NULL);
if( !bSuccess )
{
opj_cio_close(cio);
opj_destroy_compress(cinfo);
opj_image_destroy(image);
return 0;
}
assert( bSuccess );
codestream_length = (size_t)cio_tell(cio);

View File

@@ -57,7 +57,10 @@ IF(BUILD_THIRDPARTY)
message(STATUS "We will build TIFF lib from thirdparty")
ADD_SUBDIRECTORY(libtiff)
SET(TIFF_LIBNAME tiff PARENT_SCOPE)
SET(TIFF_INCLUDE_DIRNAME ${OPENJPEG_SOURCE_DIR}/thirdparty/libtiff PARENT_SCOPE)
SET(TIFF_INCLUDE_DIRNAME
${OPENJPEG_SOURCE_DIR}/thirdparty/libtiff
${OPENJPEG_BINARY_DIR}/thirdparty/libtiff
PARENT_SCOPE)
SET(HAVE_TIFF_H 1 PARENT_SCOPE)
SET(HAVE_LIBTIFF 1 PARENT_SCOPE)
ELSE (BUILD_THIRDPARTY)

View File

@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2010 Jean-loup Gailly.
* Copyright (C) 1995-2013 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -15,11 +15,13 @@
* this permanently in zconf.h using "./configure --zprefix".
*/
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
# define Z_PREFIX_SET
/* all linked symbols */
# define _dist_code z__dist_code
# define _length_code z__length_code
# define _tr_align z__tr_align
# define _tr_flush_bits z__tr_flush_bits
# define _tr_flush_block z__tr_flush_block
# define _tr_init z__tr_init
# define _tr_stored_block z__tr_stored_block
@@ -27,9 +29,11 @@
# define adler32 z_adler32
# define adler32_combine z_adler32_combine
# define adler32_combine64 z_adler32_combine64
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# ifndef Z_SOLO
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# endif
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
@@ -40,44 +44,53 @@
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePending z_deflatePending
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateResetKeep z_deflateResetKeep
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# ifndef Z_SOLO
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgetc_ z_gzgetc_
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# ifdef _WIN32
# define gzopen_w z_gzopen_w
# endif
# define gzprintf z_gzprintf
# define gzvprintf z_gzvprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# endif
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
@@ -92,16 +105,22 @@
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateSetDictionary z_inflateSetDictionary
# define inflateGetDictionary z_inflateGetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflateResetKeep z_inflateResetKeep
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# define uncompress z_uncompress
# ifndef Z_SOLO
# define uncompress z_uncompress
# endif
# define zError z_zError
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# ifndef Z_SOLO
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# endif
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
@@ -111,7 +130,9 @@
# define alloc_func z_alloc_func
# define charf z_charf
# define free_func z_free_func
# define gzFile z_gzFile
# ifndef Z_SOLO
# define gzFile z_gzFile
# endif
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
@@ -197,6 +218,12 @@
# endif
#endif
#if defined(ZLIB_CONST) && !defined(z_const)
# define z_const const
#else
# define z_const
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
@@ -243,6 +270,14 @@
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
@@ -356,12 +391,47 @@ typedef uLong FAR uLongf;
typedef Byte *voidp;
#endif
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (UINT_MAX == 0xffffffffUL)
# define Z_U4 unsigned
# elif (ULONG_MAX == 0xffffffffUL)
# define Z_U4 unsigned long
# elif (USHRT_MAX == 0xffffffffUL)
# define Z_U4 unsigned short
# endif
#endif
#ifdef Z_U4
typedef Z_U4 z_crc_t;
#else
typedef unsigned long z_crc_t;
#endif
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_STDARG_H
#endif
#ifdef STDC
# include <sys/types.h> /* for off_t */
# ifndef Z_SOLO
# include <sys/types.h> /* for off_t */
# endif
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
# include <stdarg.h> /* for va_list */
# endif
#endif
#ifdef _WIN32
# ifndef Z_SOLO
# include <stddef.h> /* for wchar_t */
# endif
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
@@ -370,21 +440,38 @@ typedef uLong FAR uLongf;
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
# define Z_HAVE_UNISTD_H
#endif
#ifndef Z_SOLO
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
# endif
#endif
#ifndef SEEK_SET
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
# define Z_LFS64
#endif
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
# define Z_LARGE64
#endif
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
# define Z_WANT64
#endif
#if !defined(SEEK_SET) && !defined(Z_SOLO)
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
@@ -394,18 +481,14 @@ typedef uLong FAR uLongf;
# define z_off_t long
#endif
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
#if !defined(_WIN32) && defined(Z_LARGE64)
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
# define z_off64_t __int64
# else
# define z_off64_t z_off_t
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */

View File

@@ -1,430 +0,0 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/* #undef Z_PREFIX */
/* #undef Z_HAVE_UNISTD_H */
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
/* all linked symbols */
# define _dist_code z__dist_code
# define _length_code z__length_code
# define _tr_align z__tr_align
# define _tr_flush_block z__tr_flush_block
# define _tr_init z__tr_init
# define _tr_stored_block z__tr_stored_block
# define _tr_tally z__tr_tally
# define adler32 z_adler32
# define adler32_combine z_adler32_combine
# define adler32_combine64 z_adler32_combine64
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit_ z_inflateBackInit_
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetHeader z_inflateGetHeader
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# define uncompress z_uncompress
# define zError z_zError
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
/* all zlib typedefs in zlib.h and zconf.h */
# define Byte z_Byte
# define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf
# define free_func z_free_func
# define gzFile z_gzFile
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf
# define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef STDC
# include <sys/types.h> /* for off_t */
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# ifndef z_off_t
# define z_off_t off_t
# endif
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
#pragma map(deflateInit_,"DEIN")
#pragma map(deflateInit2_,"DEIN2")
#pragma map(deflateEnd,"DEEND")
#pragma map(deflateBound,"DEBND")
#pragma map(inflateInit_,"ININ")
#pragma map(inflateInit2_,"ININ2")
#pragma map(inflateEnd,"INEND")
#pragma map(inflateSync,"INSY")
#pragma map(inflateSetDictionary,"INSEDI")
#pragma map(compressBound,"CMBND")
#pragma map(inflate_table,"INTABL")
#pragma map(inflate_fast,"INFA")
#pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

View File

@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.5, April 19th, 2010
version 1.2.8, April 28th, 2013
Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -24,8 +24,8 @@
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
*/
#ifndef ZLIB_H
@@ -37,11 +37,11 @@
extern "C" {
#endif
#define ZLIB_VERSION "1.2.5"
#define ZLIB_VERNUM 0x1250
#define ZLIB_VERSION "1.2.8"
#define ZLIB_VERNUM 0x1280
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 5
#define ZLIB_VER_REVISION 8
#define ZLIB_VER_SUBREVISION 0
/*
@@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address));
struct internal_state;
typedef struct z_stream_s {
Bytef *next_in; /* next input byte */
z_const Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
uLong total_in; /* total number of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
uLong total_out; /* total number of bytes output so far */
char *msg; /* last error message, NULL if no error */
z_const char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
@@ -327,8 +327,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
Z_FINISH can be used immediately after deflateInit if all the compression
is to be done in a single step. In this case, avail_out must be at least the
value returned by deflateBound (see below). If deflate does not return
Z_STREAM_END, then it must be called again as described above.
value returned by deflateBound (see below). Then deflate is guaranteed to
return Z_STREAM_END. If not enough output space is provided, deflate will
not return Z_STREAM_END, and it must be called again as described above.
deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes).
@@ -451,23 +452,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
error. However if all decompression is to be performed in a single step (a
single call of inflate), the parameter flush should be set to Z_FINISH. In
this case all pending input is processed and all pending output is flushed;
avail_out must be large enough to hold all the uncompressed data. (The size
of the uncompressed data may have been saved by the compressor for this
purpose.) The next operation on this stream must be inflateEnd to deallocate
the decompression state. The use of Z_FINISH is never required, but can be
used to inform inflate that a faster approach may be used for the single
inflate() call.
avail_out must be large enough to hold all of the uncompressed data for the
operation to complete. (The size of the uncompressed data may have been
saved by the compressor for this purpose.) The use of Z_FINISH is not
required to perform an inflation in one step. However it may be used to
inform inflate that a faster approach can be used for the single inflate()
call. Z_FINISH also informs inflate to not maintain a sliding window if the
stream completes, which reduces inflate's memory footprint. If the stream
does not complete, either because not all of the stream is provided or not
enough output space is provided, then a sliding window will be allocated and
inflate() can be called again to continue the operation as if Z_NO_FLUSH had
been used.
In this implementation, inflate() always flushes as much output as
possible to the output buffer, and always uses the faster approach on the
first call. So the only effect of the flush parameter in this implementation
is on the return value of inflate(), as noted below, or when it returns early
because Z_BLOCK or Z_TREES is used.
first call. So the effects of the flush parameter in this implementation are
on the return value of inflate() as noted below, when inflate() returns early
when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
memory for a sliding window when Z_FINISH is used.
If a preset dictionary is needed after this call (see inflateSetDictionary
below), inflate sets strm->adler to the adler32 checksum of the dictionary
below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
strm->adler to the adler32 checksum of all output produced so far (that is,
strm->adler to the Adler-32 checksum of all output produced so far (that is,
total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
below. At the end of the stream, inflate() checks that its computed adler32
checksum is equal to that saved by the compressor and returns Z_STREAM_END
@@ -478,7 +485,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
initializing with inflateInit2(). Any information contained in the gzip
header is not retained, so applications that need that information should
instead use raw inflate, see inflateInit2() below, or inflateBack() and
perform their own processing of the gzip header and trailer.
perform their own processing of the gzip header and trailer. When processing
gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
producted so far. The CRC-32 is checked against the gzip trailer.
inflate() returns Z_OK if some progress has been made (more input processed
or more output produced), Z_STREAM_END if the end of the compressed data has
@@ -580,10 +589,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
uInt dictLength));
/*
Initializes the compression dictionary from the given byte sequence
without producing any compressed output. This function must be called
immediately after deflateInit, deflateInit2 or deflateReset, before any call
of deflate. The compressor and decompressor must use exactly the same
dictionary (see inflateSetDictionary).
without producing any compressed output. When using the zlib format, this
function must be called immediately after deflateInit, deflateInit2 or
deflateReset, and before any call of deflate. When doing raw deflate, this
function must be called either before any call of deflate, or immediately
after the completion of a deflate block, i.e. after all input has been
consumed and all output has been delivered when using any of the flush
options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
compressor and decompressor must use exactly the same dictionary (see
inflateSetDictionary).
The dictionary should consist of strings (byte sequences) that are likely
to be encountered later in the data to be compressed, with the most commonly
@@ -610,8 +624,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent (for example if deflate has already been called for this stream
or if the compression method is bsort). deflateSetDictionary does not
perform any compression: this will be done by deflate().
or if not at a block boundary for raw deflate). deflateSetDictionary does
not perform any compression: this will be done by deflate().
*/
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
@@ -688,9 +702,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
deflation of sourceLen bytes. It must be called after deflateInit() or
deflateInit2(), and after deflateSetHeader(), if used. This would be used
to allocate an output buffer for deflation in a single pass, and so would be
called before deflate().
called before deflate(). If that first deflate() call is provided the
sourceLen input bytes, an output buffer allocated to the size returned by
deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
to return Z_STREAM_END. Note that it is possible for the compressed size to
be larger than the value returned by deflateBound() if flush options other
than Z_FINISH or Z_NO_FLUSH are used.
*/
ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
unsigned *pending,
int *bits));
/*
deflatePending() returns the number of bytes and bits of output that have
been generated, but not yet provided in the available output. The bytes not
provided would be due to the available output space having being consumed.
The number of bits of output not provided are between 0 and 7, where they
await more bits to join them in order to fill out a full byte. If pending
or bits are Z_NULL, then those values are not set.
deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
*/
ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
int bits,
int value));
@@ -703,8 +737,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
than or equal to 16, and that many of the least significant bits of value
will be inserted in the output.
deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
source stream state was inconsistent.
*/
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
@@ -790,10 +825,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
can be determined from the adler32 value returned by that call of inflate.
The compressor and decompressor must use exactly the same dictionary (see
deflateSetDictionary). For raw inflate, this function can be called
immediately after inflateInit2() or inflateReset() and before any call of
inflate() to set the dictionary. The application must insure that the
dictionary that was used for compression is provided.
deflateSetDictionary). For raw inflate, this function can be called at any
time to set the dictionary. If the provided dictionary is smaller than the
window and there is already data in the window, then the provided dictionary
will amend what's there. The application must insure that the dictionary
that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
@@ -803,19 +839,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
inflate().
*/
ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
Bytef *dictionary,
uInt *dictLength));
/*
Returns the sliding dictionary being maintained by inflate. dictLength is
set to the number of bytes in the dictionary, and that many bytes are copied
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If inflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
Similary, if dictLength is Z_NULL, then it is not set.
inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
stream state is inconsistent.
*/
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
/*
Skips invalid compressed data until a full flush point (see above the
description of deflate with Z_FULL_FLUSH) can be found, or until all
Skips invalid compressed data until a possible full flush point (see above
for the description of deflate with Z_FULL_FLUSH) can be found, or until all
available input is skipped. No output is provided.
inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
if no more input was provided, Z_DATA_ERROR if no flush point has been
found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the
success case, the application may save the current current value of total_in
which indicates where valid compressed data was found. In the error case,
the application may repeatedly call inflateSync, providing more input each
time, until success or end of the input data.
inflateSync searches for a 00 00 FF FF pattern in the compressed data.
All full flush points have this pattern, but not all occurrences of this
pattern are full flush points.
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
In the success case, the application may save the current current value of
total_in which indicates where valid compressed data was found. In the
error case, the application may repeatedly call inflateSync, providing more
input each time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
@@ -962,12 +1017,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
See inflateBack() for the usage of these routines.
inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
the parameters are invalid, Z_MEM_ERROR if the internal state could not be
allocated, or Z_VERSION_ERROR if the version of the library does not match
the version of the header file.
*/
typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
typedef unsigned (*in_func) OF((void FAR *,
z_const unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
@@ -975,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
out_func out, void FAR *out_desc));
/*
inflateBack() does a raw inflate with a single call using a call-back
interface for input and output. This is more efficient than inflate() for
file i/o applications in that it avoids copying between the output and the
sliding window by simply making the window itself the output buffer. This
function trusts the application to not change the output buffer passed by
the output function, at least until inflateBack() returns.
interface for input and output. This is potentially more efficient than
inflate() for file i/o applications, in that it avoids copying between the
output and the sliding window by simply making the window itself the output
buffer. inflate() can be faster on modern CPUs when used with large
buffers. inflateBack() trusts the application to not change the output
buffer passed by the output function, at least until inflateBack() returns.
inflateBackInit() must be called first to allocate the internal state
and to initialize the state with the user-provided window buffer.
@@ -1088,6 +1145,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
27-31: 0 (reserved)
*/
#ifndef Z_SOLO
/* utility functions */
@@ -1149,10 +1207,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
the case where there is not enough room, uncompress() will fill the output
buffer with the uncompressed data up to that point.
*/
/* gzip file access functions */
/*
@@ -1162,7 +1221,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
wrapper, documented in RFC 1952, wrapped around a deflate stream.
*/
typedef voidp gzFile; /* opaque gzip file descriptor */
typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
@@ -1172,13 +1231,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
for fixed code compression as in "wb9F". (See the description of
deflateInit2 for more information about the strategy parameter.) Also "a"
can be used instead of "w" to request that the gzip stream that will be
written be appended to the file. "+" will result in an error, since reading
and writing to the same gzip file is not supported.
deflateInit2 for more information about the strategy parameter.) 'T' will
request transparent writing or appending with no compression and not using
the gzip format.
"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
reading and writing to the same gzip file is not supported. The addition of
"x" when writing will create the file exclusively, which fails if the file
already exists. On systems that support it, the addition of "e" when
reading or writing will set the flag to close the file on an execve() call.
These functions, as well as gzip, will read and decode a sequence of gzip
streams in a file. The append function of gzopen() can be used to create
such a file. (Also see gzflush() for another way to do this.) When
appending, gzopen does not test whether the file begins with a gzip stream,
nor does it look for the end of the gzip streams to begin appending. gzopen
will simply append a gzip stream to the existing file.
gzopen can be used to read a file which is not in gzip format; in this
case gzread will directly read from the file without decompression.
case gzread will directly read from the file without decompression. When
reading, this will be detected automatically by looking for the magic two-
byte gzip header.
gzopen returns NULL if the file could not be opened, if there was
insufficient memory to allocate the gzFile state, or if an invalid mode was
@@ -1197,7 +1271,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
mode);. The duplicated descriptor should be saved to avoid a leak, since
gzdopen does not close fd if it fails.
gzdopen does not close fd if it fails. If you are using fileno() to get the
file descriptor from a FILE *, then you will have to use dup() to avoid
double-close()ing the file descriptor. Both gzclose() and fclose() will
close the associated file descriptor, so they need to have different file
descriptors.
gzdopen returns NULL if there was insufficient memory to allocate the
gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
@@ -1235,14 +1313,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
Reads the given number of uncompressed bytes from the compressed file. If
the input file was not in gzip format, gzread copies the given number of
bytes into the buffer.
the input file is not in gzip format, gzread copies the given number of
bytes into the buffer directly from the file.
After reaching the end of a gzip stream in the input, gzread will continue
to read, looking for another gzip stream, or failing that, reading the rest
of the input file directly without decompression. The entire input file
will be read if gzread is called until it returns less than the requested
len.
to read, looking for another gzip stream. Any number of gzip streams may be
concatenated in the input file, and will all be decompressed by gzread().
If something other than a gzip stream is encountered after a gzip stream,
that remaining trailing garbage is ignored (and no error is returned).
gzread can be used to read a gzip file that is being concurrently written.
Upon reaching the end of the input, gzread will return with the available
data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
gzclearerr can be used to clear the end of file indicator in order to permit
gzread to be tried again. Z_OK indicates that a gzip stream was completed
on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
middle of a gzip stream. Note that gzread does not return -1 in the event
of an incomplete gzip stream. This error is deferred until gzclose(), which
will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
stream. Alternatively, gzerror can be used before gzclose to detect this
case.
gzread returns the number of uncompressed bytes actually read, less than
len for end of file, or -1 for error.
@@ -1256,7 +1346,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
error.
*/
ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
/*
Converts, formats, and writes the arguments to the compressed file under
control of the format string, as in fprintf. gzprintf returns the number of
@@ -1301,7 +1391,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
Reads one byte from the compressed file. gzgetc returns this byte or -1
in case of end of file or error.
in case of end of file or error. This is implemented as a macro for speed.
As such, it does not do all of the checking the other functions do. I.e.
it does not check to see if file is NULL, nor whether the structure file
points to has been clobbered or not.
*/
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
@@ -1397,9 +1490,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
Returns true (1) if file is being copied directly while reading, or false
(0) if file is a gzip stream being decompressed. This state can change from
false to true while reading the input file if the end of a gzip stream is
reached, but is followed by data that is not another gzip stream.
(0) if file is a gzip stream being decompressed.
If the input file is empty, gzdirect() will return true, since the input
does not contain a gzip stream.
@@ -1408,6 +1499,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
cause buffers to be allocated to allow reading the file to determine if it
is a gzip file. Therefore if gzbuffer() is used, it should be called before
gzdirect().
When writing, gzdirect() returns true (1) if transparent writing was
requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
gzdirect() is not needed when writing. Transparent writing must be
explicitly requested, so the application already knows the answer. When
linking statically, using gzdirect() will include all of the zlib code for
gzip file reading and decompression, which may not be desired.)
*/
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
@@ -1419,7 +1517,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file));
must not be called more than once on the same allocation.
gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
file operation error, or Z_OK on success.
file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
last read ended in the middle of a gzip stream, or Z_OK on success.
*/
ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
@@ -1457,6 +1556,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
file that is being written concurrently.
*/
#endif /* !Z_SOLO */
/* checksum functions */
@@ -1492,16 +1592,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
that the z_off_t type (like off_t) is a signed integer. If len2 is
negative, the result has no meaning or utility.
*/
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running CRC-32 with the bytes buf[0..len-1] and return the
updated CRC-32. If buf is Z_NULL, this function returns the required
initial value for the for the crc. Pre- and post-conditioning (one's
complement) is performed within this function so it shouldn't be done by the
application.
initial value for the crc. Pre- and post-conditioning (one's complement) is
performed within this function so it shouldn't be done by the application.
Usage example:
@@ -1544,17 +1645,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
const char *version,
int stream_size));
#define deflateInit(strm, level) \
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
#define inflateInit(strm) \
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
(strategy), ZLIB_VERSION, sizeof(z_stream))
(strategy), ZLIB_VERSION, (int)sizeof(z_stream))
#define inflateInit2(strm, windowBits) \
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
(int)sizeof(z_stream))
#define inflateBackInit(strm, windowBits, window) \
inflateBackInit_((strm), (windowBits), (window), \
ZLIB_VERSION, sizeof(z_stream))
ZLIB_VERSION, (int)sizeof(z_stream))
#ifndef Z_SOLO
/* gzgetc() macro and its supporting function and exposed data structure. Note
* that the real internal state is much larger than the exposed structure.
* This abbreviated structure exposes just enough for the gzgetc() macro. The
* user should not mess with these exposed elements, since their names or
* behavior could change in the future, perhaps even capriciously. They can
* only be used by the gzgetc() macro. You have been warned.
*/
struct gzFile_s {
unsigned have;
unsigned char *next;
z_off64_t pos;
};
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
#ifdef Z_PREFIX_SET
# undef z_gzgetc
# define z_gzgetc(g) \
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
#else
# define gzgetc(g) \
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
#endif
/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
* change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
@@ -1562,7 +1688,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
* functions are changed to 64 bits) -- in case these are set on systems
* without large file support, _LFS64_LARGEFILE must also be true
*/
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
#ifdef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
@@ -1571,14 +1697,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
#endif
#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
# define gzopen gzopen64
# define gzseek gzseek64
# define gztell gztell64
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
# ifdef _LARGEFILE64_SOURCE
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
# ifdef Z_PREFIX_SET
# define z_gzopen z_gzopen64
# define z_gzseek z_gzseek64
# define z_gztell z_gztell64
# define z_gzoffset z_gzoffset64
# define z_adler32_combine z_adler32_combine64
# define z_crc32_combine z_crc32_combine64
# else
# define gzopen gzopen64
# define gzseek gzseek64
# define gztell gztell64
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
# endif
# ifndef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
@@ -1595,6 +1730,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
#endif
#else /* Z_SOLO */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
#endif /* !Z_SOLO */
/* hack for buggy compilers */
#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
struct internal_state {int dummy;};
@@ -1603,8 +1745,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
/* undocumented functions */
ZEXTERN const char * ZEXPORT zError OF((int));
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
#if defined(_WIN32) && !defined(Z_SOLO)
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
const char *mode));
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
const char *format,
va_list va));
# endif
#endif
#ifdef __cplusplus
}

View File

@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -23,7 +23,7 @@
//
//---------------------------------------------------------------------------------
//
// Version 2.1
// Version 2.6
//
#ifndef _lcms2_H
@@ -40,9 +40,6 @@
// Uncomment this if your compiler doesn't work with fast floor function
// #define CMS_DONT_USE_FAST_FLOOR 1
// Uncomment this line if your system does not support multithreading
#define CMS_DONT_USE_PTHREADS 1
// Uncomment this line if you want lcms to use the black point tag in profile,
// if commented, lcms will compute the black point by its own.
// It is safer to leave it commented out
@@ -55,6 +52,12 @@
// require "KEYWORD" on undefined identifiers, keep it comented out unless needed
// #define CMS_STRICT_CGATS 1
// Uncomment to get rid of the tables for "half" float support
// #define CMS_NO_HALF_SUPPORT 1
// Uncomment to get rid of pthreads/windows dependency
// #define CMS_NO_PTHREADS 1
// ********** End of configuration toggles ******************************
// Needed for streams
@@ -72,7 +75,7 @@ extern "C" {
#endif
// Version/release
#define LCMS_VERSION 2010
#define LCMS_VERSION 2060
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -81,6 +84,10 @@ extern "C" {
typedef unsigned char cmsUInt8Number; // That is guaranteed by the C99 spec
typedef signed char cmsInt8Number; // That is guaranteed by the C99 spec
#if CHAR_BIT != 8
# error "Unable to find 8 bit type, unsupported compiler"
#endif
// IEEE float storage numbers
typedef float cmsFloat32Number;
typedef double cmsFloat64Number;
@@ -169,26 +176,42 @@ typedef int cmsBool;
// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here.
// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar
#if defined(__sgi__) || defined(__sgi) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
#endif
#if defined(__s390__) || defined(__s390x__)
# define CMS_USE_BIG_ENDIAN 1
#endif
# ifdef TARGET_CPU_PPC
# if TARGET_CPU_PPC
# define CMS_USE_BIG_ENDIAN 1
# endif
# endif
#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC)
# define CMS_USE_BIG_ENDIAN 1
# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
# if __BYTE_ORDER == __LITTLE_ENDIAN
// // Don't use big endian for PowerPC little endian mode
# undef CMS_USE_BIG_ENDIAN
# endif
# endif
#endif
// WORDS_BIGENDIAN takes precedence
#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
# define CMS_USE_BIG_ENDIAN 1
#endif
#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
#endif
#if defined(__ppc__) || defined(__s390__) || defined(__s390x__)
# define CMS_USE_BIG_ENDIAN 1
#endif
#if TARGET_CPU_PPC
# define CMS_USE_BIG_ENDIAN 1
#endif
#ifdef macintosh
# ifdef __BIG_ENDIAN__
# define CMS_USE_BIG_ENDIAN 1
# endif
# ifdef __LITTLE_ENDIAN__
# undef CMS_USE_BIG_ENDIAN
# endif
#endif
// Calling convention -- this is hardly platform and compiler dependent
@@ -214,6 +237,14 @@ typedef int cmsBool;
# define CMSAPI
#endif
#ifdef HasTHREADS
# if HasTHREADS == 1
# undef CMS_NO_PTHREADS
# else
# define CMS_NO_PTHREADS 1
# endif
#endif
// Some common definitions
#define cmsMAX_PATH 256
@@ -247,6 +278,7 @@ typedef enum {
cmsSigCrdInfoType = 0x63726469, // 'crdi'
cmsSigCurveType = 0x63757276, // 'curv'
cmsSigDataType = 0x64617461, // 'data'
cmsSigDictType = 0x64696374, // 'dict'
cmsSigDateTimeType = 0x6474696D, // 'dtim'
cmsSigDeviceSettingsType = 0x64657673, // 'devs'
cmsSigLut16Type = 0x6d667432, // 'mft2'
@@ -273,9 +305,10 @@ typedef enum {
cmsSigUInt32ArrayType = 0x75693332, // 'ui32'
cmsSigUInt64ArrayType = 0x75693634, // 'ui64'
cmsSigUInt8ArrayType = 0x75693038, // 'ui08'
cmsSigVcgtType = 0x76636774, // 'vcgt'
cmsSigViewingConditionsType = 0x76696577, // 'view'
cmsSigXYZType = 0x58595A20, // 'XYZ '
cmsSigVcgtType = 0x76636774 // 'vcgt'
cmsSigXYZType = 0x58595A20 // 'XYZ '
} cmsTagTypeSignature;
@@ -330,6 +363,7 @@ typedef enum {
cmsSigPreview1Tag = 0x70726531, // 'pre1'
cmsSigPreview2Tag = 0x70726532, // 'pre2'
cmsSigProfileDescriptionTag = 0x64657363, // 'desc'
cmsSigProfileDescriptionMLTag = 0x6473636d, // 'dscm'
cmsSigProfileSequenceDescTag = 0x70736571, // 'pseq'
cmsSigProfileSequenceIdTag = 0x70736964, // 'psid'
cmsSigPs2CRD0Tag = 0x70736430, // 'psd0'
@@ -348,7 +382,8 @@ typedef enum {
cmsSigUcrBgTag = 0x62666420, // 'bfd '
cmsSigViewingCondDescTag = 0x76756564, // 'vued'
cmsSigViewingConditionsTag = 0x76696577, // 'view'
cmsSigVcgtTag = 0x76636774 // 'vcgt'
cmsSigVcgtTag = 0x76636774, // 'vcgt'
cmsSigMetaTag = 0x6D657461 // 'meta'
} cmsTagSignature;
@@ -407,12 +442,12 @@ typedef enum {
cmsSigMCH7Data = 0x4D434837, // 'MCH7'
cmsSigMCH8Data = 0x4D434838, // 'MCH8'
cmsSigMCH9Data = 0x4D434839, // 'MCH9'
cmsSigMCHAData = 0x4D43483A, // 'MCHA'
cmsSigMCHBData = 0x4D43483B, // 'MCHB'
cmsSigMCHCData = 0x4D43483C, // 'MCHC'
cmsSigMCHDData = 0x4D43483D, // 'MCHD'
cmsSigMCHEData = 0x4D43483E, // 'MCHE'
cmsSigMCHFData = 0x4D43483F, // 'MCHF'
cmsSigMCHAData = 0x4D434841, // 'MCHA'
cmsSigMCHBData = 0x4D434842, // 'MCHB'
cmsSigMCHCData = 0x4D434843, // 'MCHC'
cmsSigMCHDData = 0x4D434844, // 'MCHD'
cmsSigMCHEData = 0x4D434845, // 'MCHE'
cmsSigMCHFData = 0x4D434846, // 'MCHF'
cmsSigNamedData = 0x6e6d636c, // 'nmcl'
cmsSig1colorData = 0x31434C52, // '1CLR'
cmsSig2colorData = 0x32434C52, // '2CLR'
@@ -483,7 +518,13 @@ typedef enum {
cmsSigLabV4toV2 = 0x34203220, // '4 2 '
// Identities
cmsSigIdentityElemType = 0x69646E20 // 'idn '
cmsSigIdentityElemType = 0x69646E20, // 'idn '
// Float to floatPCS
cmsSigLab2FloatPCS = 0x64326C20, // 'd2l '
cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d '
cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x '
cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d '
} cmsStageSignature;
@@ -597,7 +638,6 @@ typedef struct {
// Little CMS specific typedefs
typedef void* cmsContext; // Context identifier for multithreaded environments
typedef void* cmsHANDLE ; // Generic handle
typedef void* cmsHPROFILE; // Opaque typedefs to hide internals
typedef void* cmsHTRANSFORM;
@@ -606,7 +646,9 @@ typedef void* cmsHTRANSFORM;
// Format of pixel is defined by one cmsUInt32Number, using bit fields as follows
//
// A O TTTTT U Y F P X S EEE CCCC BBB
// 2 1 0
// 3 2 10987 6 5 4 3 2 1 098 7654 321
// A O TTTTT U Y F P X S EEE CCCC BBB
//
// A: Floating point -- With this flag we can differentiate 16 bits as float and as int
// O: Optimized -- previous optimization already returns the final 8-bit value
@@ -714,16 +756,19 @@ typedef void* cmsHTRANSFORM;
#define TYPE_RGBA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
#define TYPE_ARGB_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ARGB_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1))
#define TYPE_ARGB_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1))
#define TYPE_ABGR_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
#define TYPE_ABGR_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1))
#define TYPE_ABGR_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
#define TYPE_ABGR_16_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
#define TYPE_ABGR_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
#define TYPE_BGRA_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1))
#define TYPE_BGRA_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_CMY_8 (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1))
#define TYPE_CMY_8_PLANAR (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
@@ -805,8 +850,8 @@ typedef void* cmsHTRANSFORM;
#define TYPE_Lab_8 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1))
#define TYPE_LabV2_8 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1))
#define TYPE_ALab_8 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1))
#define TYPE_ALabV2_8 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1))
#define TYPE_ALab_8 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ALabV2_8 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1))
#define TYPE_Lab_16 (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_LabV2_16 (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_Yxy_16 (COLORSPACE_SH(PT_Yxy)|CHANNELS_SH(3)|BYTES_SH(2))
@@ -844,22 +889,40 @@ typedef void* cmsHTRANSFORM;
// Float formatters.
#define TYPE_XYZ_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_XYZA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_Lab_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_LabA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_GRAY_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4))
#define TYPE_RGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_RGBA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_ARGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1))
#define TYPE_BGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_BGRA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_CMYK_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4))
// Floating point formatters.
// Floating point formatters.
// NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield
#define TYPE_XYZ_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(0))
#define TYPE_Lab_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(0))
#define TYPE_GRAY_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(0))
#define TYPE_RGB_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0))
#define TYPE_BGR_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0)|DOSWAP_SH(1))
#define TYPE_CMYK_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(0))
// IEEE 754-2008 "half"
#define TYPE_GRAY_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
#define TYPE_RGB_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_RGBA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_CMYK_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
#define TYPE_RGBA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_ARGB_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1))
#define TYPE_BGR_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
#define TYPE_BGRA_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ABGR_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
#endif
// Colorspaces
@@ -944,10 +1007,25 @@ typedef struct {
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
CMSAPI long int CMSEXPORT cmsfilelength(FILE* f);
// Plug-In registering ---------------------------------------------------------------------------------------------------
// Context handling --------------------------------------------------------------------------------------------------------
// Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility
// though using the global context is not recomended. Proper context handling makes lcms more thread-safe.
typedef struct _cmsContext_struct* cmsContext;
CMSAPI cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData);
CMSAPI void CMSEXPORT cmsDeleteContext(cmsContext ContexID);
CMSAPI cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData);
CMSAPI void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID);
// Plug-In registering --------------------------------------------------------------------------------------------------
CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
CMSAPI void CMSEXPORT cmsUnregisterPlugins(void);
CMSAPI void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID);
// Error logging ----------------------------------------------------------------------------------------------------------
@@ -984,6 +1062,7 @@ typedef void (* cmsLogErrorHandlerFunction)(cmsContext ContextID, cmsUInt32Numb
// Allows user to set any specific logger
CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn);
CMSAPI void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn);
// Conversions --------------------------------------------------------------------------------------------------------------
@@ -1090,6 +1169,10 @@ CMSAPI cmsBool CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve*
CMSAPI cmsInt32Number CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t);
CMSAPI cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision);
// Tone curve tabular estimation
CMSAPI cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t);
CMSAPI const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurve* t);
// Implements pipelines of multi-processing elements -------------------------------------------------------------
@@ -1102,6 +1185,7 @@ CMSAPI cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUIn
CMSAPI void CMSEXPORT cmsPipelineFree(cmsPipeline* lut);
CMSAPI cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* Orig);
CMSAPI cmsContext CMSEXPORT cmsGetPipelineContextID(const cmsPipeline* lut);
CMSAPI cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut);
CMSAPI cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut);
@@ -1118,7 +1202,7 @@ CMSAPI cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lu
// Where to place/locate the stages in the pipeline chain
typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
CMSAPI void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
CMSAPI int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
CMSAPI void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
// This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
@@ -1162,10 +1246,9 @@ typedef cmsInt32Number (* cmsSAMPLERFLOAT)(register const cmsFloat32Number In[],
#define SAMPLER_INSPECT 0x01000000
// For CLUT only
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
CMSAPI cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void* Cargo, cmsUInt32Number dwFlags);
// Slicers
CMSAPI cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
cmsSAMPLER16 Sampler, void * Cargo);
@@ -1203,6 +1286,13 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
char ObtainedLanguage[3], char ObtainedCountry[3]);
CMSAPI cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu);
CMSAPI cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
cmsUInt32Number idx,
char LanguageCode[3],
char CountryCode[3]);
// Undercolorremoval & black generation -------------------------------------------------------------------------------------
typedef struct {
@@ -1275,6 +1365,7 @@ CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform);
// Profile sequence descriptor. Some fields come from profile sequence descriptor tag, others
// come from Profile Sequence Identifier Tag
typedef struct {
cmsSignature deviceMfg;
cmsSignature deviceModel;
cmsUInt64Number attributes;
@@ -1298,6 +1389,27 @@ CMSAPI cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext
CMSAPI cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq);
CMSAPI void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq);
// Dictionaries --------------------------------------------------------------------------------------------------------
typedef struct _cmsDICTentry_struct {
struct _cmsDICTentry_struct* Next;
cmsMLU *DisplayName;
cmsMLU *DisplayValue;
wchar_t* Name;
wchar_t* Value;
} cmsDICTentry;
CMSAPI cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID);
CMSAPI void CMSEXPORT cmsDictFree(cmsHANDLE hDict);
CMSAPI cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict);
CMSAPI cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue);
CMSAPI const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict);
CMSAPI const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e);
// Access to Profile data ----------------------------------------------------------------------------------------------
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID);
@@ -1317,9 +1429,9 @@ CMSAPI cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSig
CMSAPI cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size);
// Access header data
#define cmsEmbeddedProfileFalse 0x00000000
#define cmsEmbeddedProfileTrue 0x00000001
#define cmsUseAnywhere 0x00000000
#define cmsEmbeddedProfileFalse 0x00000000
#define cmsEmbeddedProfileTrue 0x00000001
#define cmsUseAnywhere 0x00000000
#define cmsUseWithEmbeddedDataOnly 0x00000002
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile);
@@ -1331,6 +1443,7 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProf
CMSAPI void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile);
CMSAPI void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model);
CMSAPI void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags);
@@ -1411,6 +1524,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext Context
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize);
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize);
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io);
CMSAPI cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write);
CMSAPI cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
CMSAPI cmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName);
@@ -1501,6 +1615,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransfo
// Call with NULL as parameters to get the intent count
CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
// Flags
@@ -1605,18 +1720,40 @@ CMSAPI void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
void * OutputBuffer,
cmsUInt32Number Size);
CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
const void * InputBuffer,
void * OutputBuffer,
cmsUInt32Number Size,
cmsUInt32Number Stride);
CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID,
const cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID,
cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
// Adaptation state for absolute colorimetric intent
CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d);
CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d);
// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform);
// Grab the input/output formats
CMSAPI cmsUInt32Number CMSEXPORT cmsGetTransformInputFormat(cmsHTRANSFORM hTransform);
CMSAPI cmsUInt32Number CMSEXPORT cmsGetTransformOutputFormat(cmsHTRANSFORM hTransform);
// For backwards compatibility
CMSAPI cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
cmsUInt32Number InputFormat,
CMSAPI cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
cmsUInt32Number InputFormat,
cmsUInt32Number OutputFormat);
@@ -1663,12 +1800,15 @@ CMSAPI cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* c
CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* cProp, const char *Str);
CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val);
CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val);
CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer);
CMSAPI cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer);
CMSAPI const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* cProp);
CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp);
CMSAPI const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey);
CMSAPI cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames);
CMSAPI cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames);
// Datasets
CMSAPI const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col);
@@ -1698,10 +1838,13 @@ CMSAPI cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE hIT8, int n, con
CMSAPI int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames);
CMSAPI const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer);
CMSAPI int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch);
// The LABEL extension
CMSAPI int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType);
CMSAPI cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample);
// Formatter for double
CMSAPI void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter);
@@ -1717,6 +1860,7 @@ CMSAPI cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIEL
// Estimate the black point
CMSAPI cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags);
CMSAPI cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags);
// Estimate total area coverage
CMSAPI cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile);

View File

@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2011 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -131,7 +131,7 @@ struct _cms_io_handler {
// Endianess adjust functions
CMSAPI cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word);
CMSAPI cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number Value);
CMSAPI void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number QWord);
CMSAPI void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord);
// Helper IO functions
CMSAPI cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n);
@@ -147,7 +147,7 @@ CMSAPI cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUI
CMSAPI cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n);
CMSAPI cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n);
CMSAPI cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n);
CMSAPI cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number n);
CMSAPI cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n);
CMSAPI cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n);
CMSAPI cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ);
CMSAPI cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array);
@@ -181,6 +181,11 @@ CMSAPI cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v);
CMSAPI void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source);
CMSAPI void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest);
//----------------------------------------------------------------------------------------------------------
// Shared callbacks for user data
typedef void (* _cmsFreeUserDataFn)(cmsContext ContextID, void* Data);
typedef void* (* _cmsDupUserDataFn)(cmsContext ContextID, const void* Data);
//----------------------------------------------------------------------------------------------------------
@@ -196,6 +201,8 @@ CMSAPI void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeN
#define cmsPluginRenderingIntentSig 0x696E7448 // 'intH'
#define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH'
#define cmsPluginOptimizationSig 0x6F707448 // 'optH'
#define cmsPluginTransformSig 0x7A666D48 // 'xfmH'
#define cmsPluginMutexSig 0x6D747A48 // 'mtxH'
typedef struct _cmsPluginBaseStruct {
@@ -212,19 +219,28 @@ typedef struct _cmsPluginBaseStruct {
//----------------------------------------------------------------------------------------------------------
// Memory handler. Each new plug-in type replaces current behaviour
typedef void* (* _cmsMallocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
typedef void (* _cmsFreeFnPtrType)(cmsContext ContextID, void *Ptr);
typedef void* (* _cmsReallocFnPtrType)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
typedef void* (* _cmsMalloZerocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
typedef void* (* _cmsCallocFnPtrType)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
typedef void* (* _cmsDupFnPtrType)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
typedef struct {
cmsPluginBase base;
// Required
void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size);
void (* FreePtr)(cmsContext ContextID, void *Ptr);
void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
_cmsMallocFnPtrType MallocPtr;
_cmsFreeFnPtrType FreePtr;
_cmsReallocFnPtrType ReallocPtr;
// Optional
void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size);
void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
_cmsMalloZerocFnPtrType MallocZeroPtr;
_cmsCallocFnPtrType CallocPtr;
_cmsDupFnPtrType DupPtr;
} cmsPluginMemHandler;
@@ -387,7 +403,7 @@ typedef struct _cms_typehandler_struct {
void *Ptr);
// Additional parameters used by the calling thread
cmsContext ContextID;
cmsContext ContextID;
cmsUInt32Number ICCVersion;
} cmsTagTypeHandler;
@@ -486,6 +502,39 @@ typedef struct {
} cmsPluginMultiProcessElement;
// Data kept in "Element" member of cmsStage
// Curves
typedef struct {
cmsUInt32Number nCurves;
cmsToneCurve** TheCurves;
} _cmsStageToneCurvesData;
// Matrix
typedef struct {
cmsFloat64Number* Double; // floating point for the matrix
cmsFloat64Number* Offset; // The offset
} _cmsStageMatrixData;
// CLUT
typedef struct {
union { // Can have only one of both representations at same time
cmsUInt16Number* T; // Points to the table 16 bits table
cmsFloat32Number* TFloat; // Points to the cmsFloat32Number table
} Tab;
cmsInterpParams* Params;
cmsUInt32Number nEntries;
cmsBool HasFloatValues;
} _cmsStageCLutData;
//----------------------------------------------------------------------------------------------------------
// Optimization. Using this plug-in, additional optimization strategies may be implemented.
// The function should return TRUE if any optimization is done on the LUT, this terminates
@@ -496,9 +545,6 @@ typedef void (* _cmsOPTeval16Fn)(register const cmsUInt16Number In[],
register cmsUInt16Number Out[],
register const void* Data);
typedef void (* _cmsOPTfreeDataFn)(cmsContext ContextID, void* Data);
typedef void* (* _cmsOPTdupDataFn)(cmsContext ContextID, const void* Data);
typedef cmsBool (* _cmsOPToptimizeFn)(cmsPipeline** Lut,
cmsUInt32Number Intent,
@@ -512,8 +558,8 @@ typedef cmsBool (* _cmsOPToptimizeFn)(cmsPipeline** Lut,
CMSAPI void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
_cmsOPTeval16Fn Eval16,
void* PrivateData,
_cmsOPTfreeDataFn FreePrivateDataFn,
_cmsOPTdupDataFn DupPrivateDataFn);
_cmsFreeUserDataFn FreePrivateDataFn,
_cmsDupUserDataFn DupPrivateDataFn);
typedef struct {
cmsPluginBase base;
@@ -524,6 +570,62 @@ typedef struct {
} cmsPluginOptimization;
//----------------------------------------------------------------------------------------------------------
// Full xform
typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo,
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number Size,
cmsUInt32Number Stride);
typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform,
void** UserData,
_cmsFreeUserDataFn* FreePrivateDataFn,
cmsPipeline** Lut,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags);
// Retrieve user data as specified by the factory
CMSAPI void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn);
CMSAPI void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CMMcargo);
// Retrieve formatters
CMSAPI void CMSEXPORT _cmsGetTransformFormatters16 (struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput);
CMSAPI void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput);
typedef struct {
cmsPluginBase base;
// Transform entry point
_cmsTransformFactory Factory;
} cmsPluginTransform;
//----------------------------------------------------------------------------------------------------------
// Mutex
typedef void* (* _cmsCreateMutexFnPtrType)(cmsContext ContextID);
typedef void (* _cmsDestroyMutexFnPtrType)(cmsContext ContextID, void* mtx);
typedef cmsBool (* _cmsLockMutexFnPtrType)(cmsContext ContextID, void* mtx);
typedef void (* _cmsUnlockMutexFnPtrType)(cmsContext ContextID, void* mtx);
typedef struct {
cmsPluginBase base;
_cmsCreateMutexFnPtrType CreateMutexPtr;
_cmsDestroyMutexFnPtrType DestroyMutexPtr;
_cmsLockMutexFnPtrType LockMutexPtr;
_cmsUnlockMutexFnPtrType UnlockMutexPtr;
} cmsPluginMutex;
CMSAPI void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID);
CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx);
CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx);
CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx);
#ifndef CMS_USE_CPP_API
# ifdef __cplusplus

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -31,7 +31,7 @@
// ---------- Implementation --------------------------------------------
typedef struct {
cmsFloat64Number XYZ[3];
cmsFloat64Number RGB[3];
cmsFloat64Number RGBc[3];
@@ -41,55 +41,55 @@ typedef struct {
cmsFloat64Number abC[2];
cmsFloat64Number abs[2];
cmsFloat64Number abM[2];
} CAM02COLOR;
typedef struct {
CAM02COLOR adoptedWhite;
cmsFloat64Number LA, Yb;
cmsFloat64Number F, c, Nc;
cmsUInt32Number surround;
cmsFloat64Number n, Nbb, Ncb, z, FL, D;
cmsContext ContextID;
cmsContext ContextID;
} cmsCIECAM02;
static
cmsFloat64Number compute_n(cmsCIECAM02* pMod)
cmsFloat64Number compute_n(cmsCIECAM02* pMod)
{
return (pMod -> Yb / pMod -> adoptedWhite.XYZ[1]);
}
static
cmsFloat64Number compute_z(cmsCIECAM02* pMod)
cmsFloat64Number compute_z(cmsCIECAM02* pMod)
{
return (1.48 + pow(pMod -> n, 0.5));
}
static
cmsFloat64Number computeNbb(cmsCIECAM02* pMod)
cmsFloat64Number computeNbb(cmsCIECAM02* pMod)
{
return (0.725 * pow((1.0 / pMod -> n), 0.2));
}
static
cmsFloat64Number computeFL(cmsCIECAM02* pMod)
cmsFloat64Number computeFL(cmsCIECAM02* pMod)
{
cmsFloat64Number k, FL;
k = 1.0 / ((5.0 * pMod->LA) + 1.0);
FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 *
(pow((1.0 - pow(k, 4.0)), 2.0)) *
(pow((5.0 * pMod->LA), (1.0 / 3.0)));
return FL;
}
static
cmsFloat64Number computeD(cmsCIECAM02* pMod)
static
cmsFloat64Number computeD(cmsCIECAM02* pMod)
{
cmsFloat64Number D;
@@ -100,17 +100,17 @@ cmsFloat64Number computeD(cmsCIECAM02* pMod)
static
CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
{
clr.RGB[0] = (clr.XYZ[0] * 0.7328) + (clr.XYZ[1] * 0.4296) + (clr.XYZ[2] * -0.1624);
clr.RGB[1] = (clr.XYZ[0] * -0.7036) + (clr.XYZ[1] * 1.6975) + (clr.XYZ[2] * 0.0061);
clr.RGB[2] = (clr.XYZ[0] * 0.0030) + (clr.XYZ[1] * 0.0136) + (clr.XYZ[2] * 0.9834);
return clr;
}
static
CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsUInt32Number i;
@@ -120,15 +120,15 @@ CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
(1.0 - pMod->D)) * clr.RGB[i];
}
return clr;
return clr;
}
static
CAM02COLOR CAT02toHPE(CAM02COLOR clr)
CAM02COLOR CAT02toHPE(CAM02COLOR clr)
{
cmsFloat64Number M[9];
M[0] =(( 0.38971 * 1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628));
M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698));
M[2] =(( 0.38971 * 0.182745) + (0.68898 * 0.072098) + (-0.07868 * 1.015326));
@@ -138,16 +138,16 @@ CAM02COLOR CAT02toHPE(CAM02COLOR clr)
M[6] =(-0.009628);
M[7] =(-0.005698);
M[8] =( 1.015326);
clr.RGBp[0] = (clr.RGBc[0] * M[0]) + (clr.RGBc[1] * M[1]) + (clr.RGBc[2] * M[2]);
clr.RGBp[1] = (clr.RGBc[0] * M[3]) + (clr.RGBc[1] * M[4]) + (clr.RGBc[2] * M[5]);
clr.RGBp[2] = (clr.RGBc[0] * M[6]) + (clr.RGBc[1] * M[7]) + (clr.RGBc[2] * M[8]);
return clr;
}
static
CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsUInt32Number i;
cmsFloat64Number temp;
@@ -163,21 +163,21 @@ CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1;
}
}
clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
(clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
return clr;
}
static
CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsFloat64Number a, b, temp, e, t, r2d, d2r;
a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0);
b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0;
r2d = (180.0 / 3.141592654);
if (a == 0) {
if (b == 0) clr.h = 0;
@@ -194,11 +194,11 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
temp = b / a;
clr.h = (r2d * atan(temp)) + 180;
}
d2r = (3.141592654 / 180.0);
e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) *
(cos((clr.h * d2r + 2.0)) + 3.8);
e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) *
(cos((clr.h * d2r + 2.0)) + 3.8);
if (clr.h < 20.14) {
temp = ((clr.h + 122.47)/1.2) + ((20.14 - clr.h)/0.8);
clr.H = 300 + (100*((clr.h + 122.47)/1.2)) / temp;
@@ -219,15 +219,15 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
temp = ((clr.h - 237.53)/1.2) + ((360 - clr.h + 20.14)/0.8);
clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp);
}
clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A),
clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A),
(pMod->c * pMod->z));
clr.Q = (4.0 / pMod->c) * pow((clr.J / 100.0), 0.5) *
(pMod->adoptedWhite.A + 4.0) * pow(pMod->FL, 0.25);
t = (e * pow(((a * a) + (b * b)), 0.5)) /
(clr.RGBpa[0] + clr.RGBpa[1] +
(clr.RGBpa[0] + clr.RGBpa[1] +
((21.0 / 20.0) * clr.RGBpa[2]));
clr.C = pow(t, 0.9) * pow((clr.J / 100.0), 0.5) *
@@ -235,34 +235,34 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
clr.M = clr.C * pow(pMod->FL, 0.25);
clr.s = 100.0 * pow((clr.M / clr.Q), 0.5);
return clr;
}
static
CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsFloat64Number t, e, p1, p2, p3, p4, p5, hr, d2r;
d2r = 3.141592654 / 180.0;
t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) *
(pow((1.64 - pow(0.29, pMod->n)), 0.73)))),
(pow((1.64 - pow(0.29, pMod->n)), 0.73)))),
(1.0 / 0.9) );
e = ((12500.0 / 13.0) * pMod->Nc * pMod->Ncb) *
(cos((clr.h * d2r + 2.0)) + 3.8);
clr.A = pMod->adoptedWhite.A * pow(
(clr.J / 100.0),
(1.0 / (pMod->c * pMod->z)));
p1 = e / t;
p2 = (clr.A / pMod->Nbb) + 0.305;
p3 = 21.0 / 20.0;
hr = clr.h * d2r;
if (fabs(sin(hr)) >= fabs(cos(hr))) {
p4 = p1 / sin(hr);
clr.b = (p2 * (2.0 + p3) * (460.0 / 1403.0)) /
@@ -279,17 +279,17 @@ CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
(sin(hr) / cos(hr)));
clr.b = clr.a * (sin(hr) / cos(hr));
}
clr.RGBpa[0] = ((460.0 / 1403.0) * p2) +
clr.RGBpa[0] = ((460.0 / 1403.0) * p2) +
((451.0 / 1403.0) * clr.a) +
((288.0 / 1403.0) * clr.b);
clr.RGBpa[1] = ((460.0 / 1403.0) * p2) -
clr.RGBpa[1] = ((460.0 / 1403.0) * p2) -
((891.0 / 1403.0) * clr.a) -
((261.0 / 1403.0) * clr.b);
clr.RGBpa[2] = ((460.0 / 1403.0) * p2) -
((220.0 / 1403.0) * clr.a) -
((6300.0 / 1403.0) * clr.b);
return clr;
}
@@ -298,7 +298,7 @@ CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsUInt32Number i;
cmsFloat64Number c1;
for (i = 0; i < 3; i++) {
if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1;
else c1 = 1;
@@ -307,15 +307,15 @@ CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
(400.0 - fabs(clr.RGBpa[i] - 0.1))),
(1.0 / 0.42));
}
return clr;
}
static
CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
{
cmsFloat64Number M[9];
M[0] = (( 0.7328 * 1.910197) + (0.4296 * 0.370950));
M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054));
M[2] = (( 0.7328 * 0.201908) + (0.4296 * 0.000008) - 0.1624);
@@ -325,7 +325,7 @@ CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
M[6] = (( 0.0030 * 1.910197) + (0.0136 * 0.370950));
M[7] = (( 0.0030 * -1.112124) + (0.0136 * 0.629054));
M[8] = (( 0.0030 * 0.201908) + (0.0136 * 0.000008) + 0.9834);;
clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]);
clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]);
clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]);
@@ -334,10 +334,10 @@ CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
static
CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{
cmsUInt32Number i;
for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++) {
clr.RGB[i] = clr.RGBc[i] /
((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D);
}
@@ -346,82 +346,82 @@ CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
static
CAM02COLOR CAT02toXYZ(CAM02COLOR clr)
CAM02COLOR CAT02toXYZ(CAM02COLOR clr)
{
clr.XYZ[0] = (clr.RGB[0] * 1.096124) + (clr.RGB[1] * -0.278869) + (clr.RGB[2] * 0.182745);
clr.XYZ[1] = (clr.RGB[0] * 0.454369) + (clr.RGB[1] * 0.473533) + (clr.RGB[2] * 0.072098);
clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] * 1.015326);
return clr;
}
cmsHANDLE CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC)
{
cmsCIECAM02* lpMod;
cmsCIECAM02* lpMod;
_cmsAssert(pVC != NULL);
_cmsAssert(pVC != NULL);
if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
return NULL;
}
if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
return NULL;
}
lpMod ->ContextID = ContextID;
lpMod ->ContextID = ContextID;
lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
lpMod ->adoptedWhite.XYZ[2] = pVC ->whitePoint.Z;
lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
lpMod ->adoptedWhite.XYZ[2] = pVC ->whitePoint.Z;
lpMod -> LA = pVC ->La;
lpMod -> Yb = pVC ->Yb;
lpMod -> D = pVC ->D_value;
lpMod -> surround = pVC ->surround;
lpMod -> LA = pVC ->La;
lpMod -> Yb = pVC ->Yb;
lpMod -> D = pVC ->D_value;
lpMod -> surround = pVC ->surround;
switch (lpMod -> surround) {
switch (lpMod -> surround) {
case CUTSHEET_SURROUND:
lpMod->F = 0.8;
lpMod->c = 0.41;
lpMod->Nc = 0.8;
break;
case CUTSHEET_SURROUND:
lpMod->F = 0.8;
lpMod->c = 0.41;
lpMod->Nc = 0.8;
break;
case DARK_SURROUND:
lpMod -> F = 0.8;
lpMod -> c = 0.525;
lpMod -> Nc = 0.8;
break;
case DARK_SURROUND:
lpMod -> F = 0.8;
lpMod -> c = 0.525;
lpMod -> Nc = 0.8;
break;
case DIM_SURROUND:
lpMod -> F = 0.9;
lpMod -> c = 0.59;
lpMod -> Nc = 0.95;
break;
case DIM_SURROUND:
lpMod -> F = 0.9;
lpMod -> c = 0.59;
lpMod -> Nc = 0.95;
break;
default:
// Average surround
lpMod -> F = 1.0;
lpMod -> c = 0.69;
lpMod -> Nc = 1.0;
}
default:
// Average surround
lpMod -> F = 1.0;
lpMod -> c = 0.69;
lpMod -> Nc = 1.0;
}
lpMod -> n = compute_n(lpMod);
lpMod -> z = compute_z(lpMod);
lpMod -> Nbb = computeNbb(lpMod);
lpMod -> FL = computeFL(lpMod);
lpMod -> n = compute_n(lpMod);
lpMod -> z = compute_z(lpMod);
lpMod -> Nbb = computeNbb(lpMod);
lpMod -> FL = computeFL(lpMod);
if (lpMod -> D == D_CALCULATE) {
lpMod -> D = computeD(lpMod);
}
if (lpMod -> D == D_CALCULATE) {
lpMod -> D = computeD(lpMod);
}
lpMod -> Ncb = lpMod -> Nbb;
lpMod -> Ncb = lpMod -> Nbb;
lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod);
lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod);
lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
return (cmsHANDLE) lpMod;
return (cmsHANDLE) lpMod;
}
@@ -429,32 +429,34 @@ void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel)
{
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
if (lpMod) _cmsFree(lpMod ->ContextID, lpMod);
if (lpMod) _cmsFree(lpMod ->ContextID, lpMod);
}
void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut)
{
{
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
memset(&clr, 0, sizeof(clr));
clr.XYZ[0] = pIn ->X;
clr.XYZ[1] = pIn ->Y;
clr.XYZ[2] = pIn ->Z;
clr = XYZtoCAT02(clr);
clr = ChromaticAdaptation(clr, lpMod);
clr = CAT02toHPE(clr);
clr = NonlinearCompression(clr, lpMod);
clr = ComputeCorrelates(clr, lpMod);
pOut ->J = clr.J;
pOut ->C = clr.C;
pOut ->h = clr.h;
pOut ->h = clr.h;
}
void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut)
@@ -462,22 +464,23 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
memset(&clr, 0, sizeof(clr));
clr.J = pIn -> J;
clr.C = pIn -> C;
clr.h = pIn -> h;
clr = InverseCorrelates(clr, lpMod);
clr = InverseNonlinearity(clr, lpMod);
clr = HPEtoCAT02(clr);
clr = InverseChromaticAdaptation(clr, lpMod);
clr = CAT02toXYZ(clr);
pOut ->X = clr.XYZ[0];
pOut ->Y = clr.XYZ[1];
pOut ->Z = clr.XYZ[2];
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -31,30 +31,31 @@
// compare two strings ignoring case
int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
{
register const unsigned char *us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
register const unsigned char *us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
while (toupper(*us1) == toupper(*us2++))
if (*us1++ == '\0')
return (0);
return (toupper(*us1) - toupper(*--us2));
while (toupper(*us1) == toupper(*us2++))
if (*us1++ == '\0')
return 0;
return (toupper(*us1) - toupper(*--us2));
}
// long int because C99 specifies ftell in such way (7.19.9.2)
long int CMSEXPORT cmsfilelength(FILE* f)
{
long int p , n;
long int p , n;
p = ftell(f); // register current file position
p = ftell(f); // register current file position
if (fseek(f, 0, SEEK_END) != 0) {
return -1;
}
if (fseek(f, 0, SEEK_END) != 0) {
return -1;
}
n = ftell(f);
fseek(f, p, SEEK_SET); // file position restored
fseek(f, p, SEEK_SET); // file position restored
return n;
return n;
}
@@ -62,23 +63,22 @@ long int CMSEXPORT cmsfilelength(FILE* f)
//
// This is the interface to low-level memory management routines. By default a simple
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
// amount of memoy that can be reclaimed. This is mostly as a safety feature to
// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms
// would never need.
// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent
// bogus or evil code to allocate huge blocks that otherwise lcms would never need.
#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U))
// User may override this behaviour by using a memory plug-in, which basically replaces
// the default memory management functions. In this case, no check is performed and it
// is up to the plug-in writter to keep in the safe side. There are only three functions
// required to be implemented: malloc, realloc and free, although the user may want to
// the default memory management functions. In this case, no check is performed and it
// is up to the plug-in writter to keep in the safe side. There are only three functions
// required to be implemented: malloc, realloc and free, although the user may want to
// replace the optional mallocZero, calloc and dup as well.
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// *********************************************************************************
// This is the default memory allocation function. It does a very coarse
// This is the default memory allocation function. It does a very coarse
// check of amout of memory, just to prevent exploits
static
void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
@@ -109,13 +109,13 @@ void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr)
// free(NULL) is defined a no-op by C99, therefore it is safe to
// avoid the check, but it is here just in case...
if (Ptr) free(Ptr);
if (Ptr) free(Ptr);
cmsUNUSED_PARAMETER(ContextID);
}
// The default realloc function. Again it check for exploits. If Ptr is NULL,
// realloc behaves the same way as malloc and allocates a new block of size bytes.
// The default realloc function. Again it checks for exploits. If Ptr is NULL,
// realloc behaves the same way as malloc and allocates a new block of size bytes.
static
void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{
@@ -139,13 +139,13 @@ void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Nu
if (Total == 0) return NULL;
// Safe check for overflow.
if (num >= UINT_MAX / size) return NULL;
if (num >= UINT_MAX / size) return NULL;
// Check for overflow
if (Total < num || Total < size) {
return NULL;
}
if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb
return _cmsMallocZero(ContextID, Total);
@@ -156,7 +156,7 @@ static
void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
void* mem;
if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb
mem = _cmsMalloc(ContextID, size);
@@ -167,95 +167,149 @@ void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number si
return mem;
}
// Pointers to malloc and _cmsFree functions in current environment
static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn;
static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn;
static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn;
static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn;
static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn;
static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn;
// Pointers to memory manager functions in Context0
_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn,
_cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn
};
// Reset and duplicate memory manager
void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
{
_cmsAssert(ctx != NULL);
if (src != NULL) {
// Duplicate
ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType));
}
else {
// To reset it, we use the default allocators, which cannot be overriden
ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
}
}
// Auxiliar to fill memory management functions from plugin (or context 0 defaults)
void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr)
{
if (Plugin == NULL) {
memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk));
}
else {
ptr ->MallocPtr = Plugin -> MallocPtr;
ptr ->FreePtr = Plugin -> FreePtr;
ptr ->ReallocPtr = Plugin -> ReallocPtr;
// Make sure we revert to defaults
ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn;
ptr ->CallocPtr = _cmsCallocDefaultFn;
ptr ->DupPtr = _cmsDupDefaultFn;
if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr;
if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr;
if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr;
}
}
// Plug-in replacement entry
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data)
{
cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
_cmsMemPluginChunkType* ptr;
// NULL forces to reset to defaults
// NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure.
// Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the
// context internal data should be malloce'd by using those functions.
if (Data == NULL) {
MallocPtr = _cmsMallocDefaultFn;
MallocZeroPtr= _cmsMallocZeroDefaultFn;
FreePtr = _cmsFreeDefaultFn;
ReallocPtr = _cmsReallocDefaultFn;
CallocPtr = _cmsCallocDefaultFn;
DupPtr = _cmsDupDefaultFn;
struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID;
// Return to the default allocators
if (ContextID != NULL) {
ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager;
}
return TRUE;
}
// Check for required callbacks
if (Plugin -> MallocPtr == NULL ||
// Check for required callbacks
if (Plugin -> MallocPtr == NULL ||
Plugin -> FreePtr == NULL ||
Plugin -> ReallocPtr == NULL) return FALSE;
Plugin -> ReallocPtr == NULL) return FALSE;
// Set replacement functions
MallocPtr = Plugin -> MallocPtr;
FreePtr = Plugin -> FreePtr;
ReallocPtr = Plugin -> ReallocPtr;
if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr;
if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr;
if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr;
ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
if (ptr == NULL)
return FALSE;
_cmsInstallAllocFunctions(Plugin, ptr);
return TRUE;
}
// Generic allocate
void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
{
return MallocPtr(ContextID, size);
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
return ptr ->MallocPtr(ContextID, size);
}
// Generic allocate & zero
void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
{
return MallocZeroPtr(ContextID, size);
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
return ptr->MallocZeroPtr(ContextID, size);
}
// Generic calloc
void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
{
return CallocPtr(ContextID, num, size);
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
return ptr->CallocPtr(ContextID, num, size);
}
// Generic reallocate
void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{
return ReallocPtr(ContextID, Ptr, size);
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
return ptr->ReallocPtr(ContextID, Ptr, size);
}
// Generic free memory
void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
{
if (Ptr != NULL) FreePtr(ContextID, Ptr);
if (Ptr != NULL) {
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
ptr ->FreePtr(ContextID, Ptr);
}
}
// Generic block duplication
void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
return DupPtr(ContextID, Org, size);
_cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
return ptr ->DupPtr(ContextID, Org, size);
}
// ********************************************************************************************
// Sub allocation takes care of many pointers of small size. The memory allocated in
// this way have be freed at once. Next function allocates a single chunk for linked list
// I prefer this method over realloc due to the big inpact on xput realloc may have if
// memory is being swapped to disk. This approach is safer (although thats not true on any platform)
// I prefer this method over realloc due to the big inpact on xput realloc may have if
// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms)
static
_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial)
{
_cmsSubAllocator_chunk* chunk;
// 20K by default
if (Initial == 0)
Initial = 20*1024;
// Create the container
chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk));
if (chunk == NULL) return NULL;
@@ -269,10 +323,6 @@ _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32N
return NULL;
}
// 20K by default
if (Initial == 0)
Initial = 20*1024;
chunk ->BlockSize = Initial;
chunk ->Used = 0;
chunk ->next = NULL;
@@ -325,9 +375,9 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used;
cmsUInt8Number* ptr;
size = _cmsALIGNLONG(size);
size = _cmsALIGNMEM(size);
// Check for memory. If there is no room, allocate a new chunk of double memory size.
// Check for memory. If there is no room, allocate a new chunk of double memory size.
if (size > Free) {
_cmsSubAllocator_chunk* chunk;
@@ -344,20 +394,40 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
sub ->h = chunk;
}
ptr = sub -> h ->Block + sub -> h ->Used;
sub -> h -> Used += size;
return (void*) ptr;
}
// Duplicate in pool
void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size)
{
void *NewPtr;
// Dup of null pointer is also NULL
if (ptr == NULL)
return NULL;
NewPtr = _cmsSubAlloc(s, size);
if (ptr != NULL && NewPtr != NULL) {
memcpy(NewPtr, ptr, size);
}
return NewPtr;
}
// Error logging ******************************************************************
// There is no error handling at all. When a funtion fails, it returns proper value.
// For example, all create functions does return NULL on failure. Other return FALSE
// It may be interesting, for the developer, to know why the function is failing.
// for that reason, lcms2 does offer a logging function. This function does recive
// a ENGLISH string with some clues on what is going wrong. You can show this
// a ENGLISH string with some clues on what is going wrong. You can show this
// info to the end user, or just create some sort of log.
// The logging function should NOT terminate the program, as this obviously can leave
// resources. It is the programmer's responsability to check each function return code
@@ -372,8 +442,26 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
// This is our default log error
static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
// The current handler in actual environment
static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction;
// Context0 storage, which is global
_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction };
// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value
// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients
void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction };
void* from;
if (src != NULL) {
from = src ->chunks[Logger];
}
else {
from = &LogErrorChunk;
}
ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType));
}
// The default error logger does nothing.
static
@@ -381,34 +469,50 @@ void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorC
{
// fprintf(stderr, "[lcms]: %s\n", Text);
// fflush(stderr);
cmsUNUSED_PARAMETER(ContextID);
cmsUNUSED_PARAMETER(ErrorCode);
cmsUNUSED_PARAMETER(Text);
cmsUNUSED_PARAMETER(Text);
}
// Change log error
// Change log error, context based
void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn)
{
_cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
if (lhg != NULL) {
if (Fn == NULL)
lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction;
else
lhg -> LogErrorHandler = Fn;
}
}
// Change log error, legacy
void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
{
if (Fn == NULL)
LogErrorHandler = DefaultLogErrorHandlerFunction;
else
LogErrorHandler = Fn;
cmsSetLogErrorHandlerTHR(NULL, Fn);
}
// Log an error
// Log an error
// ErrorText is a text holding an english description of error.
void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...)
{
va_list args;
char Buffer[MAX_ERROR_MESSAGE_LEN];
_cmsLogErrorChunkType* lhg;
va_start(args, ErrorText);
vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
va_end(args);
va_end(args);
// Call handler
LogErrorHandler(ContextID, ErrorCode, Buffer);
// Check for the context, if specified go there. If not, go for the global
lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
if (lhg ->LogErrorHandler) {
lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer);
}
}
// Utility function to print signatures
@@ -419,10 +523,132 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig)
// Convert to big endian
be = _cmsAdjustEndianess32((cmsUInt32Number) sig);
// Move chars
// Move chars
memmove(String, &be, 4);
// Make sure of terminator
String[4] = 0;
}
//--------------------------------------------------------------------------------------------------
static
void* defMtxCreate(cmsContext id)
{
_cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex));
_cmsInitMutexPrimitive(ptr_mutex);
return (void*) ptr_mutex;
}
static
void defMtxDestroy(cmsContext id, void* mtx)
{
_cmsDestroyMutexPrimitive((_cmsMutex *) mtx);
_cmsFree(id, mtx);
}
static
cmsBool defMtxLock(cmsContext id, void* mtx)
{
cmsUNUSED_PARAMETER(id);
return _cmsLockPrimitive((_cmsMutex *) mtx) == 0;
}
static
void defMtxUnlock(cmsContext id, void* mtx)
{
cmsUNUSED_PARAMETER(id);
_cmsUnlockPrimitive((_cmsMutex *) mtx);
}
// Pointers to memory manager functions in Context0
_cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
// Allocate and init mutex container.
void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock };
void* from;
if (src != NULL) {
from = src ->chunks[MutexPlugin];
}
else {
from = &MutexChunk;
}
ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType));
}
// Register new ways to transform
cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginMutex* Plugin = (cmsPluginMutex*) Data;
_cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
if (Data == NULL) {
// No lock routines
ctx->CreateMutexPtr = NULL;
ctx->DestroyMutexPtr = NULL;
ctx->LockMutexPtr = NULL;
ctx ->UnlockMutexPtr = NULL;
return TRUE;
}
// Factory callback is required
if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL ||
Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE;
ctx->CreateMutexPtr = Plugin->CreateMutexPtr;
ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr;
ctx ->LockMutexPtr = Plugin ->LockMutexPtr;
ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr;
// All is ok
return TRUE;
}
// Generic Mutex fns
void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID)
{
_cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
if (ptr ->CreateMutexPtr == NULL) return NULL;
return ptr ->CreateMutexPtr(ContextID);
}
void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx)
{
_cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
if (ptr ->DestroyMutexPtr != NULL) {
ptr ->DestroyMutexPtr(ContextID, mtx);
}
}
cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx)
{
_cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
if (ptr ->LockMutexPtr == NULL) return TRUE;
return ptr ->LockMutexPtr(ContextID, mtx);
}
void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx)
{
_cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
if (ptr ->UnlockMutexPtr != NULL) {
ptr ->UnlockMutexPtr(ContextID, mtx);
}
}

View File

@@ -1,42 +1,42 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2013 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//
#include "lcms2_internal.h"
// Tone curves are powerful constructs that can contain curves specified in diverse ways.
// Tone curves are powerful constructs that can contain curves specified in diverse ways.
// The curve is stored in segments, where each segment can be sampled or specified by parameters.
// a 16.bit simplification of the *whole* curve is kept for optimization purposes. For float operation,
// each segment is evaluated separately. Plug-ins may be used to define new parametric schemes,
// each plug-in may define up to MAX_TYPES_IN_LCMS_PLUGIN functions types. For defining a function,
// a 16.bit simplification of the *whole* curve is kept for optimization purposes. For float operation,
// each segment is evaluated separately. Plug-ins may be used to define new parametric schemes,
// each plug-in may define up to MAX_TYPES_IN_LCMS_PLUGIN functions types. For defining a function,
// the plug-in should provide the type id, how many parameters each type has, and a pointer to
// a procedure that evaluates the function. In the case of reverse evaluation, the evaluator will
// be called with the type id as a negative value, and a sampled version of the reversed curve
// a procedure that evaluates the function. In the case of reverse evaluation, the evaluator will
// be called with the type id as a negative value, and a sampled version of the reversed curve
// will be built.
// ----------------------------------------------------------------- Implementation
// Maxim number of nodes
// Maxim number of nodes
#define MAX_NODES_IN_CURVE 4097
#define MINUS_INF (-1E22F)
#define PLUS_INF (+1E22F)
@@ -53,12 +53,11 @@ typedef struct _cmsParametricCurvesCollection_st {
} _cmsParametricCurvesCollection;
// This is the default (built-in) evaluator
// This is the default (built-in) evaluator
static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R);
// The built-in list
static _cmsParametricCurvesCollection DefaultCurves = {
static _cmsParametricCurvesCollection DefaultCurves = {
9, // # of curve types
{ 1, 2, 3, 4, 5, 6, 7, 8, 108 }, // Parametric curve ID
{ 1, 3, 4, 5, 7, 4, 5, 5, 1 }, // Parameters by type
@@ -66,22 +65,77 @@ static _cmsParametricCurvesCollection DefaultCurves = {
NULL // Next in chain
};
// Duplicates the zone of memory used by the plug-in in the new context
static
void DupPluginCurvesList(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
_cmsCurvesPluginChunkType newHead = { NULL };
_cmsParametricCurvesCollection* entry;
_cmsParametricCurvesCollection* Anterior = NULL;
_cmsCurvesPluginChunkType* head = (_cmsCurvesPluginChunkType*) src->chunks[CurvesPlugin];
_cmsAssert(head != NULL);
// Walk the list copying all nodes
for (entry = head->ParametricCurves;
entry != NULL;
entry = entry ->Next) {
_cmsParametricCurvesCollection *newEntry = ( _cmsParametricCurvesCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsParametricCurvesCollection));
if (newEntry == NULL)
return;
// We want to keep the linked list order, so this is a little bit tricky
newEntry -> Next = NULL;
if (Anterior)
Anterior -> Next = newEntry;
Anterior = newEntry;
if (newHead.ParametricCurves == NULL)
newHead.ParametricCurves = newEntry;
}
ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsCurvesPluginChunkType));
}
// The allocator have to follow the chain
void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
_cmsAssert(ctx != NULL);
if (src != NULL) {
// Copy all linked list
DupPluginCurvesList(ctx, src);
}
else {
static _cmsCurvesPluginChunkType CurvesPluginChunk = { NULL };
ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx ->MemPool, &CurvesPluginChunk, sizeof(_cmsCurvesPluginChunkType));
}
}
// The linked list head
static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
_cmsCurvesPluginChunkType _cmsCurvesPluginChunk = { NULL };
// As a way to install new parametric curves
cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
_cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
_cmsParametricCurvesCollection* fl;
if (Data == NULL) {
ParametricCurves = &DefaultCurves;
ctx -> ParametricCurves = NULL;
return TRUE;
}
fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(sizeof(_cmsParametricCurvesCollection));
fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsParametricCurvesCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
@@ -97,8 +151,8 @@ cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number));
// Keep linked list
fl ->Next = ParametricCurves;
ParametricCurves = fl;
fl ->Next = ctx->ParametricCurves;
ctx->ParametricCurves = fl;
// All is ok
return TRUE;
@@ -120,17 +174,29 @@ int IsInSet(int Type, _cmsParametricCurvesCollection* c)
// Search for the collection which contains a specific type
static
_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index)
_cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, int Type, int* index)
{
_cmsParametricCurvesCollection* c;
int Position;
_cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
for (c = ParametricCurves; c != NULL; c = c ->Next) {
for (c = ctx->ParametricCurves; c != NULL; c = c ->Next) {
Position = IsInSet(Type, c);
if (Position != -1) {
if (index != NULL)
if (index != NULL)
*index = Position;
return c;
}
}
// If none found, revert for defaults
for (c = &DefaultCurves; c != NULL; c = c ->Next) {
Position = IsInSet(Type, c);
if (Position != -1) {
if (index != NULL)
*index = Position;
return c;
}
@@ -139,12 +205,12 @@ _cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index)
return NULL;
}
// Low level allocate, which takes care of memory details. nEntries may be zero, and in this case
// Low level allocate, which takes care of memory details. nEntries may be zero, and in this case
// no optimation curve is computed. nSegments may also be zero in the inverse case, where only the
// optimization curve is given. Both features simultaneously is an error
static
cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries,
cmsInt32Number nSegments, const cmsCurveSegment* Segments,
cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries,
cmsInt32Number nSegments, const cmsCurveSegment* Segments,
const cmsUInt16Number* Values)
{
cmsToneCurve* p;
@@ -179,7 +245,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr
}
p -> nSegments = nSegments;
// This 16-bit table contains a limited precision representation of the whole curve and is kept for
// increasing xput on certain operations.
if (nEntries <= 0) {
@@ -189,13 +255,13 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr
p ->Table16 = (cmsUInt16Number*) _cmsCalloc(ContextID, nEntries, sizeof(cmsUInt16Number));
if (p ->Table16 == NULL) goto Error;
}
p -> nEntries = nEntries;
// Initialize members if requested
if (Values != NULL && (nEntries > 0)) {
for (i=0; i < nEntries; i++)
for (i=0; i < nEntries; i++)
p ->Table16[i] = Values[i];
}
@@ -222,14 +288,15 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr
p ->Segments[i].SampledPoints = NULL;
c = GetParametricCurveByType(Segments[i].Type, NULL);
c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL);
if (c != NULL)
p ->Evals[i] = c ->Evaluator;
}
}
p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
return p;
if (p->InterpParams != NULL)
return p;
Error:
if (p -> Segments) _cmsFree(ContextID, p ->Segments);
@@ -248,18 +315,28 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
switch (Type) {
// X = Y ^ Gamma
// X = Y ^ Gamma
case 1:
if (R < 0)
Val = 0;
if (R < 0) {
if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE)
Val = R;
else
Val = 0;
}
else
Val = pow(R, Params[0]);
break;
// Type 1 Reversed: X = Y ^1/gamma
case -1:
if (R < 0)
Val = 0;
if (R < 0) {
if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE)
Val = R;
else
Val = 0;
}
else
Val = pow(R, 1/Params[0]);
break;
@@ -285,14 +362,14 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Type 2 Reversed
// X = (Y ^1/g - b) / a
case -2:
case -2:
if (R < 0)
Val = 0;
else
Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
if (Val < 0)
Val = 0;
Val = 0;
break;
@@ -306,7 +383,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (R >= disc) {
e = Params[1]*R + Params[2];
e = Params[1]*R + Params[2];
if (e > 0)
Val = pow(e, Params[0]) + Params[3];
@@ -320,15 +397,15 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Type 3 reversed
// X=((Y-c)^1/g - b)/a | (Y>=c)
// X=-b/a | (Y<c)
// X=-b/a | (Y<c)
case -3:
if (R >= Params[3]) {
e = R - Params[3];
if (e > 0)
Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
else
else
Val = 0;
}
else {
@@ -384,8 +461,8 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (e > 0)
Val = pow(e, Params[0]) + Params[5];
else
Val = 0;
}
Val = Params[5];
}
else
Val = R*Params[3] + Params[6];
break;
@@ -400,7 +477,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
if (R >= disc) {
e = R - Params[5];
if (e < 0)
if (e < 0)
Val = 0;
else
Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
@@ -413,46 +490,46 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Types 6,7,8 comes from segmented curves as described in ICCSpecRevision_02_11_06_Float.pdf
// Type 6 is basically identical to type 5 without d
// Y = (a * X + b) ^ Gamma + c
case 6:
case 6:
e = Params[1]*R + Params[2];
if (e < 0)
Val = 0;
else
if (e < 0)
Val = Params[3];
else
Val = pow(e, Params[0]) + Params[3];
break;
// ((Y - c) ^1/Gamma - b) / a
// ((Y - c) ^1/Gamma - b) / a
case -6:
e = R - Params[3];
if (e < 0)
Val = 0;
else
else
Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
break;
// Y = a * log (b * X^Gamma + c) + d
case 7:
case 7:
e = Params[2] * pow(R, Params[0]) + Params[3];
if (e <= 0)
Val = 0;
Val = Params[4];
else
Val = Params[1]*log10(e) + Params[4];
break;
// (Y - d) / a = log(b * X ^Gamma + c)
// pow(10, (Y-d) / a) = b * X ^Gamma + c
// pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X
// pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X
case -7:
Val = pow((pow(10.0, (R-Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]);
break;
//Y = a * b^(c*X+d) + e
//Y = a * b^(c*X+d) + e
case 8:
Val = (Params[0] * pow(Params[1], Params[2] * R + Params[3]) + Params[4]);
break;
@@ -461,14 +538,14 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// Y = (log((y-e) / a) / log(b) - d ) / c
// a=0, b=1, c=2, d=3, e=4,
case -8:
disc = R - Params[4];
if (disc < 0) Val = 0;
else
Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2];
else
Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2];
break;
// S-Shaped: (1 - (1-x)^1/g)^1/g
// S-Shaped: (1 - (1-x)^1/g)^1/g
case 108:
Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]);
break;
@@ -491,7 +568,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
}
// Evaluate a segmented funtion for a single value. Return -1 if no valid segment found .
// If fn type is 0, perform an interpolation on the table
// If fn type is 0, perform an interpolation on the table
static
cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
{
@@ -505,14 +582,14 @@ cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
// Type == 0 means segment is sampled
if (g ->Segments[i].Type == 0) {
cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0);
cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0);
cmsFloat32Number Out;
// Setup the table (TODO: clean that)
g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints;
g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints;
g ->SegInterp[i] -> Interpolation.LerpFloat(&R1, &Out, g ->SegInterp[i]);
return Out;
}
else
@@ -523,6 +600,19 @@ cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
return MINUS_INF;
}
// Access to estimated low-res table
cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t)
{
_cmsAssert(t != NULL);
return t ->nEntries;
}
const cmsUInt16Number* CMSEXPORT cmsGetToneCurveEstimatedTable(const cmsToneCurve* t)
{
_cmsAssert(t != NULL);
return t ->Table16;
}
// Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the
// floating point description empty.
@@ -540,17 +630,17 @@ int EntriesByGamma(cmsFloat64Number Gamma)
// Create a segmented gamma, fill the table
cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
cmsInt32Number nSegments, const cmsCurveSegment Segments[])
{
int i;
cmsFloat64Number R, Val;
cmsToneCurve* g;
int nGridPoints = 4096;
_cmsAssert(Segments != NULL);
// Optimizatin for identity curves.
// Optimizatin for identity curves.
if (nSegments == 1 && Segments[0].Type == 1) {
nGridPoints = EntriesByGamma(Segments[0].Params[0]);
@@ -577,28 +667,41 @@ cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
// Use a segmented curve to store the floating point table
cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[])
{
cmsCurveSegment Seg[2];
cmsCurveSegment Seg[3];
// Initialize segmented curve part up to 0
Seg[0].x0 = -1;
// A segmented tone curve should have function segments in the first and last positions
// Initialize segmented curve part up to 0 to constant value = samples[0]
Seg[0].x0 = MINUS_INF;
Seg[0].x1 = 0;
Seg[0].Type = 6;
Seg[0].Params[0] = 1;
Seg[0].Params[1] = 0;
Seg[0].Params[2] = 0;
Seg[0].Params[3] = 0;
Seg[0].Params[3] = values[0];
Seg[0].Params[4] = 0;
// From zero to any
// From zero to 1
Seg[1].x0 = 0;
Seg[1].x1 = 1.0;
Seg[1].x1 = 1.0;
Seg[1].Type = 0;
Seg[1].nGridPoints = nEntries;
Seg[1].SampledPoints = (cmsFloat32Number*) values;
return cmsBuildSegmentedToneCurve(ContextID, 2, Seg);
// Final segment is constant = lastsample
Seg[2].x0 = 1.0;
Seg[2].x1 = PLUS_INF;
Seg[2].Type = 6;
Seg[2].Params[0] = 1;
Seg[2].Params[1] = 0;
Seg[2].Params[2] = 0;
Seg[2].Params[3] = values[nEntries-1];
Seg[2].Params[4] = 0;
return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
}
// Parametric curves
@@ -611,12 +714,12 @@ cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt
cmsCurveSegment Seg0;
int Pos = 0;
cmsUInt32Number size;
_cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos);
_cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos);
_cmsAssert(Params != NULL);
if (c == NULL) {
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
return NULL;
}
@@ -645,27 +748,27 @@ cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gam
void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve)
{
cmsContext ContextID;
if (Curve == NULL) return;
ContextID = Curve ->InterpParams->ContextID;
_cmsFreeInterpParams(Curve ->InterpParams);
if (Curve -> Table16)
_cmsFree(ContextID, Curve ->Table16);
if (Curve ->Segments) {
cmsUInt32Number i;
for (i=0; i < Curve ->nSegments; i++) {
if (Curve ->Segments[i].SampledPoints) {
_cmsFree(ContextID, Curve ->Segments[i].SampledPoints);
}
if (Curve ->SegInterp[i] != 0)
if (Curve ->SegInterp[i] != 0)
_cmsFreeInterpParams(Curve->SegInterp[i]);
}
@@ -695,18 +798,18 @@ void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3])
// Duplicate a gamma table
cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In)
{
{
if (In == NULL) return NULL;
return AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16);
}
// Joins two curves for X and Y. Curves should be monotonic.
// We want to get
// We want to get
//
// y = Y^-1(X(t))
// y = Y^-1(X(t))
//
cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
const cmsToneCurve* X,
const cmsToneCurve* Y, cmsUInt32Number nResultingPoints)
{
@@ -725,7 +828,7 @@ cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
Res = (cmsFloat32Number*) _cmsCalloc(ContextID, nResultingPoints, sizeof(cmsFloat32Number));
if (Res == NULL) goto Error;
//Iterate
for (i=0; i < nResultingPoints; i++) {
@@ -736,7 +839,7 @@ cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
// Allocate space for output
out = cmsBuildTabulatedToneCurveFloat(ContextID, nResultingPoints, Res);
Error:
if (Res != NULL) _cmsFree(ContextID, Res);
@@ -747,25 +850,25 @@ Error:
// Get the surrounding nodes. This is tricky on non-monotonic tables
// Get the surrounding nodes. This is tricky on non-monotonic tables
static
int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const struct _cms_interp_struc* p)
{
{
int i;
int y0, y1;
// A 1 point table is not allowed
if (p -> Domain[0] < 1) return -1;
// Let's see if ascending or descending.
// Let's see if ascending or descending.
if (LutTable[0] < LutTable[p ->Domain[0]]) {
// Table is overall ascending
for (i=p->Domain[0]-1; i >=0; --i) {
y0 = LutTable[i];
y0 = LutTable[i];
y1 = LutTable[i+1];
if (y0 <= y1) { // Increasing
if (In >= y0 && In <= y1) return i;
}
@@ -779,7 +882,7 @@ int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const str
// Table is overall descending
for (i=0; i < (int) p -> Domain[0]; i++) {
y0 = LutTable[i];
y0 = LutTable[i];
y1 = LutTable[i+1];
if (y0 <= y1) { // Increasing
@@ -802,18 +905,21 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con
cmsFloat64Number a = 0, b = 0, y, x1, y1, x2, y2;
int i, j;
int Ascending;
_cmsAssert(InCurve != NULL);
// Try to reverse it analytically whatever possible
if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) {
if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 &&
/* InCurve -> Segments[0].Type <= 5 */
GetParametricCurveByType(InCurve ->InterpParams->ContextID, InCurve ->Segments[0].Type, NULL) != NULL) {
return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID,
-(InCurve -> Segments[0].Type),
return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID,
-(InCurve -> Segments[0].Type),
InCurve -> Segments[0].Params);
}
// Nope, reverse the table.
// Nope, reverse the table.
out = cmsBuildTabulatedToneCurve16(InCurve ->InterpParams->ContextID, nResultSamples, NULL);
if (out == NULL)
return NULL;
@@ -826,18 +932,18 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con
y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1);
// Find interval in which y is within.
// Find interval in which y is within.
j = GetInterval(y, InCurve->Table16, InCurve->InterpParams);
if (j >= 0) {
// Get limits of interval
x1 = InCurve ->Table16[j];
x1 = InCurve ->Table16[j];
x2 = InCurve ->Table16[j+1];
y1 = (cmsFloat64Number) (j * 65535.0) / (InCurve ->nEntries - 1);
y2 = (cmsFloat64Number) ((j+1) * 65535.0 ) / (InCurve ->nEntries - 1);
// If collapsed, then use any
if (x1 == x2) {
@@ -846,12 +952,12 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con
} else {
// Interpolate
// Interpolate
a = (y2 - y1) / (x2 - x1);
b = y2 - a * x2;
}
}
out ->Table16[i] = _cmsQuickSaturateWord(a* y + b);
}
@@ -887,7 +993,7 @@ cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[]
c = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
d = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
e = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
if (c != NULL && d != NULL && e != NULL) {
@@ -899,7 +1005,7 @@ cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[]
c[2] = (-4 * lambda - d[1] * c[1] * e[1]) / d[2];
e[2] = lambda / d[2];
z[2] = w[2] * y[2] - c[1] * z[1];
for (i = 3; i < m - 1; i++) {
i1 = i - 1; i2 = i - 2;
d[i]= w[i] + 6 * lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
@@ -907,18 +1013,18 @@ cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[]
e[i] = lambda / d[i];
z[i] = w[i] * y[i] - c[i1] * z[i1] - e[i2] * z[i2];
}
i1 = m - 2; i2 = m - 3;
d[m - 1] = w[m - 1] + 5 * lambda -c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
c[m - 1] = (-2 * lambda - d[i1] * c[i1] * e[i1]) / d[m - 1];
z[m - 1] = w[m - 1] * y[m - 1] - c[i1] * z[i1] - e[i2] * z[i2];
i1 = m - 1; i2 = m - 2;
d[m] = w[m] + lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
z[m] = (w[m] * y[m] - c[i1] * z[i1] - e[i2] * z[i2]) / d[m];
z[m - 1] = z[m - 1] / d[m - 1] - c[m - 1] * z[m];
for (i = m - 2; 1<= i; i--)
z[i] = z[i] / d[i] - c[i] * z[i + 1] - e[i] * z[i + 2];
@@ -933,7 +1039,7 @@ cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[]
return st;
}
// Smooths a curve sampled at regular intervals.
// Smooths a curve sampled at regular intervals.
cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda)
{
cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE];
@@ -941,7 +1047,7 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (Tab == NULL) return FALSE;
if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do
if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do
nItems = Tab -> nEntries;
@@ -968,11 +1074,20 @@ cmsBool CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
if (z[i] == 0.) Zeros++;
if (z[i] >= 65535.) Poles++;
if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
if (z[i] < z[i-1]) {
cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
return FALSE;
}
}
if (Zeros > (nItems / 3)) return FALSE; // Degenerated, mostly zeros
if (Poles > (nItems / 3)) return FALSE; // Degenerated, mostly poles
if (Zeros > (nItems / 3)) {
cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
return FALSE;
}
if (Poles > (nItems / 3)) {
cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
return FALSE;
}
// Seems ok
for (i=0; i < nItems; i++) {
@@ -1008,20 +1123,42 @@ cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t)
{
int n;
int i, last;
cmsBool lDescending;
_cmsAssert(t != NULL);
n = t ->nEntries;
last = t ->Table16[n-1];
// Degenerated curves are monotonic? Ok, let's pass them
n = t ->nEntries;
if (n < 2) return TRUE;
for (i = n-2; i >= 0; --i) {
// Curve direction
lDescending = cmsIsToneCurveDescending(t);
if (t ->Table16[i] > last)
if (lDescending) {
return FALSE;
else
last = t ->Table16[i];
last = t ->Table16[0];
for (i = 1; i < n; i++) {
if (t ->Table16[i] - last > 2) // We allow some ripple
return FALSE;
else
last = t ->Table16[i];
}
}
else {
last = t ->Table16[n-1];
for (i = n-2; i >= 0; --i) {
if (t ->Table16[i] - last > 2)
return FALSE;
else
last = t ->Table16[i];
}
}
return TRUE;
@@ -1061,10 +1198,10 @@ cmsFloat32Number CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsF
if (Curve ->nSegments == 0) {
cmsUInt16Number In, Out;
In = (cmsUInt16Number) _cmsQuickSaturateWord(v * 65535.0);
Out = cmsEvalToneCurve16(Curve, In);
return (cmsFloat32Number) (Out / 65535.0);
}
@@ -1084,21 +1221,21 @@ cmsUInt16Number CMSEXPORT cmsEvalToneCurve16(const cmsToneCurve* Curve, cmsUInt1
// Least squares fitting.
// A mathematical procedure for finding the best-fitting curve to a given set of points by
// minimizing the sum of the squares of the offsets ("the residuals") of the points from the curve.
// The sum of the squares of the offsets is used instead of the offset absolute values because
// this allows the residuals to be treated as a continuous differentiable quantity.
// A mathematical procedure for finding the best-fitting curve to a given set of points by
// minimizing the sum of the squares of the offsets ("the residuals") of the points from the curve.
// The sum of the squares of the offsets is used instead of the offset absolute values because
// this allows the residuals to be treated as a continuous differentiable quantity.
//
// y = f(x) = x ^ g
//
// R = (yi - (xi^g))
// R2 = (yi - (xi^g))2
// SUM R2 = SUM (yi - (xi^g))2
//
// dR2/dg = -2 SUM x^g log(x)(y - x^g)
// solving for dR2/dg = 0
//
// g = 1/n * SUM(log(y) / log(x))
//
// dR2/dg = -2 SUM x^g log(x)(y - x^g)
// solving for dR2/dg = 0
//
// g = 1/n * SUM(log(y) / log(x))
cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision)
{
@@ -1110,13 +1247,13 @@ cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Num
sum = sum2 = n = 0;
// Excluding endpoints
// Excluding endpoints
for (i=1; i < (MAX_NODES_IN_CURVE-1); i++) {
x = (cmsFloat64Number) i / (MAX_NODES_IN_CURVE-1);
y = (cmsFloat64Number) cmsEvalToneCurveFloat(t, (cmsFloat32Number) x);
// Avoid 7% on lower part to prevent
// Avoid 7% on lower part to prevent
// artifacts due to linear ramps
if (y > 0. && y < 1. && x > 0.07) {

File diff suppressed because it is too large Load Diff

535
thirdparty/liblcms2/src/cmshalf.c vendored Normal file
View File

@@ -0,0 +1,535 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//
//
#include "lcms2_internal.h"
#ifndef CMS_NO_HALF_SUPPORT
// This code is inspired in the paper "Fast Half Float Conversions"
// by Jeroen van der Zijp
static cmsUInt32Number Mantissa[2048] = {
0x00000000, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34a00000,
0x34c00000, 0x34e00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000,
0x35400000, 0x35500000, 0x35600000, 0x35700000, 0x35800000, 0x35880000,
0x35900000, 0x35980000, 0x35a00000, 0x35a80000, 0x35b00000, 0x35b80000,
0x35c00000, 0x35c80000, 0x35d00000, 0x35d80000, 0x35e00000, 0x35e80000,
0x35f00000, 0x35f80000, 0x36000000, 0x36040000, 0x36080000, 0x360c0000,
0x36100000, 0x36140000, 0x36180000, 0x361c0000, 0x36200000, 0x36240000,
0x36280000, 0x362c0000, 0x36300000, 0x36340000, 0x36380000, 0x363c0000,
0x36400000, 0x36440000, 0x36480000, 0x364c0000, 0x36500000, 0x36540000,
0x36580000, 0x365c0000, 0x36600000, 0x36640000, 0x36680000, 0x366c0000,
0x36700000, 0x36740000, 0x36780000, 0x367c0000, 0x36800000, 0x36820000,
0x36840000, 0x36860000, 0x36880000, 0x368a0000, 0x368c0000, 0x368e0000,
0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369a0000,
0x369c0000, 0x369e0000, 0x36a00000, 0x36a20000, 0x36a40000, 0x36a60000,
0x36a80000, 0x36aa0000, 0x36ac0000, 0x36ae0000, 0x36b00000, 0x36b20000,
0x36b40000, 0x36b60000, 0x36b80000, 0x36ba0000, 0x36bc0000, 0x36be0000,
0x36c00000, 0x36c20000, 0x36c40000, 0x36c60000, 0x36c80000, 0x36ca0000,
0x36cc0000, 0x36ce0000, 0x36d00000, 0x36d20000, 0x36d40000, 0x36d60000,
0x36d80000, 0x36da0000, 0x36dc0000, 0x36de0000, 0x36e00000, 0x36e20000,
0x36e40000, 0x36e60000, 0x36e80000, 0x36ea0000, 0x36ec0000, 0x36ee0000,
0x36f00000, 0x36f20000, 0x36f40000, 0x36f60000, 0x36f80000, 0x36fa0000,
0x36fc0000, 0x36fe0000, 0x37000000, 0x37010000, 0x37020000, 0x37030000,
0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000,
0x370a0000, 0x370b0000, 0x370c0000, 0x370d0000, 0x370e0000, 0x370f0000,
0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000,
0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371a0000, 0x371b0000,
0x371c0000, 0x371d0000, 0x371e0000, 0x371f0000, 0x37200000, 0x37210000,
0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000,
0x37280000, 0x37290000, 0x372a0000, 0x372b0000, 0x372c0000, 0x372d0000,
0x372e0000, 0x372f0000, 0x37300000, 0x37310000, 0x37320000, 0x37330000,
0x37340000, 0x37350000, 0x37360000, 0x37370000, 0x37380000, 0x37390000,
0x373a0000, 0x373b0000, 0x373c0000, 0x373d0000, 0x373e0000, 0x373f0000,
0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000,
0x37460000, 0x37470000, 0x37480000, 0x37490000, 0x374a0000, 0x374b0000,
0x374c0000, 0x374d0000, 0x374e0000, 0x374f0000, 0x37500000, 0x37510000,
0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000,
0x37580000, 0x37590000, 0x375a0000, 0x375b0000, 0x375c0000, 0x375d0000,
0x375e0000, 0x375f0000, 0x37600000, 0x37610000, 0x37620000, 0x37630000,
0x37640000, 0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000,
0x376a0000, 0x376b0000, 0x376c0000, 0x376d0000, 0x376e0000, 0x376f0000,
0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000,
0x37760000, 0x37770000, 0x37780000, 0x37790000, 0x377a0000, 0x377b0000,
0x377c0000, 0x377d0000, 0x377e0000, 0x377f0000, 0x37800000, 0x37808000,
0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000,
0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000,
0x37870000, 0x37878000, 0x37880000, 0x37888000, 0x37890000, 0x37898000,
0x378a0000, 0x378a8000, 0x378b0000, 0x378b8000, 0x378c0000, 0x378c8000,
0x378d0000, 0x378d8000, 0x378e0000, 0x378e8000, 0x378f0000, 0x378f8000,
0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000,
0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000,
0x37960000, 0x37968000, 0x37970000, 0x37978000, 0x37980000, 0x37988000,
0x37990000, 0x37998000, 0x379a0000, 0x379a8000, 0x379b0000, 0x379b8000,
0x379c0000, 0x379c8000, 0x379d0000, 0x379d8000, 0x379e0000, 0x379e8000,
0x379f0000, 0x379f8000, 0x37a00000, 0x37a08000, 0x37a10000, 0x37a18000,
0x37a20000, 0x37a28000, 0x37a30000, 0x37a38000, 0x37a40000, 0x37a48000,
0x37a50000, 0x37a58000, 0x37a60000, 0x37a68000, 0x37a70000, 0x37a78000,
0x37a80000, 0x37a88000, 0x37a90000, 0x37a98000, 0x37aa0000, 0x37aa8000,
0x37ab0000, 0x37ab8000, 0x37ac0000, 0x37ac8000, 0x37ad0000, 0x37ad8000,
0x37ae0000, 0x37ae8000, 0x37af0000, 0x37af8000, 0x37b00000, 0x37b08000,
0x37b10000, 0x37b18000, 0x37b20000, 0x37b28000, 0x37b30000, 0x37b38000,
0x37b40000, 0x37b48000, 0x37b50000, 0x37b58000, 0x37b60000, 0x37b68000,
0x37b70000, 0x37b78000, 0x37b80000, 0x37b88000, 0x37b90000, 0x37b98000,
0x37ba0000, 0x37ba8000, 0x37bb0000, 0x37bb8000, 0x37bc0000, 0x37bc8000,
0x37bd0000, 0x37bd8000, 0x37be0000, 0x37be8000, 0x37bf0000, 0x37bf8000,
0x37c00000, 0x37c08000, 0x37c10000, 0x37c18000, 0x37c20000, 0x37c28000,
0x37c30000, 0x37c38000, 0x37c40000, 0x37c48000, 0x37c50000, 0x37c58000,
0x37c60000, 0x37c68000, 0x37c70000, 0x37c78000, 0x37c80000, 0x37c88000,
0x37c90000, 0x37c98000, 0x37ca0000, 0x37ca8000, 0x37cb0000, 0x37cb8000,
0x37cc0000, 0x37cc8000, 0x37cd0000, 0x37cd8000, 0x37ce0000, 0x37ce8000,
0x37cf0000, 0x37cf8000, 0x37d00000, 0x37d08000, 0x37d10000, 0x37d18000,
0x37d20000, 0x37d28000, 0x37d30000, 0x37d38000, 0x37d40000, 0x37d48000,
0x37d50000, 0x37d58000, 0x37d60000, 0x37d68000, 0x37d70000, 0x37d78000,
0x37d80000, 0x37d88000, 0x37d90000, 0x37d98000, 0x37da0000, 0x37da8000,
0x37db0000, 0x37db8000, 0x37dc0000, 0x37dc8000, 0x37dd0000, 0x37dd8000,
0x37de0000, 0x37de8000, 0x37df0000, 0x37df8000, 0x37e00000, 0x37e08000,
0x37e10000, 0x37e18000, 0x37e20000, 0x37e28000, 0x37e30000, 0x37e38000,
0x37e40000, 0x37e48000, 0x37e50000, 0x37e58000, 0x37e60000, 0x37e68000,
0x37e70000, 0x37e78000, 0x37e80000, 0x37e88000, 0x37e90000, 0x37e98000,
0x37ea0000, 0x37ea8000, 0x37eb0000, 0x37eb8000, 0x37ec0000, 0x37ec8000,
0x37ed0000, 0x37ed8000, 0x37ee0000, 0x37ee8000, 0x37ef0000, 0x37ef8000,
0x37f00000, 0x37f08000, 0x37f10000, 0x37f18000, 0x37f20000, 0x37f28000,
0x37f30000, 0x37f38000, 0x37f40000, 0x37f48000, 0x37f50000, 0x37f58000,
0x37f60000, 0x37f68000, 0x37f70000, 0x37f78000, 0x37f80000, 0x37f88000,
0x37f90000, 0x37f98000, 0x37fa0000, 0x37fa8000, 0x37fb0000, 0x37fb8000,
0x37fc0000, 0x37fc8000, 0x37fd0000, 0x37fd8000, 0x37fe0000, 0x37fe8000,
0x37ff0000, 0x37ff8000, 0x38000000, 0x38004000, 0x38008000, 0x3800c000,
0x38010000, 0x38014000, 0x38018000, 0x3801c000, 0x38020000, 0x38024000,
0x38028000, 0x3802c000, 0x38030000, 0x38034000, 0x38038000, 0x3803c000,
0x38040000, 0x38044000, 0x38048000, 0x3804c000, 0x38050000, 0x38054000,
0x38058000, 0x3805c000, 0x38060000, 0x38064000, 0x38068000, 0x3806c000,
0x38070000, 0x38074000, 0x38078000, 0x3807c000, 0x38080000, 0x38084000,
0x38088000, 0x3808c000, 0x38090000, 0x38094000, 0x38098000, 0x3809c000,
0x380a0000, 0x380a4000, 0x380a8000, 0x380ac000, 0x380b0000, 0x380b4000,
0x380b8000, 0x380bc000, 0x380c0000, 0x380c4000, 0x380c8000, 0x380cc000,
0x380d0000, 0x380d4000, 0x380d8000, 0x380dc000, 0x380e0000, 0x380e4000,
0x380e8000, 0x380ec000, 0x380f0000, 0x380f4000, 0x380f8000, 0x380fc000,
0x38100000, 0x38104000, 0x38108000, 0x3810c000, 0x38110000, 0x38114000,
0x38118000, 0x3811c000, 0x38120000, 0x38124000, 0x38128000, 0x3812c000,
0x38130000, 0x38134000, 0x38138000, 0x3813c000, 0x38140000, 0x38144000,
0x38148000, 0x3814c000, 0x38150000, 0x38154000, 0x38158000, 0x3815c000,
0x38160000, 0x38164000, 0x38168000, 0x3816c000, 0x38170000, 0x38174000,
0x38178000, 0x3817c000, 0x38180000, 0x38184000, 0x38188000, 0x3818c000,
0x38190000, 0x38194000, 0x38198000, 0x3819c000, 0x381a0000, 0x381a4000,
0x381a8000, 0x381ac000, 0x381b0000, 0x381b4000, 0x381b8000, 0x381bc000,
0x381c0000, 0x381c4000, 0x381c8000, 0x381cc000, 0x381d0000, 0x381d4000,
0x381d8000, 0x381dc000, 0x381e0000, 0x381e4000, 0x381e8000, 0x381ec000,
0x381f0000, 0x381f4000, 0x381f8000, 0x381fc000, 0x38200000, 0x38204000,
0x38208000, 0x3820c000, 0x38210000, 0x38214000, 0x38218000, 0x3821c000,
0x38220000, 0x38224000, 0x38228000, 0x3822c000, 0x38230000, 0x38234000,
0x38238000, 0x3823c000, 0x38240000, 0x38244000, 0x38248000, 0x3824c000,
0x38250000, 0x38254000, 0x38258000, 0x3825c000, 0x38260000, 0x38264000,
0x38268000, 0x3826c000, 0x38270000, 0x38274000, 0x38278000, 0x3827c000,
0x38280000, 0x38284000, 0x38288000, 0x3828c000, 0x38290000, 0x38294000,
0x38298000, 0x3829c000, 0x382a0000, 0x382a4000, 0x382a8000, 0x382ac000,
0x382b0000, 0x382b4000, 0x382b8000, 0x382bc000, 0x382c0000, 0x382c4000,
0x382c8000, 0x382cc000, 0x382d0000, 0x382d4000, 0x382d8000, 0x382dc000,
0x382e0000, 0x382e4000, 0x382e8000, 0x382ec000, 0x382f0000, 0x382f4000,
0x382f8000, 0x382fc000, 0x38300000, 0x38304000, 0x38308000, 0x3830c000,
0x38310000, 0x38314000, 0x38318000, 0x3831c000, 0x38320000, 0x38324000,
0x38328000, 0x3832c000, 0x38330000, 0x38334000, 0x38338000, 0x3833c000,
0x38340000, 0x38344000, 0x38348000, 0x3834c000, 0x38350000, 0x38354000,
0x38358000, 0x3835c000, 0x38360000, 0x38364000, 0x38368000, 0x3836c000,
0x38370000, 0x38374000, 0x38378000, 0x3837c000, 0x38380000, 0x38384000,
0x38388000, 0x3838c000, 0x38390000, 0x38394000, 0x38398000, 0x3839c000,
0x383a0000, 0x383a4000, 0x383a8000, 0x383ac000, 0x383b0000, 0x383b4000,
0x383b8000, 0x383bc000, 0x383c0000, 0x383c4000, 0x383c8000, 0x383cc000,
0x383d0000, 0x383d4000, 0x383d8000, 0x383dc000, 0x383e0000, 0x383e4000,
0x383e8000, 0x383ec000, 0x383f0000, 0x383f4000, 0x383f8000, 0x383fc000,
0x38400000, 0x38404000, 0x38408000, 0x3840c000, 0x38410000, 0x38414000,
0x38418000, 0x3841c000, 0x38420000, 0x38424000, 0x38428000, 0x3842c000,
0x38430000, 0x38434000, 0x38438000, 0x3843c000, 0x38440000, 0x38444000,
0x38448000, 0x3844c000, 0x38450000, 0x38454000, 0x38458000, 0x3845c000,
0x38460000, 0x38464000, 0x38468000, 0x3846c000, 0x38470000, 0x38474000,
0x38478000, 0x3847c000, 0x38480000, 0x38484000, 0x38488000, 0x3848c000,
0x38490000, 0x38494000, 0x38498000, 0x3849c000, 0x384a0000, 0x384a4000,
0x384a8000, 0x384ac000, 0x384b0000, 0x384b4000, 0x384b8000, 0x384bc000,
0x384c0000, 0x384c4000, 0x384c8000, 0x384cc000, 0x384d0000, 0x384d4000,
0x384d8000, 0x384dc000, 0x384e0000, 0x384e4000, 0x384e8000, 0x384ec000,
0x384f0000, 0x384f4000, 0x384f8000, 0x384fc000, 0x38500000, 0x38504000,
0x38508000, 0x3850c000, 0x38510000, 0x38514000, 0x38518000, 0x3851c000,
0x38520000, 0x38524000, 0x38528000, 0x3852c000, 0x38530000, 0x38534000,
0x38538000, 0x3853c000, 0x38540000, 0x38544000, 0x38548000, 0x3854c000,
0x38550000, 0x38554000, 0x38558000, 0x3855c000, 0x38560000, 0x38564000,
0x38568000, 0x3856c000, 0x38570000, 0x38574000, 0x38578000, 0x3857c000,
0x38580000, 0x38584000, 0x38588000, 0x3858c000, 0x38590000, 0x38594000,
0x38598000, 0x3859c000, 0x385a0000, 0x385a4000, 0x385a8000, 0x385ac000,
0x385b0000, 0x385b4000, 0x385b8000, 0x385bc000, 0x385c0000, 0x385c4000,
0x385c8000, 0x385cc000, 0x385d0000, 0x385d4000, 0x385d8000, 0x385dc000,
0x385e0000, 0x385e4000, 0x385e8000, 0x385ec000, 0x385f0000, 0x385f4000,
0x385f8000, 0x385fc000, 0x38600000, 0x38604000, 0x38608000, 0x3860c000,
0x38610000, 0x38614000, 0x38618000, 0x3861c000, 0x38620000, 0x38624000,
0x38628000, 0x3862c000, 0x38630000, 0x38634000, 0x38638000, 0x3863c000,
0x38640000, 0x38644000, 0x38648000, 0x3864c000, 0x38650000, 0x38654000,
0x38658000, 0x3865c000, 0x38660000, 0x38664000, 0x38668000, 0x3866c000,
0x38670000, 0x38674000, 0x38678000, 0x3867c000, 0x38680000, 0x38684000,
0x38688000, 0x3868c000, 0x38690000, 0x38694000, 0x38698000, 0x3869c000,
0x386a0000, 0x386a4000, 0x386a8000, 0x386ac000, 0x386b0000, 0x386b4000,
0x386b8000, 0x386bc000, 0x386c0000, 0x386c4000, 0x386c8000, 0x386cc000,
0x386d0000, 0x386d4000, 0x386d8000, 0x386dc000, 0x386e0000, 0x386e4000,
0x386e8000, 0x386ec000, 0x386f0000, 0x386f4000, 0x386f8000, 0x386fc000,
0x38700000, 0x38704000, 0x38708000, 0x3870c000, 0x38710000, 0x38714000,
0x38718000, 0x3871c000, 0x38720000, 0x38724000, 0x38728000, 0x3872c000,
0x38730000, 0x38734000, 0x38738000, 0x3873c000, 0x38740000, 0x38744000,
0x38748000, 0x3874c000, 0x38750000, 0x38754000, 0x38758000, 0x3875c000,
0x38760000, 0x38764000, 0x38768000, 0x3876c000, 0x38770000, 0x38774000,
0x38778000, 0x3877c000, 0x38780000, 0x38784000, 0x38788000, 0x3878c000,
0x38790000, 0x38794000, 0x38798000, 0x3879c000, 0x387a0000, 0x387a4000,
0x387a8000, 0x387ac000, 0x387b0000, 0x387b4000, 0x387b8000, 0x387bc000,
0x387c0000, 0x387c4000, 0x387c8000, 0x387cc000, 0x387d0000, 0x387d4000,
0x387d8000, 0x387dc000, 0x387e0000, 0x387e4000, 0x387e8000, 0x387ec000,
0x387f0000, 0x387f4000, 0x387f8000, 0x387fc000, 0x38000000, 0x38002000,
0x38004000, 0x38006000, 0x38008000, 0x3800a000, 0x3800c000, 0x3800e000,
0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801a000,
0x3801c000, 0x3801e000, 0x38020000, 0x38022000, 0x38024000, 0x38026000,
0x38028000, 0x3802a000, 0x3802c000, 0x3802e000, 0x38030000, 0x38032000,
0x38034000, 0x38036000, 0x38038000, 0x3803a000, 0x3803c000, 0x3803e000,
0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804a000,
0x3804c000, 0x3804e000, 0x38050000, 0x38052000, 0x38054000, 0x38056000,
0x38058000, 0x3805a000, 0x3805c000, 0x3805e000, 0x38060000, 0x38062000,
0x38064000, 0x38066000, 0x38068000, 0x3806a000, 0x3806c000, 0x3806e000,
0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807a000,
0x3807c000, 0x3807e000, 0x38080000, 0x38082000, 0x38084000, 0x38086000,
0x38088000, 0x3808a000, 0x3808c000, 0x3808e000, 0x38090000, 0x38092000,
0x38094000, 0x38096000, 0x38098000, 0x3809a000, 0x3809c000, 0x3809e000,
0x380a0000, 0x380a2000, 0x380a4000, 0x380a6000, 0x380a8000, 0x380aa000,
0x380ac000, 0x380ae000, 0x380b0000, 0x380b2000, 0x380b4000, 0x380b6000,
0x380b8000, 0x380ba000, 0x380bc000, 0x380be000, 0x380c0000, 0x380c2000,
0x380c4000, 0x380c6000, 0x380c8000, 0x380ca000, 0x380cc000, 0x380ce000,
0x380d0000, 0x380d2000, 0x380d4000, 0x380d6000, 0x380d8000, 0x380da000,
0x380dc000, 0x380de000, 0x380e0000, 0x380e2000, 0x380e4000, 0x380e6000,
0x380e8000, 0x380ea000, 0x380ec000, 0x380ee000, 0x380f0000, 0x380f2000,
0x380f4000, 0x380f6000, 0x380f8000, 0x380fa000, 0x380fc000, 0x380fe000,
0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810a000,
0x3810c000, 0x3810e000, 0x38110000, 0x38112000, 0x38114000, 0x38116000,
0x38118000, 0x3811a000, 0x3811c000, 0x3811e000, 0x38120000, 0x38122000,
0x38124000, 0x38126000, 0x38128000, 0x3812a000, 0x3812c000, 0x3812e000,
0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813a000,
0x3813c000, 0x3813e000, 0x38140000, 0x38142000, 0x38144000, 0x38146000,
0x38148000, 0x3814a000, 0x3814c000, 0x3814e000, 0x38150000, 0x38152000,
0x38154000, 0x38156000, 0x38158000, 0x3815a000, 0x3815c000, 0x3815e000,
0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816a000,
0x3816c000, 0x3816e000, 0x38170000, 0x38172000, 0x38174000, 0x38176000,
0x38178000, 0x3817a000, 0x3817c000, 0x3817e000, 0x38180000, 0x38182000,
0x38184000, 0x38186000, 0x38188000, 0x3818a000, 0x3818c000, 0x3818e000,
0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819a000,
0x3819c000, 0x3819e000, 0x381a0000, 0x381a2000, 0x381a4000, 0x381a6000,
0x381a8000, 0x381aa000, 0x381ac000, 0x381ae000, 0x381b0000, 0x381b2000,
0x381b4000, 0x381b6000, 0x381b8000, 0x381ba000, 0x381bc000, 0x381be000,
0x381c0000, 0x381c2000, 0x381c4000, 0x381c6000, 0x381c8000, 0x381ca000,
0x381cc000, 0x381ce000, 0x381d0000, 0x381d2000, 0x381d4000, 0x381d6000,
0x381d8000, 0x381da000, 0x381dc000, 0x381de000, 0x381e0000, 0x381e2000,
0x381e4000, 0x381e6000, 0x381e8000, 0x381ea000, 0x381ec000, 0x381ee000,
0x381f0000, 0x381f2000, 0x381f4000, 0x381f6000, 0x381f8000, 0x381fa000,
0x381fc000, 0x381fe000, 0x38200000, 0x38202000, 0x38204000, 0x38206000,
0x38208000, 0x3820a000, 0x3820c000, 0x3820e000, 0x38210000, 0x38212000,
0x38214000, 0x38216000, 0x38218000, 0x3821a000, 0x3821c000, 0x3821e000,
0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822a000,
0x3822c000, 0x3822e000, 0x38230000, 0x38232000, 0x38234000, 0x38236000,
0x38238000, 0x3823a000, 0x3823c000, 0x3823e000, 0x38240000, 0x38242000,
0x38244000, 0x38246000, 0x38248000, 0x3824a000, 0x3824c000, 0x3824e000,
0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825a000,
0x3825c000, 0x3825e000, 0x38260000, 0x38262000, 0x38264000, 0x38266000,
0x38268000, 0x3826a000, 0x3826c000, 0x3826e000, 0x38270000, 0x38272000,
0x38274000, 0x38276000, 0x38278000, 0x3827a000, 0x3827c000, 0x3827e000,
0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828a000,
0x3828c000, 0x3828e000, 0x38290000, 0x38292000, 0x38294000, 0x38296000,
0x38298000, 0x3829a000, 0x3829c000, 0x3829e000, 0x382a0000, 0x382a2000,
0x382a4000, 0x382a6000, 0x382a8000, 0x382aa000, 0x382ac000, 0x382ae000,
0x382b0000, 0x382b2000, 0x382b4000, 0x382b6000, 0x382b8000, 0x382ba000,
0x382bc000, 0x382be000, 0x382c0000, 0x382c2000, 0x382c4000, 0x382c6000,
0x382c8000, 0x382ca000, 0x382cc000, 0x382ce000, 0x382d0000, 0x382d2000,
0x382d4000, 0x382d6000, 0x382d8000, 0x382da000, 0x382dc000, 0x382de000,
0x382e0000, 0x382e2000, 0x382e4000, 0x382e6000, 0x382e8000, 0x382ea000,
0x382ec000, 0x382ee000, 0x382f0000, 0x382f2000, 0x382f4000, 0x382f6000,
0x382f8000, 0x382fa000, 0x382fc000, 0x382fe000, 0x38300000, 0x38302000,
0x38304000, 0x38306000, 0x38308000, 0x3830a000, 0x3830c000, 0x3830e000,
0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831a000,
0x3831c000, 0x3831e000, 0x38320000, 0x38322000, 0x38324000, 0x38326000,
0x38328000, 0x3832a000, 0x3832c000, 0x3832e000, 0x38330000, 0x38332000,
0x38334000, 0x38336000, 0x38338000, 0x3833a000, 0x3833c000, 0x3833e000,
0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834a000,
0x3834c000, 0x3834e000, 0x38350000, 0x38352000, 0x38354000, 0x38356000,
0x38358000, 0x3835a000, 0x3835c000, 0x3835e000, 0x38360000, 0x38362000,
0x38364000, 0x38366000, 0x38368000, 0x3836a000, 0x3836c000, 0x3836e000,
0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837a000,
0x3837c000, 0x3837e000, 0x38380000, 0x38382000, 0x38384000, 0x38386000,
0x38388000, 0x3838a000, 0x3838c000, 0x3838e000, 0x38390000, 0x38392000,
0x38394000, 0x38396000, 0x38398000, 0x3839a000, 0x3839c000, 0x3839e000,
0x383a0000, 0x383a2000, 0x383a4000, 0x383a6000, 0x383a8000, 0x383aa000,
0x383ac000, 0x383ae000, 0x383b0000, 0x383b2000, 0x383b4000, 0x383b6000,
0x383b8000, 0x383ba000, 0x383bc000, 0x383be000, 0x383c0000, 0x383c2000,
0x383c4000, 0x383c6000, 0x383c8000, 0x383ca000, 0x383cc000, 0x383ce000,
0x383d0000, 0x383d2000, 0x383d4000, 0x383d6000, 0x383d8000, 0x383da000,
0x383dc000, 0x383de000, 0x383e0000, 0x383e2000, 0x383e4000, 0x383e6000,
0x383e8000, 0x383ea000, 0x383ec000, 0x383ee000, 0x383f0000, 0x383f2000,
0x383f4000, 0x383f6000, 0x383f8000, 0x383fa000, 0x383fc000, 0x383fe000,
0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840a000,
0x3840c000, 0x3840e000, 0x38410000, 0x38412000, 0x38414000, 0x38416000,
0x38418000, 0x3841a000, 0x3841c000, 0x3841e000, 0x38420000, 0x38422000,
0x38424000, 0x38426000, 0x38428000, 0x3842a000, 0x3842c000, 0x3842e000,
0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843a000,
0x3843c000, 0x3843e000, 0x38440000, 0x38442000, 0x38444000, 0x38446000,
0x38448000, 0x3844a000, 0x3844c000, 0x3844e000, 0x38450000, 0x38452000,
0x38454000, 0x38456000, 0x38458000, 0x3845a000, 0x3845c000, 0x3845e000,
0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846a000,
0x3846c000, 0x3846e000, 0x38470000, 0x38472000, 0x38474000, 0x38476000,
0x38478000, 0x3847a000, 0x3847c000, 0x3847e000, 0x38480000, 0x38482000,
0x38484000, 0x38486000, 0x38488000, 0x3848a000, 0x3848c000, 0x3848e000,
0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849a000,
0x3849c000, 0x3849e000, 0x384a0000, 0x384a2000, 0x384a4000, 0x384a6000,
0x384a8000, 0x384aa000, 0x384ac000, 0x384ae000, 0x384b0000, 0x384b2000,
0x384b4000, 0x384b6000, 0x384b8000, 0x384ba000, 0x384bc000, 0x384be000,
0x384c0000, 0x384c2000, 0x384c4000, 0x384c6000, 0x384c8000, 0x384ca000,
0x384cc000, 0x384ce000, 0x384d0000, 0x384d2000, 0x384d4000, 0x384d6000,
0x384d8000, 0x384da000, 0x384dc000, 0x384de000, 0x384e0000, 0x384e2000,
0x384e4000, 0x384e6000, 0x384e8000, 0x384ea000, 0x384ec000, 0x384ee000,
0x384f0000, 0x384f2000, 0x384f4000, 0x384f6000, 0x384f8000, 0x384fa000,
0x384fc000, 0x384fe000, 0x38500000, 0x38502000, 0x38504000, 0x38506000,
0x38508000, 0x3850a000, 0x3850c000, 0x3850e000, 0x38510000, 0x38512000,
0x38514000, 0x38516000, 0x38518000, 0x3851a000, 0x3851c000, 0x3851e000,
0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852a000,
0x3852c000, 0x3852e000, 0x38530000, 0x38532000, 0x38534000, 0x38536000,
0x38538000, 0x3853a000, 0x3853c000, 0x3853e000, 0x38540000, 0x38542000,
0x38544000, 0x38546000, 0x38548000, 0x3854a000, 0x3854c000, 0x3854e000,
0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855a000,
0x3855c000, 0x3855e000, 0x38560000, 0x38562000, 0x38564000, 0x38566000,
0x38568000, 0x3856a000, 0x3856c000, 0x3856e000, 0x38570000, 0x38572000,
0x38574000, 0x38576000, 0x38578000, 0x3857a000, 0x3857c000, 0x3857e000,
0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858a000,
0x3858c000, 0x3858e000, 0x38590000, 0x38592000, 0x38594000, 0x38596000,
0x38598000, 0x3859a000, 0x3859c000, 0x3859e000, 0x385a0000, 0x385a2000,
0x385a4000, 0x385a6000, 0x385a8000, 0x385aa000, 0x385ac000, 0x385ae000,
0x385b0000, 0x385b2000, 0x385b4000, 0x385b6000, 0x385b8000, 0x385ba000,
0x385bc000, 0x385be000, 0x385c0000, 0x385c2000, 0x385c4000, 0x385c6000,
0x385c8000, 0x385ca000, 0x385cc000, 0x385ce000, 0x385d0000, 0x385d2000,
0x385d4000, 0x385d6000, 0x385d8000, 0x385da000, 0x385dc000, 0x385de000,
0x385e0000, 0x385e2000, 0x385e4000, 0x385e6000, 0x385e8000, 0x385ea000,
0x385ec000, 0x385ee000, 0x385f0000, 0x385f2000, 0x385f4000, 0x385f6000,
0x385f8000, 0x385fa000, 0x385fc000, 0x385fe000, 0x38600000, 0x38602000,
0x38604000, 0x38606000, 0x38608000, 0x3860a000, 0x3860c000, 0x3860e000,
0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861a000,
0x3861c000, 0x3861e000, 0x38620000, 0x38622000, 0x38624000, 0x38626000,
0x38628000, 0x3862a000, 0x3862c000, 0x3862e000, 0x38630000, 0x38632000,
0x38634000, 0x38636000, 0x38638000, 0x3863a000, 0x3863c000, 0x3863e000,
0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864a000,
0x3864c000, 0x3864e000, 0x38650000, 0x38652000, 0x38654000, 0x38656000,
0x38658000, 0x3865a000, 0x3865c000, 0x3865e000, 0x38660000, 0x38662000,
0x38664000, 0x38666000, 0x38668000, 0x3866a000, 0x3866c000, 0x3866e000,
0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867a000,
0x3867c000, 0x3867e000, 0x38680000, 0x38682000, 0x38684000, 0x38686000,
0x38688000, 0x3868a000, 0x3868c000, 0x3868e000, 0x38690000, 0x38692000,
0x38694000, 0x38696000, 0x38698000, 0x3869a000, 0x3869c000, 0x3869e000,
0x386a0000, 0x386a2000, 0x386a4000, 0x386a6000, 0x386a8000, 0x386aa000,
0x386ac000, 0x386ae000, 0x386b0000, 0x386b2000, 0x386b4000, 0x386b6000,
0x386b8000, 0x386ba000, 0x386bc000, 0x386be000, 0x386c0000, 0x386c2000,
0x386c4000, 0x386c6000, 0x386c8000, 0x386ca000, 0x386cc000, 0x386ce000,
0x386d0000, 0x386d2000, 0x386d4000, 0x386d6000, 0x386d8000, 0x386da000,
0x386dc000, 0x386de000, 0x386e0000, 0x386e2000, 0x386e4000, 0x386e6000,
0x386e8000, 0x386ea000, 0x386ec000, 0x386ee000, 0x386f0000, 0x386f2000,
0x386f4000, 0x386f6000, 0x386f8000, 0x386fa000, 0x386fc000, 0x386fe000,
0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870a000,
0x3870c000, 0x3870e000, 0x38710000, 0x38712000, 0x38714000, 0x38716000,
0x38718000, 0x3871a000, 0x3871c000, 0x3871e000, 0x38720000, 0x38722000,
0x38724000, 0x38726000, 0x38728000, 0x3872a000, 0x3872c000, 0x3872e000,
0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873a000,
0x3873c000, 0x3873e000, 0x38740000, 0x38742000, 0x38744000, 0x38746000,
0x38748000, 0x3874a000, 0x3874c000, 0x3874e000, 0x38750000, 0x38752000,
0x38754000, 0x38756000, 0x38758000, 0x3875a000, 0x3875c000, 0x3875e000,
0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876a000,
0x3876c000, 0x3876e000, 0x38770000, 0x38772000, 0x38774000, 0x38776000,
0x38778000, 0x3877a000, 0x3877c000, 0x3877e000, 0x38780000, 0x38782000,
0x38784000, 0x38786000, 0x38788000, 0x3878a000, 0x3878c000, 0x3878e000,
0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879a000,
0x3879c000, 0x3879e000, 0x387a0000, 0x387a2000, 0x387a4000, 0x387a6000,
0x387a8000, 0x387aa000, 0x387ac000, 0x387ae000, 0x387b0000, 0x387b2000,
0x387b4000, 0x387b6000, 0x387b8000, 0x387ba000, 0x387bc000, 0x387be000,
0x387c0000, 0x387c2000, 0x387c4000, 0x387c6000, 0x387c8000, 0x387ca000,
0x387cc000, 0x387ce000, 0x387d0000, 0x387d2000, 0x387d4000, 0x387d6000,
0x387d8000, 0x387da000, 0x387dc000, 0x387de000, 0x387e0000, 0x387e2000,
0x387e4000, 0x387e6000, 0x387e8000, 0x387ea000, 0x387ec000, 0x387ee000,
0x387f0000, 0x387f2000, 0x387f4000, 0x387f6000, 0x387f8000, 0x387fa000,
0x387fc000, 0x387fe000
};
static cmsUInt16Number Offset[64] = {
0x0000, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0000, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400
};
static cmsUInt32Number Exponent[64] = {
0x00000000, 0x00800000, 0x01000000, 0x01800000, 0x02000000, 0x02800000,
0x03000000, 0x03800000, 0x04000000, 0x04800000, 0x05000000, 0x05800000,
0x06000000, 0x06800000, 0x07000000, 0x07800000, 0x08000000, 0x08800000,
0x09000000, 0x09800000, 0x0a000000, 0x0a800000, 0x0b000000, 0x0b800000,
0x0c000000, 0x0c800000, 0x0d000000, 0x0d800000, 0x0e000000, 0x0e800000,
0x0f000000, 0x47800000, 0x80000000, 0x80800000, 0x81000000, 0x81800000,
0x82000000, 0x82800000, 0x83000000, 0x83800000, 0x84000000, 0x84800000,
0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000,
0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8a000000, 0x8a800000,
0x8b000000, 0x8b800000, 0x8c000000, 0x8c800000, 0x8d000000, 0x8d800000,
0x8e000000, 0x8e800000, 0x8f000000, 0xc7800000
};
static cmsUInt16Number Base[512] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040,
0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00,
0x2000, 0x2400, 0x2800, 0x2c00, 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x4400,
0x4800, 0x4c00, 0x5000, 0x5400, 0x5800, 0x5c00, 0x6000, 0x6400, 0x6800, 0x6c00,
0x7000, 0x7400, 0x7800, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00,
0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x7c00, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8001,
0x8002, 0x8004, 0x8008, 0x8010, 0x8020, 0x8040, 0x8080, 0x8100, 0x8200, 0x8400,
0x8800, 0x8c00, 0x9000, 0x9400, 0x9800, 0x9c00, 0xa000, 0xa400, 0xa800, 0xac00,
0xb000, 0xb400, 0xb800, 0xbc00, 0xc000, 0xc400, 0xc800, 0xcc00, 0xd000, 0xd400,
0xd800, 0xdc00, 0xe000, 0xe400, 0xe800, 0xec00, 0xf000, 0xf400, 0xf800, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00, 0xfc00,
0xfc00, 0xfc00
};
static cmsUInt8Number Shift[512] = {
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17,
0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0d, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13,
0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x0d
};
cmsFloat32Number _cmsHalf2Float(cmsUInt16Number h)
{
union {
cmsFloat32Number flt;
cmsUInt32Number num;
} out;
int n = h >> 10;
out.num = Mantissa[ (h & 0x3ff) + Offset[ n ] ] + Exponent[ n ];
return out.flt;
}
cmsUInt16Number _cmsFloat2Half(cmsFloat32Number flt)
{
union {
cmsFloat32Number flt;
cmsUInt32Number num;
} in;
cmsUInt32Number n, j;
in.flt = flt;
n = in.num;
j = (n >> 23) & 0x1ff;
return (cmsUInt16Number) ((cmsUInt32Number) Base[ j ] + (( n & 0x007fffff) >> Shift[ j ]));
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -56,9 +56,9 @@ static const cmsTagSignature PCS2DeviceFloat[] = {cmsSigBToD0Tag, // Percept
// Several resources for gray conversions.
static const cmsFloat64Number GrayInputMatrix[] = { (InpAdj*cmsD50X), (InpAdj*cmsD50Y), (InpAdj*cmsD50Z) };
static const cmsFloat64Number OneToThreeInputMatrix[] = { 1, 1, 1 };
static const cmsFloat64Number PickYMatrix[] = { 0, (OutpAdj*cmsD50Y), 0 };
static const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 };
static const cmsFloat64Number OneToThreeInputMatrix[] = { 1, 1, 1 };
static const cmsFloat64Number PickYMatrix[] = { 0, (OutpAdj*cmsD50Y), 0 };
static const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 };
// Get a media white point fixing some issues found in certain old profiles
cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile)
@@ -67,7 +67,7 @@ cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile)
_cmsAssert(Dest != NULL);
Tag = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
Tag = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
// If no wp, take D50
if (Tag == NULL) {
@@ -80,7 +80,7 @@ cmsBool _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile)
if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) {
*Dest = *cmsD50_XYZ();
return TRUE;
return TRUE;
}
}
@@ -100,7 +100,6 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag);
if (Tag != NULL) {
*Dest = *Tag;
return TRUE;
}
@@ -113,7 +112,7 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) {
cmsCIEXYZ* White = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
cmsCIEXYZ* White = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
if (White == NULL) {
@@ -121,7 +120,7 @@ cmsBool _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
return TRUE;
}
return _cmsAdaptationMatrix(Dest, NULL, cmsD50_XYZ(), White);
return _cmsAdaptationMatrix(Dest, NULL, White, cmsD50_XYZ());
}
}
@@ -141,7 +140,7 @@ cmsBool ReadICCMatrixRGB2XYZ(cmsMAT3* r, cmsHPROFILE hProfile)
PtrGreen = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigGreenColorantTag);
PtrBlue = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigBlueColorantTag);
if (PtrRed == NULL || PtrGreen == NULL || PtrBlue == NULL)
if (PtrRed == NULL || PtrGreen == NULL || PtrBlue == NULL)
return FALSE;
_cmsVEC3init(&r -> v[0], PtrRed -> X, PtrGreen -> X, PtrBlue -> X);
@@ -159,12 +158,13 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile)
cmsToneCurve *GrayTRC;
cmsPipeline* Lut;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag);
if (GrayTRC == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 1, 3);
if (Lut == NULL) return NULL;
if (Lut == NULL)
goto Error;
if (cmsGetPCS(hProfile) == cmsSigLabData) {
@@ -172,31 +172,38 @@ cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile)
cmsUInt16Number Zero[2] = { 0x8080, 0x8080 };
cmsToneCurve* EmptyTab;
cmsToneCurve* LabCurves[3];
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
if (EmptyTab == NULL) {
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
cmsPipelineFree(Lut);
return NULL;
}
if (EmptyTab == NULL)
goto Error;
LabCurves[0] = GrayTRC;
LabCurves[1] = EmptyTab;
LabCurves[2] = EmptyTab;
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL));
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, OneToThreeInputMatrix, NULL)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves))) {
cmsFreeToneCurve(EmptyTab);
goto Error;
}
cmsFreeToneCurve(EmptyTab);
}
else {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC));
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 1, GrayInputMatrix, NULL)))
goto Error;
}
return Lut;
Error:
cmsFreeToneCurve(GrayTRC);
cmsPipelineFree(Lut);
return NULL;
}
// RGB Matrix shaper
@@ -212,15 +219,15 @@ cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile)
if (!ReadICCMatrixRGB2XYZ(&Mat, hProfile)) return NULL;
// XYZ PCS in encoded in 1.15 format, and the matrix output comes in 0..0xffff range, so
// we need to adjust the output by a factor of (0x10000/0xffff) to put data in
// we need to adjust the output by a factor of (0x10000/0xffff) to put data in
// a 1.16 range, and then a >> 1 to obtain 1.15. The total factor is (65536.0)/(65535.0*2)
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
Mat.v[i].n[j] *= InpAdj;
Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag);
Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag);
@@ -230,15 +237,76 @@ cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile)
Lut = cmsPipelineAlloc(ContextID, 3, 3);
if (Lut != NULL) {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes));
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL)))
goto Error;
// Note that it is certainly possible a single profile would have a LUT based
// tag for output working in lab and a matrix-shaper for the fallback cases.
// This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) {
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocXYZ2Lab(ContextID)))
goto Error;
}
}
return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
}
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
if (Lut == NULL) return NULL;
// input and output of transform are in lcms 0..1 encoding. If XYZ or Lab spaces are used,
// these need to be normalized into the appropriate ranges (Lab = 100,0,0, XYZ=1.0,1.0,1.0)
if ( spc == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
}
else if (spc == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
}
if ( PCS == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
}
else if( PCS == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
}
return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
}
// Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc
// is adjusted here in order to create a LUT that takes care of all those details
// is adjusted here in order to create a LUT that takes care of all those details.
// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT
cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
{
cmsTagTypeSignature OriginalType;
@@ -246,57 +314,95 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
cmsTagSignature tagFloat = Device2PCSFloat[Intent];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// On named color, take the appropiate tag
if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
// Floating point LUT are always V4, so no adjustment is required
return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
}
cmsPipeline* Lut;
cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag);
// Revert to perceptual if no tag is found
if (!cmsIsTag(hProfile, tag16)) {
tag16 = Device2PCS16[0];
}
if (nc == NULL) return NULL;
if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
Lut = cmsPipelineAlloc(ContextID, 0, 0);
if (Lut == NULL) {
cmsFreeNamedColorList(nc);
return NULL;
}
// Check profile version and LUT type. Do the necessary adjustments if needed
// First read the tag
cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
if (Lut == NULL) return NULL;
// After reading it, we have now info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
// The profile owns the Lut, so we need to copy it
Lut = cmsPipelineDup(Lut);
// We need to adjust data only for Lab16 on output
if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
return Lut;
// Add a matrix for conversion V2 to V4 Lab PCS
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) {
cmsPipelineFree(Lut);
return NULL;
}
return Lut;
}
}
// This is an attempt to reuse this funtion to retrieve the matrix-shaper as pipeline no
// matter other LUT are present and have precedence. Intent = -1 means just this.
if (Intent != -1) {
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4, but the encoding range is no
// longer 0..1.0, so we need to add an stage depending on the color space
return _cmsReadFloatInputTag(hProfile, tagFloat);
}
// Revert to perceptual if no tag is found
if (!cmsIsTag(hProfile, tag16)) {
tag16 = Device2PCS16[0];
}
if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
// Check profile version and LUT type. Do the necessary adjustments if needed
// First read the tag
cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
if (Lut == NULL) return NULL;
// After reading it, we have now info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
// The profile owns the Lut, so we need to copy it
Lut = cmsPipelineDup(Lut);
// We need to adjust data only for Lab16 on output
if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
return Lut;
// If the input is Lab, add also a conversion at the begin
if (cmsGetColorSpace(hProfile) == cmsSigLabData &&
!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
// Add a matrix for conversion V2 to V4 Lab PCS
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
}
}
// Lut was not found, try to create a matrix-shaper
// Check if this is a grayscale profile.
if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
// if so, build appropiate conversion tables.
// if so, build appropiate conversion tables.
// The tables are the PCS iluminant, scaled across GrayTRC
return BuildGrayInputMatrixPipeline(hProfile);
return BuildGrayInputMatrixPipeline(hProfile);
}
// Not gray, create a normal matrix-shaper
// Not gray, create a normal matrix-shaper
return BuildRGBInputMatrixShaper(hProfile);
}
// ---------------------------------------------------------------------------------------------------------------
// Gray output pipeline.
// Gray output pipeline.
// XYZ -> Gray or Lab -> Gray. Since we only know the GrayTRC, we need to do some assumptions. Gray component will be
// given by Y on XYZ PCS and by L* on Lab PCS, Both across inverse TRC curve.
// The complete pipeline on XYZ is Matrix[3:1] -> Tone curve and in Lab Matrix[3:1] -> Tone Curve as well.
@@ -308,7 +414,7 @@ cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile)
cmsPipeline* Lut;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag);
GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag);
if (GrayTRC == NULL) return NULL;
RevGrayTRC = cmsReverseToneCurve(GrayTRC);
@@ -322,21 +428,27 @@ cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile)
if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL)))
goto Error;
}
else {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickYMatrix, NULL)))
goto Error;
}
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC));
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC)))
goto Error;
cmsFreeToneCurve(RevGrayTRC);
return Lut;
Error:
cmsFreeToneCurve(RevGrayTRC);
cmsPipelineFree(Lut);
return NULL;
}
static
cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
{
@@ -353,14 +465,14 @@ cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
return NULL;
// XYZ PCS in encoded in 1.15 format, and the matrix input should come in 0..0xffff range, so
// we need to adjust the input by a << 1 to obtain a 1.16 fixed and then by a factor of
// we need to adjust the input by a << 1 to obtain a 1.16 fixed and then by a factor of
// (0xffff/0x10000) to put data in 0..0xffff range. Total factor is (2.0*65535.0)/65536.0;
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
Inv.v[i].n[j] *= OutpAdj;
Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag);
Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag);
@@ -371,19 +483,33 @@ cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
InvShapes[1] = cmsReverseToneCurve(Shapes[1]);
InvShapes[2] = cmsReverseToneCurve(Shapes[2]);
if (!InvShapes[0] || !InvShapes[1] || !InvShapes[2]) {
if (!InvShapes[0] || !InvShapes[1] || !InvShapes[2]) {
return NULL;
}
Lut = cmsPipelineAlloc(ContextID, 3, 3);
if (Lut != NULL) {
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL));
cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes));
// Note that it is certainly possible a single profile would have a LUT based
// tag for output working in lab and a matrix-shaper for the fallback cases.
// This is not allowed by the spec, but this code is tolerant to those cases
if (cmsGetPCS(hProfile) == cmsSigLabData) {
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLab2XYZ(ContextID)))
goto Error;
}
if (!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes)))
goto Error;
}
cmsFreeToneCurveTriple(InvShapes);
return Lut;
Error:
cmsFreeToneCurveTriple(InvShapes);
cmsPipelineFree(Lut);
return NULL;
}
@@ -402,11 +528,56 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut)
_cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data;
CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR;
_cmsSetInterpolationRoutine(CLUT ->Params);
_cmsSetInterpolationRoutine(Lut->ContextID, CLUT ->Params);
}
}
}
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
cmsColorSpaceSignature dataSpace = cmsGetColorSpace(hProfile);
if (Lut == NULL) return NULL;
// If PCS is Lab or XYZ, the floating point tag is accepting data in the space encoding,
// and since the formatter has already accomodated to 0..1.0, we should undo this change
if ( PCS == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
}
else
if (PCS == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
}
// the output can be Lab or XYZ, in which case normalisation is needed on the end of the pipeline
if ( dataSpace == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
}
else if (dataSpace == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
}
return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
}
// Create an output MPE LUT from agiven profile. Version mismatches are handled here
cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
{
@@ -415,63 +586,118 @@ cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
cmsTagSignature tagFloat = PCS2DeviceFloat[Intent];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4, so no adjustment is required
return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
}
if (Intent != -1) {
// Revert to perceptual if no tag is found
if (!cmsIsTag(hProfile, tag16)) {
tag16 = PCS2Device16[0];
}
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
// Floating point LUT are always V4
return _cmsReadFloatOutputTag(hProfile, tagFloat);
}
// Check profile version and LUT type. Do the necessary adjustments if needed
// Revert to perceptual if no tag is found
if (!cmsIsTag(hProfile, tag16)) {
tag16 = PCS2Device16[0];
}
// First read the tag
cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
if (Lut == NULL) return NULL;
if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
// After reading it, we have info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
// Check profile version and LUT type. Do the necessary adjustments if needed
// The profile owns the Lut, so we need to copy it
Lut = cmsPipelineDup(Lut);
if (Lut == NULL) return NULL;
// First read the tag
cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
if (Lut == NULL) return NULL;
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
if (cmsGetPCS(hProfile) == cmsSigLabData)
ChangeInterpolationToTrilinear(Lut);
// After reading it, we have info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
// The profile owns the Lut, so we need to copy it
Lut = cmsPipelineDup(Lut);
if (Lut == NULL) return NULL;
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
if (cmsGetPCS(hProfile) == cmsSigLabData)
ChangeInterpolationToTrilinear(Lut);
// We need to adjust data only for Lab and Lut16 type
if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
return Lut;
// Add a matrix for conversion V4 to V2 Lab PCS
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
// If the output is Lab, add also a conversion at the end
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
// We need to adjust data only for Lab and Lut16 type
if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
return Lut;
// Add a matrix for conversion V4 to V2 Lab PCS
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
return Lut;
}
Error:
cmsPipelineFree(Lut);
return NULL;
}
}
// Lut not found, try to create a matrix-shaper
// Check if this is a grayscale profile.
if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
// if so, build appropiate conversion tables.
// The tables are the PCS iluminant, scaled across GrayTRC
return BuildGrayOutputPipeline(hProfile);
// if so, build appropiate conversion tables.
// The tables are the PCS iluminant, scaled across GrayTRC
return BuildGrayOutputPipeline(hProfile);
}
// Not gray, create a normal matrix-shaper
// Not gray, create a normal matrix-shaper, which only operates in XYZ space
return BuildRGBOutputMatrixShaper(hProfile);
}
// ---------------------------------------------------------------------------------------------------------------
// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
// Read the AToD0 tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
if (Lut == NULL) return NULL;
if (spc == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToLabFloat(ContextID)))
goto Error;
}
else
if (spc == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageNormalizeToXyzFloat(ContextID)))
goto Error;
}
if (PCS == cmsSigLabData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
goto Error;
}
else
if (PCS == cmsSigXYZData)
{
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
goto Error;
}
return Lut;
Error:
cmsPipelineFree(Lut);
return NULL;
}
// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
// tag name here may default to AToB0
cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
{
@@ -481,22 +707,48 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
cmsTagSignature tagFloat = Device2PCSFloat[Intent];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
// On named color, take the appropiate tag
if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag);
if (nc == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 0, 0);
if (Lut == NULL)
goto Error;
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, FALSE)))
goto Error;
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error;
return Lut;
Error:
cmsPipelineFree(Lut);
cmsFreeNamedColorList(nc);
return NULL;
}
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4, no adjustment is required
return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
// Floating point LUT are always V
return _cmsReadFloatDevicelinkTag(hProfile, tagFloat);
}
tagFloat = Device2PCSFloat[0];
if (cmsIsTag(hProfile, tagFloat)) {
if (cmsIsTag(hProfile, tagFloat)) {
return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
}
if (!cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
tag16 = Device2PCS16[0];
if (!cmsIsTag(hProfile, tag16)) return NULL;
if (!cmsIsTag(hProfile, tag16)) return NULL;
}
// Check profile version and LUT type. Do the necessary adjustments if needed
@@ -509,41 +761,45 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
Lut = cmsPipelineDup(Lut);
if (Lut == NULL) return NULL;
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
if (cmsGetColorSpace(hProfile) == cmsSigLabData)
ChangeInterpolationToTrilinear(Lut);
// Now it is time for a controversial stuff. I found that for 3D LUTS using
// Lab used as indexer space, trilinear interpolation should be used
if (cmsGetPCS(hProfile) == cmsSigLabData)
ChangeInterpolationToTrilinear(Lut);
// After reading it, we have info about the original type
OriginalType = _cmsGetTagTrueType(hProfile, tag16);
// We need to adjust data for Lab16 on output
if (OriginalType != cmsSigLut16Type) return Lut;
// Here it is possible to get Lab on both sides
if (cmsGetPCS(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
if(!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error2;
}
if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
if (cmsGetPCS(hProfile) == cmsSigLabData) {
if(!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID)))
goto Error2;
}
return Lut;
Error2:
cmsPipelineFree(Lut);
return NULL;
}
// ---------------------------------------------------------------------------------------------------------------
// Returns TRUE if the profile is implemented as matrix-shaper
cmsBool CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile)
{
{
switch (cmsGetColorSpace(hProfile)) {
case cmsSigGrayData:
return cmsIsTag(hProfile, cmsSigGrayTRCTag);
case cmsSigRgbData:
@@ -563,7 +819,7 @@ cmsBool CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile)
// Returns TRUE if the intent is implemented as CLUT
cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number UsedDirection)
{
{
const cmsTagSignature* TagTable;
// For devicelinks, the supported intent is that one stated in the header
@@ -574,10 +830,10 @@ cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUI
switch (UsedDirection) {
case LCMS_USED_AS_INPUT: TagTable = Device2PCS16; break;
case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device16; break;
case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device16; break;
// For proofing, we need rel. colorimetric in output. Let's do some recursion
case LCMS_USED_AS_PROOF:
case LCMS_USED_AS_PROOF:
return cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) &&
cmsIsIntentSupported(hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_OUTPUT);
@@ -611,7 +867,6 @@ cmsBool CMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
// Read both, profile sequence description and profile sequence id if present. Then combine both to
// create qa unique structure holding both. Shame on ICC to store things in such complicated way.
cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile)
{
cmsSEQ* ProfileSeq;
@@ -621,7 +876,7 @@ cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile)
// Take profile sequence description first
ProfileSeq = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceDescTag);
// Take profile sequence ID
ProfileId = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceIdTag);
@@ -630,18 +885,19 @@ cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile)
if (ProfileSeq == NULL) return cmsDupProfileSequenceDescription(ProfileId);
if (ProfileId == NULL) return cmsDupProfileSequenceDescription(ProfileSeq);
// We have to mix both together. For that they must agree
// We have to mix both together. For that they must agree
if (ProfileSeq ->n != ProfileId ->n) return cmsDupProfileSequenceDescription(ProfileSeq);
NewSeq = cmsDupProfileSequenceDescription(ProfileSeq);
// Ok, proceed to the mixing
for (i=0; i < ProfileSeq ->n; i++) {
memmove(&NewSeq ->seq[i].ProfileID, &ProfileId ->seq[i].ProfileID, sizeof(cmsProfileID));
NewSeq ->seq[i].Description = cmsMLUdup(ProfileId ->seq[i].Description);
}
// Ok, proceed to the mixing
if (NewSeq != NULL) {
for (i=0; i < ProfileSeq ->n; i++) {
memmove(&NewSeq ->seq[i].ProfileID, &ProfileId ->seq[i].ProfileID, sizeof(cmsProfileID));
NewSeq ->seq[i].Description = cmsMLUdup(ProfileId ->seq[i].Description);
}
}
return NewSeq;
}
@@ -682,22 +938,22 @@ cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfil
cmsPSEQDESC* ps = &seq ->seq[i];
cmsHPROFILE h = hProfiles[i];
cmsTechnologySignature* techpt;
cmsGetHeaderAttributes(h, &ps ->attributes);
cmsGetHeaderProfileID(h, ps ->ProfileID.ID8);
cmsGetHeaderProfileID(h, ps ->ProfileID.ID8);
ps ->deviceMfg = cmsGetHeaderManufacturer(h);
ps ->deviceModel = cmsGetHeaderModel(h);
techpt = (cmsTechnologySignature*) cmsReadTag(h, cmsSigTechnologyTag);
if (techpt == NULL)
ps ->technology = (cmsTechnologySignature) 0;
else
ps ->technology = *techpt;
ps ->Manufacturer = GetMLUFromProfile(h, cmsSigDeviceMfgDescTag);
ps ->Model = GetMLUFromProfile(h, cmsSigDeviceModelDescTag);
ps ->Model = GetMLUFromProfile(h, cmsSigDeviceModelDescTag);
ps ->Description = GetMLUFromProfile(h, cmsSigProfileDescriptionTag);
}
return seq;
@@ -714,7 +970,7 @@ const cmsMLU* GetInfo(cmsHPROFILE hProfile, cmsInfoType Info)
switch (Info) {
case cmsInfoDescription:
sig = cmsSigProfileDescriptionTag;
sig = cmsSigProfileDescriptionTag;
break;
case cmsInfoManufacturer:
@@ -738,8 +994,8 @@ const cmsMLU* GetInfo(cmsHPROFILE hProfile, cmsInfoType Info)
cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info,
const char LanguageCode[3], const char CountryCode[3],
cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info,
const char LanguageCode[3], const char CountryCode[3],
wchar_t* Buffer, cmsUInt32Number BufferSize)
{
const cmsMLU* mlu = GetInfo(hProfile, Info);
@@ -749,8 +1005,8 @@ cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType In
}
cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info,
const char LanguageCode[3], const char CountryCode[3],
cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info,
const char LanguageCode[3], const char CountryCode[3],
char* Buffer, cmsUInt32Number BufferSize)
{
const cmsMLU* mlu = GetInfo(hProfile, Info);

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -42,7 +42,7 @@ void byteReverse(cmsUInt8Number * buf, cmsUInt32Number longs)
}
#else
#define byteReverse(buf, len)
#define byteReverse(buf, len)
#endif
@@ -66,7 +66,7 @@ typedef struct {
static
void MD5_Transform(cmsUInt32Number buf[4], cmsUInt32Number in[16])
{
register cmsUInt32Number a, b, c, d;
@@ -176,14 +176,14 @@ void MD5add(cmsHANDLE Handle, cmsUInt8Number* buf, cmsUInt32Number len)
{
_cmsMD5* ctx = (_cmsMD5*) Handle;
cmsUInt32Number t;
t = ctx->bits[0];
if ((ctx->bits[0] = t + (len << 3)) < t)
ctx->bits[1]++;
ctx->bits[1]++;
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f;
t = (t >> 3) & 0x3f;
if (t) {
@@ -265,15 +265,15 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
cmsUInt8Number* Mem = NULL;
cmsHANDLE MD5 = NULL;
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
_cmsICCPROFILE Keep;
_cmsICCPROFILE Keep;
_cmsAssert(hProfile != NULL);
_cmsAssert(hProfile != NULL);
ContextID = cmsGetProfileContextID(hProfile);
// Save a copy of the profile header
memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
// Set RI, attributes and ID
memset(&Icc ->attributes, 0, sizeof(Icc ->attributes));
Icc ->RenderingIntent = 0;
@@ -288,7 +288,7 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
// Save to temporary storage
if (!cmsSaveProfileToMem(hProfile, Mem, &BytesNeeded)) goto Error;
// Create MD5 object
MD5 = MD5alloc(ContextID);
if (MD5 == NULL) goto Error;
@@ -298,7 +298,7 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
// Temp storage is no longer needed
_cmsFree(ContextID, Mem);
// Restore header
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
@@ -309,7 +309,7 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
Error:
// Free resources as something went wrong
if (MD5 != NULL) _cmsFree(ContextID, MD5);
// "MD5" cannot be other than NULL here, so no need to free it
if (Mem != NULL) _cmsFree(ContextID, Mem);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
return FALSE;

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -30,7 +30,7 @@
#define DSWAP(x, y) {cmsFloat64Number tmp = (x); (x)=(y); (y)=tmp;}
// Initiate a vector
// Initiate a vector
void CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, cmsFloat64Number z)
{
r -> n[VX] = x;
@@ -60,7 +60,7 @@ cmsFloat64Number CMSEXPORT _cmsVEC3dot(const cmsVEC3* u, const cmsVEC3* v)
return u->n[VX] * v->n[VX] + u->n[VY] * v->n[VY] + u->n[VZ] * v->n[VZ];
}
// Euclidean length
// Euclidean length
cmsFloat64Number CMSEXPORT _cmsVEC3length(const cmsVEC3* a)
{
return sqrt(a ->n[VX] * a ->n[VX] +
@@ -97,16 +97,16 @@ cmsBool CloseEnough(cmsFloat64Number a, cmsFloat64Number b)
cmsBool CMSEXPORT _cmsMAT3isIdentity(const cmsMAT3* a)
{
cmsMAT3 Identity;
int i, j;
cmsMAT3 Identity;
int i, j;
_cmsMAT3identity(&Identity);
_cmsMAT3identity(&Identity);
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
if (!CloseEnough(a ->v[i].n[j], Identity.v[i].n[j])) return FALSE;
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
if (!CloseEnough(a ->v[i].n[j], Identity.v[i].n[j])) return FALSE;
return TRUE;
return TRUE;
}

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2012 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -32,81 +32,81 @@
// Allocates an empty multi localizad unicode object
cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems)
{
cmsMLU* mlu;
cmsMLU* mlu;
// nItems should be positive if given
if (nItems <= 0) nItems = 2;
// nItems should be positive if given
if (nItems <= 0) nItems = 2;
// Create the container
mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU));
if (mlu == NULL) return NULL;
// Create the container
mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU));
if (mlu == NULL) return NULL;
mlu ->ContextID = ContextID;
mlu ->ContextID = ContextID;
// Create entry array
mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry));
if (mlu ->Entries == NULL) {
_cmsFree(ContextID, mlu);
return NULL;
}
// Create entry array
mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry));
if (mlu ->Entries == NULL) {
_cmsFree(ContextID, mlu);
return NULL;
}
// Ok, keep indexes up to date
mlu ->AllocatedEntries = nItems;
mlu ->UsedEntries = 0;
// Ok, keep indexes up to date
mlu ->AllocatedEntries = nItems;
mlu ->UsedEntries = 0;
return mlu;
return mlu;
}
// Grows a mempool table for a MLU. Each time this function is called, mempool size is multiplied times two.
// Grows a mempool table for a MLU. Each time this function is called, mempool size is multiplied times two.
static
cmsBool GrowMLUpool(cmsMLU* mlu)
{
cmsUInt32Number size;
void *NewPtr;
cmsUInt32Number size;
void *NewPtr;
// Sanity check
if (mlu == NULL) return FALSE;
// Sanity check
if (mlu == NULL) return FALSE;
if (mlu ->PoolSize == 0)
size = 256;
else
size = mlu ->PoolSize * 2;
if (mlu ->PoolSize == 0)
size = 256;
else
size = mlu ->PoolSize * 2;
// Check for overflow
if (size < mlu ->PoolSize) return FALSE;
// Check for overflow
if (size < mlu ->PoolSize) return FALSE;
// Reallocate the pool
NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
if (NewPtr == NULL) return FALSE;
// Reallocate the pool
NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
if (NewPtr == NULL) return FALSE;
mlu ->MemPool = NewPtr;
mlu ->PoolSize = size;
mlu ->MemPool = NewPtr;
mlu ->PoolSize = size;
return TRUE;
return TRUE;
}
// Grows a ntry table for a MLU. Each time this function is called, table size is multiplied times two.
// Grows a entry table for a MLU. Each time this function is called, table size is multiplied times two.
static
cmsBool GrowMLUtable(cmsMLU* mlu)
{
int AllocatedEntries;
_cmsMLUentry *NewPtr;
// Sanity check
if (mlu == NULL) return FALSE;
// Sanity check
if (mlu == NULL) return FALSE;
AllocatedEntries = mlu ->AllocatedEntries * 2;
// Check for overflow
if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
// Check for overflow
if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
// Reallocate the memory
// Reallocate the memory
NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry));
if (NewPtr == NULL) return FALSE;
mlu ->Entries = NewPtr;
mlu ->AllocatedEntries = AllocatedEntries;
@@ -114,37 +114,37 @@ cmsBool GrowMLUtable(cmsMLU* mlu)
}
// Search for a specific entry in the structure. Language and Country are used.
// Search for a specific entry in the structure. Language and Country are used.
static
int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
{
int i;
// Sanity check
if (mlu == NULL) return -1;
// Iterate whole table
// Sanity check
if (mlu == NULL) return -1;
// Iterate whole table
for (i=0; i < mlu ->UsedEntries; i++) {
if (mlu ->Entries[i].Country == CountryCode &&
if (mlu ->Entries[i].Country == CountryCode &&
mlu ->Entries[i].Language == LanguageCode) return i;
}
// Not found
// Not found
return -1;
}
// Add a block of characters to the intended MLU. Language and country are specified.
// Add a block of characters to the intended MLU. Language and country are specified.
// Only one entry for Language/country pair is allowed.
static
cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
{
cmsUInt32Number Offset;
cmsUInt8Number* Ptr;
// Sanity check
if (mlu == NULL) return FALSE;
// Sanity check
if (mlu == NULL) return FALSE;
// Is there any room available?
if (mlu ->UsedEntries >= mlu ->AllocatedEntries) {
@@ -155,20 +155,20 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
if (SearchMLUEntry(mlu, LanguageCode, CountryCode) >= 0) return FALSE; // Only one is allowed!
// Check for size
while ((mlu ->PoolSize - mlu ->PoolUsed) < size) {
while ((mlu ->PoolSize - mlu ->PoolUsed) < size) {
if (!GrowMLUpool(mlu)) return FALSE;
}
}
Offset = mlu ->PoolUsed;
Ptr = (cmsUInt8Number*) mlu ->MemPool;
if (Ptr == NULL) return FALSE;
// Set the entry
Ptr = (cmsUInt8Number*) mlu ->MemPool;
if (Ptr == NULL) return FALSE;
// Set the entry
memmove(Ptr + Offset, Block, size);
mlu ->PoolUsed += size;
mlu ->Entries[mlu ->UsedEntries].StrW = Offset;
mlu ->Entries[mlu ->UsedEntries].Len = size;
mlu ->Entries[mlu ->UsedEntries].Country = CountryCode;
@@ -179,7 +179,7 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
}
// Add an ASCII entry.
// Add an ASCII entry.
cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
{
cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1;
@@ -195,21 +195,21 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const
for (i=0; i < len; i++)
WStr[i] = (wchar_t) ASCIIString[i];
rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry);
_cmsFree(mlu ->ContextID, WStr);
return rc;
}
// We don't need any wcs support library
static
static
cmsUInt32Number mywcslen(const wchar_t *s)
{
const wchar_t *p;
p = s;
p = s;
while (*p)
p++;
@@ -223,9 +223,9 @@ cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country);
cmsUInt32Number len;
if (mlu == NULL) return FALSE;
if (WideString == NULL) return FALSE;
if (WideString == NULL) return FALSE;
len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t);
return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
@@ -234,73 +234,73 @@ cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
// Duplicating a MLU is as easy as copying all members
cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu)
{
cmsMLU* NewMlu = NULL;
cmsMLU* NewMlu = NULL;
// Duplicating a NULL obtains a NULL
if (mlu == NULL) return NULL;
// Duplicating a NULL obtains a NULL
if (mlu == NULL) return NULL;
NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
if (NewMlu == NULL) return NULL;
NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
if (NewMlu == NULL) return NULL;
// Should never happen
if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
goto Error;
// Should never happen
if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
goto Error;
// Sanitize...
if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
// Sanitize...
if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry));
NewMlu ->UsedEntries = mlu ->UsedEntries;
memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry));
NewMlu ->UsedEntries = mlu ->UsedEntries;
// The MLU may be empty
if (mlu ->PoolUsed == 0) {
NewMlu ->MemPool = NULL;
}
else {
// It is not empty
NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed);
if (NewMlu ->MemPool == NULL) goto Error;
}
// The MLU may be empty
if (mlu ->PoolUsed == 0) {
NewMlu ->MemPool = NULL;
}
else {
// It is not empty
NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed);
if (NewMlu ->MemPool == NULL) goto Error;
}
NewMlu ->PoolSize = mlu ->PoolUsed;
NewMlu ->PoolSize = mlu ->PoolUsed;
if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error;
if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error;
memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed);
NewMlu ->PoolUsed = mlu ->PoolUsed;
memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed);
NewMlu ->PoolUsed = mlu ->PoolUsed;
return NewMlu;
return NewMlu;
Error:
if (NewMlu != NULL) cmsMLUfree(NewMlu);
return NULL;
if (NewMlu != NULL) cmsMLUfree(NewMlu);
return NULL;
}
// Free any used memory
void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
{
if (mlu) {
if (mlu) {
if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
_cmsFree(mlu ->ContextID, mlu);
}
_cmsFree(mlu ->ContextID, mlu);
}
}
// The algorithm first searches for an exact match of country and language, if not found it uses
// The algorithm first searches for an exact match of country and language, if not found it uses
// the Language. If none is found, first entry is used instead.
static
const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
cmsUInt32Number *len,
cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
cmsUInt32Number *len,
cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
{
int i;
int Best = -1;
_cmsMLUentry* v;
_cmsMLUentry* v;
if (mlu == NULL) return NULL;
@@ -316,12 +316,12 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
if (v -> Country == CountryCode) {
if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (len != NULL) *len = v ->Len;
return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v -> StrW); // Found exact match
return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v -> StrW); // Found exact match
}
}
}
@@ -330,30 +330,30 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
if (Best == -1)
Best = 0;
v = mlu ->Entries + Best;
v = mlu ->Entries + Best;
if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (len != NULL) *len = v ->Len;
return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
}
// Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len
cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
char* Buffer, cmsUInt32Number BufferSize)
cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
char* Buffer, cmsUInt32Number BufferSize)
{
const wchar_t *Wide;
cmsUInt32Number StrLen = 0;
cmsUInt32Number ASCIIlen, i;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
// Sanitize
// Sanitize
if (mlu == NULL) return 0;
// Get WideChar
@@ -373,7 +373,7 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
ASCIIlen = BufferSize - 1;
// Precess each character
for (i=0; i < ASCIIlen; i++) {
for (i=0; i < ASCIIlen; i++) {
if (Wide[i] == 0)
Buffer[i] = 0;
@@ -381,28 +381,28 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
Buffer[i] = (char) Wide[i];
}
// We put a termination "\0"
// We put a termination "\0"
Buffer[ASCIIlen] = 0;
return ASCIIlen + 1;
}
// Obtain a wide representation of the MLU, on depending on current locale settings
cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
wchar_t* Buffer, cmsUInt32Number BufferSize)
// Obtain a wide representation of the MLU, on depending on current locale settings
cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
wchar_t* Buffer, cmsUInt32Number BufferSize)
{
const wchar_t *Wide;
cmsUInt32Number StrLen = 0;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
// Sanitize
// Sanitize
if (mlu == NULL) return 0;
Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
if (Wide == NULL) return 0;
// Maybe we want only to know the len?
if (Buffer == NULL) return StrLen + sizeof(wchar_t);
@@ -414,35 +414,64 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
StrLen = BufferSize - + sizeof(wchar_t);
memmove(Buffer, Wide, StrLen);
Buffer[StrLen / sizeof(wchar_t)] = 0;
Buffer[StrLen / sizeof(wchar_t)] = 0;
return StrLen + sizeof(wchar_t);
}
// Get also the language and country
CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
char ObtainedLanguage[3], char ObtainedCountry[3])
CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
char ObtainedLanguage[3], char ObtainedCountry[3])
{
const wchar_t *Wide;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number ObtLang, ObtCode;
const wchar_t *Wide;
// Sanitize
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number ObtLang, ObtCode;
// Sanitize
if (mlu == NULL) return FALSE;
Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode);
if (Wide == NULL) return FALSE;
// Get used language and code
*(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
*(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
if (Wide == NULL) return FALSE;
ObtainedLanguage[2] = ObtainedCountry[2] = 0;
return TRUE;
// Get used language and code
*(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
*(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
ObtainedLanguage[2] = ObtainedCountry[2] = 0;
return TRUE;
}
// Get the number of translations in the MLU object
cmsUInt32Number CMSEXPORT cmsMLUtranslationsCount(const cmsMLU* mlu)
{
if (mlu == NULL) return 0;
return mlu->UsedEntries;
}
// Get the language and country codes for a specific MLU index
cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
cmsUInt32Number idx,
char LanguageCode[3],
char CountryCode[3])
{
_cmsMLUentry *entry;
if (mlu == NULL) return FALSE;
if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
entry = &mlu->Entries[idx];
*(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
*(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country);
return TRUE;
}
@@ -451,7 +480,7 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
// Grow the list to keep at least NumElements
static
cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
{
{
cmsUInt32Number size;
_cmsNAMEDCOLOR * NewPtr;
@@ -466,9 +495,9 @@ cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
if (size > 1024*100) return FALSE;
NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR));
if (NewPtr == NULL)
if (NewPtr == NULL)
return FALSE;
v ->List = NewPtr;
v ->Allocated = size;
return TRUE;
@@ -478,9 +507,9 @@ cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUInt32Number n, cmsUInt32Number ColorantCount, const char* Prefix, const char* Suffix)
{
cmsNAMEDCOLORLIST* v = (cmsNAMEDCOLORLIST*) _cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST));
if (v == NULL) return NULL;
v ->List = NULL;
v ->nColors = 0;
v ->ContextID = ContextID;
@@ -488,8 +517,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
while (v -> Allocated < n)
GrowNamedColorList(v);
strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix));
strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix));
strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
v->Prefix[32] = v->Suffix[32] = 0;
v -> ColorantCount = ColorantCount;
return v;
@@ -497,15 +528,16 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
// Free a list
void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v)
{
{
if (v == NULL) return;
if (v ->List) _cmsFree(v ->ContextID, v ->List);
if (v) _cmsFree(v ->ContextID, v);
}
_cmsFree(v ->ContextID, v);
}
cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
{
cmsNAMEDCOLORLIST* NewNC;
if (v == NULL) return NULL;
NewNC= cmsAllocNamedColorList(v ->ContextID, v -> nColors, v ->ColorantCount, v ->Prefix, v ->Suffix);
@@ -525,10 +557,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
// Append a color to a list. List pointer may change if reallocated
cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
const char* Name,
cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
const char* Name,
cmsUInt16Number PCS[3], cmsUInt16Number Colorant[cmsMAXCHANNELS])
{
{
cmsUInt32Number i;
if (NamedColorList == NULL) return FALSE;
@@ -543,9 +575,12 @@ cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
for (i=0; i < 3; i++)
NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? 0 : PCS[i];
if (Name != NULL)
strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name,
sizeof(NamedColorList ->List[NamedColorList ->nColors].Name));
if (Name != NULL) {
strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name, cmsMAX_PATH-1);
NamedColorList ->List[NamedColorList ->nColors].Name[cmsMAX_PATH-1] = 0;
}
else
NamedColorList ->List[NamedColorList ->nColors].Name[0] = 0;
@@ -554,21 +589,21 @@ cmsBool CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
return TRUE;
}
// Returns number of elements
// Returns number of elements
cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* NamedColorList)
{
{
if (NamedColorList == NULL) return 0;
return NamedColorList ->nColors;
}
// Info aboout a given color
cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor,
char* Name,
char* Prefix,
cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor,
char* Name,
char* Prefix,
char* Suffix,
cmsUInt16Number* PCS,
cmsUInt16Number* PCS,
cmsUInt16Number* Colorant)
{
{
if (NamedColorList == NULL) return FALSE;
if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE;
@@ -576,11 +611,11 @@ cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cm
if (Name) strcpy(Name, NamedColorList->List[nColor].Name);
if (Prefix) strcpy(Prefix, NamedColorList->Prefix);
if (Suffix) strcpy(Suffix, NamedColorList->Suffix);
if (PCS)
if (PCS)
memmove(PCS, NamedColorList ->List[nColor].PCS, 3*sizeof(cmsUInt16Number));
if (Colorant)
memmove(Colorant, NamedColorList ->List[nColor].DeviceColorant,
if (Colorant)
memmove(Colorant, NamedColorList ->List[nColor].DeviceColorant,
sizeof(cmsUInt16Number) * NamedColorList ->ColorantCount);
@@ -589,7 +624,7 @@ cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cm
// Search for a given color name (no prefix or suffix)
cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name)
{
{
int i, n;
if (NamedColorList == NULL) return -1;
@@ -618,6 +653,24 @@ void* DupNamedColorList(cmsStage* mpe)
return cmsDupNamedColorList(List);
}
static
void EvalNamedColorPCS(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
{
cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data;
cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0);
if (index >= NamedColorList-> nColors) {
cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index);
}
else {
// Named color always uses Lab
Out[0] = (cmsFloat32Number) (NamedColorList->List[index].PCS[0] / 65535.0);
Out[1] = (cmsFloat32Number) (NamedColorList->List[index].PCS[1] / 65535.0);
Out[2] = (cmsFloat32Number) (NamedColorList->List[index].PCS[2] / 65535.0);
}
}
static
void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
{
@@ -629,23 +682,23 @@ void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const c
cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index);
}
else {
for (j=0; j < NamedColorList ->ColorantCount; j++)
Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0);
for (j=0; j < NamedColorList ->ColorantCount; j++)
Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0);
}
}
// Named color lookup element
cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList)
cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS)
{
return _cmsStageAllocPlaceholder(NamedColorList ->ContextID,
cmsSigNamedColorElemType,
1, 3,
EvalNamedColor,
DupNamedColorList,
FreeNamedColorList,
cmsDupNamedColorList(NamedColorList));
return _cmsStageAllocPlaceholder(NamedColorList ->ContextID,
cmsSigNamedColorElemType,
1, UsePCS ? 3 : NamedColorList ->ColorantCount,
UsePCS ? EvalNamedColorPCS : EvalNamedColor,
DupNamedColorList,
FreeNamedColorList,
cmsDupNamedColorList(NamedColorList));
}
@@ -674,19 +727,23 @@ cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUI
if (n > 255) return NULL;
Seq = (cmsSEQ*) _cmsMallocZero(ContextID, sizeof(cmsSEQ));
if (Seq == NULL) return NULL;
if (Seq == NULL) return NULL;
Seq -> ContextID = ContextID;
Seq -> seq = (cmsPSEQDESC*) _cmsCalloc(ContextID, n, sizeof(cmsPSEQDESC));
Seq -> n = n;
if (Seq -> seq == NULL) {
_cmsFree(ContextID, Seq);
return NULL;
}
for (i=0; i < n; i++) {
Seq -> seq[i].Manufacturer = NULL;
Seq -> seq[i].Model = NULL;
Seq -> seq[i].Description = NULL;
}
return Seq;
}
@@ -715,10 +772,10 @@ cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq)
NewSeq = (cmsSEQ*) _cmsMalloc(pseq -> ContextID, sizeof(cmsSEQ));
if (NewSeq == NULL) return NULL;
NewSeq -> seq = (cmsPSEQDESC*) _cmsCalloc(pseq ->ContextID, pseq ->n, sizeof(cmsPSEQDESC));
if (NewSeq ->seq == NULL) goto Error;
NewSeq -> ContextID = pseq ->ContextID;
NewSeq -> n = pseq ->n;
@@ -734,7 +791,7 @@ cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq)
NewSeq ->seq[i].Manufacturer = cmsMLUdup(pseq ->seq[i].Manufacturer);
NewSeq ->seq[i].Model = cmsMLUdup(pseq ->seq[i].Model);
NewSeq ->seq[i].Description = cmsMLUdup(pseq ->seq[i].Description);
}
return NewSeq;
@@ -745,6 +802,128 @@ Error:
return NULL;
}
// Dictionaries --------------------------------------------------------------------------------------------------------
// Dictionaries are just very simple linked lists
typedef struct _cmsDICT_struct {
cmsDICTentry* head;
cmsContext ContextID;
} _cmsDICT;
// Allocate an empty dictionary
cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID)
{
_cmsDICT* dict = (_cmsDICT*) _cmsMallocZero(ContextID, sizeof(_cmsDICT));
if (dict == NULL) return NULL;
dict ->ContextID = ContextID;
return (cmsHANDLE) dict;
}
// Dispose resources
void CMSEXPORT cmsDictFree(cmsHANDLE hDict)
{
_cmsDICT* dict = (_cmsDICT*) hDict;
cmsDICTentry *entry, *next;
_cmsAssert(dict != NULL);
// Walk the list freeing all nodes
entry = dict ->head;
while (entry != NULL) {
if (entry ->DisplayName != NULL) cmsMLUfree(entry ->DisplayName);
if (entry ->DisplayValue != NULL) cmsMLUfree(entry ->DisplayValue);
if (entry ->Name != NULL) _cmsFree(dict ->ContextID, entry -> Name);
if (entry ->Value != NULL) _cmsFree(dict ->ContextID, entry -> Value);
// Don't fall in the habitual trap...
next = entry ->Next;
_cmsFree(dict ->ContextID, entry);
entry = next;
}
_cmsFree(dict ->ContextID, dict);
}
// Duplicate a wide char string
static
wchar_t* DupWcs(cmsContext ContextID, const wchar_t* ptr)
{
if (ptr == NULL) return NULL;
return (wchar_t*) _cmsDupMem(ContextID, ptr, (mywcslen(ptr) + 1) * sizeof(wchar_t));
}
// Add a new entry to the linked list
cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue)
{
_cmsDICT* dict = (_cmsDICT*) hDict;
cmsDICTentry *entry;
_cmsAssert(dict != NULL);
_cmsAssert(Name != NULL);
entry = (cmsDICTentry*) _cmsMallocZero(dict ->ContextID, sizeof(cmsDICTentry));
if (entry == NULL) return FALSE;
entry ->DisplayName = cmsMLUdup(DisplayName);
entry ->DisplayValue = cmsMLUdup(DisplayValue);
entry ->Name = DupWcs(dict ->ContextID, Name);
entry ->Value = DupWcs(dict ->ContextID, Value);
entry ->Next = dict ->head;
dict ->head = entry;
return TRUE;
}
// Duplicates an existing dictionary
cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict)
{
_cmsDICT* old_dict = (_cmsDICT*) hDict;
cmsHANDLE hNew;
cmsDICTentry *entry;
_cmsAssert(old_dict != NULL);
hNew = cmsDictAlloc(old_dict ->ContextID);
if (hNew == NULL) return NULL;
// Walk the list freeing all nodes
entry = old_dict ->head;
while (entry != NULL) {
if (!cmsDictAddEntry(hNew, entry ->Name, entry ->Value, entry ->DisplayName, entry ->DisplayValue)) {
cmsDictFree(hNew);
return NULL;
}
entry = entry -> Next;
}
return hNew;
}
// Get a pointer to the linked list
const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict)
{
_cmsDICT* dict = (_cmsDICT*) hDict;
if (dict == NULL) return NULL;
return dict ->head;
}
// Helper For external languages
const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e)
{
if (e == NULL) return NULL;
return e ->Next;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,22 +3,22 @@
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -114,7 +114,7 @@ cmsFloat64Number f(cmsFloat64Number t)
if (t <= Limit)
return (841.0/108.0) * t + (16.0/116.0);
else
return pow(t, 1.0/3.0);
return pow(t, 1.0/3.0);
}
static
@@ -135,7 +135,7 @@ void CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cms
{
cmsFloat64Number fx, fy, fz;
if (WhitePoint == NULL)
if (WhitePoint == NULL)
WhitePoint = cmsD50_XYZ();
fx = f(xyz->X / WhitePoint->X);
@@ -153,7 +153,7 @@ void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz, const cm
{
cmsFloat64Number x, y, z;
if (WhitePoint == NULL)
if (WhitePoint == NULL)
WhitePoint = cmsD50_XYZ();
y = (Lab-> L + 16.0) / 116.0;
@@ -169,26 +169,26 @@ void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz, const cm
static
cmsFloat64Number L2float2(cmsUInt16Number v)
{
return (cmsFloat64Number) v / 652.800;
return (cmsFloat64Number) v / 652.800;
}
// the a/b part
static
cmsFloat64Number ab2float2(cmsUInt16Number v)
{
return ((cmsFloat64Number) v / 256.0) - 128.0;
{
return ((cmsFloat64Number) v / 256.0) - 128.0;
}
static
cmsUInt16Number L2Fix2(cmsFloat64Number L)
{
return _cmsQuickSaturateWord(L * 652.8);
return _cmsQuickSaturateWord(L * 652.8);
}
static
cmsUInt16Number ab2Fix2(cmsFloat64Number ab)
{
return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
}
@@ -249,7 +249,7 @@ void CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* f
Lab.L = Clamp_L_doubleV2(fLab ->L);
Lab.a = Clamp_ab_doubleV2(fLab ->a);
Lab.b = Clamp_ab_doubleV2(fLab ->b);
wLab[0] = L2Fix2(Lab.L);
wLab[1] = ab2Fix2(Lab.a);
wLab[2] = ab2Fix2(Lab.b);
@@ -274,7 +274,7 @@ cmsFloat64Number Clamp_ab_doubleV4(cmsFloat64Number ab)
return ab;
}
static
static
cmsUInt16Number L2Fix4(cmsFloat64Number L)
{
return _cmsQuickSaturateWord(L * 655.35);
@@ -289,11 +289,11 @@ cmsUInt16Number ab2Fix4(cmsFloat64Number ab)
void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
{
cmsCIELab Lab;
Lab.L = Clamp_L_doubleV4(fLab ->L);
Lab.a = Clamp_ab_doubleV4(fLab ->a);
Lab.b = Clamp_ab_doubleV4(fLab ->b);
wLab[0] = L2Fix4(Lab.L);
wLab[1] = ab2Fix4(Lab.a);
wLab[2] = ab2Fix4(Lab.b);
@@ -317,15 +317,15 @@ cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b)
h = 0;
else
h = atan2(a, b);
h *= (180. / M_PI);
while (h > 360.)
while (h > 360.)
h -= 360.;
while ( h < 0)
h += 360.;
return h;
}
@@ -334,7 +334,7 @@ cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b)
static
cmsFloat64Number Sqr(cmsFloat64Number v)
{
return v * v;
return v * v;
}
// From cylindrical coordinates. No check is performed, then negative values are allowed
void CMSEXPORT cmsLab2LCh(cmsCIELCh* LCh, const cmsCIELab* Lab)
@@ -352,13 +352,13 @@ void CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh)
Lab -> L = LCh -> L;
Lab -> a = LCh -> C * cos(h);
Lab -> b = LCh -> C * sin(h);
Lab -> b = LCh -> C * sin(h);
}
// In XYZ All 3 components are encoded using 1.15 fixed point
static
cmsUInt16Number XYZ2Fix(cmsFloat64Number d)
{
{
return _cmsQuickSaturateWord(d * 32768.0);
}
@@ -370,7 +370,7 @@ void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ
xyz.Y = fXYZ -> Y;
xyz.Z = fXYZ -> Z;
// Clamp to encodeable values.
// Clamp to encodeable values.
if (xyz.Y <= 0) {
xyz.X = 0;
@@ -378,19 +378,19 @@ void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ
xyz.Z = 0;
}
if (xyz.X > MAX_ENCODEABLE_XYZ)
if (xyz.X > MAX_ENCODEABLE_XYZ)
xyz.X = MAX_ENCODEABLE_XYZ;
if (xyz.X < 0)
xyz.X = 0;
if (xyz.Y > MAX_ENCODEABLE_XYZ)
if (xyz.Y > MAX_ENCODEABLE_XYZ)
xyz.Y = MAX_ENCODEABLE_XYZ;
if (xyz.Y < 0)
xyz.Y = 0;
if (xyz.Z > MAX_ENCODEABLE_XYZ)
if (xyz.Z > MAX_ENCODEABLE_XYZ)
xyz.Z = MAX_ENCODEABLE_XYZ;
if (xyz.Z < 0)
@@ -399,7 +399,7 @@ void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ
XYZ[0] = XYZ2Fix(xyz.X);
XYZ[1] = XYZ2Fix(xyz.Y);
XYZ[2] = XYZ2Fix(xyz.Z);
XYZ[2] = XYZ2Fix(xyz.Z);
}
@@ -422,7 +422,7 @@ void CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fXYZ, const cmsUInt16Number XYZ[3]
fXYZ -> X = XYZ2float(XYZ[0]);
fXYZ -> Y = XYZ2float(XYZ[1]);
fXYZ -> Z = XYZ2float(XYZ[2]);
}
}
// Returns dE on two Lab values
@@ -438,7 +438,7 @@ cmsFloat64Number CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab
}
// Return the CIE94 Delta E
// Return the CIE94 Delta E
cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
{
cmsCIELCh LCh1, LCh2;
@@ -452,7 +452,7 @@ cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab
dC = fabs(LCh1.C - LCh2.C);
dE = cmsDeltaE(Lab1, Lab2);
dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC);
if (dhsq < 0)
dh = 0;
@@ -463,7 +463,7 @@ cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab
sc = 1.0 + (0.048 * c12);
sh = 1.0 + (0.014 * c12);
return sqrt(Sqr(dL) + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh));
}
@@ -513,7 +513,7 @@ cmsFloat64Number CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab*
dc = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521;
g = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000));
t = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
t = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
0.040*cos((2*Aveh-136)/(180/M_PI))+
0.070*cos((3*Aveh-31)/(180/M_PI))+
0.049*cos((4*Aveh+114)/(180/M_PI))-
@@ -546,27 +546,27 @@ cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab*
cmsLab2LCh(&LCh1, Lab1);
cmsLab2LCh(&LCh2, Lab2);
dL = Lab2->L-Lab1->L;
dC = LCh2.C-LCh1.C;
dE = cmsDeltaE(Lab1, Lab2);
if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC));
else
dh =0;
if ((LCh1.h > 164) && (LCh1.h < 345))
if ((LCh1.h > 164) && (LCh1.h < 345))
t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI))));
else
else
t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI))));
sc = 0.0638 * LCh1.C / (1 + 0.0131 * LCh1.C) + 0.638;
sl = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L);
if (Lab1->L<16)
sl = 0.511;
sl = 0.511;
f = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900));
sh = sc*(t*f+1-f);
@@ -575,7 +575,7 @@ cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab*
return cmc;
}
// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
// importance of lightness, chroma and hue in different industrial applications
cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2,
cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh)
@@ -595,25 +595,25 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL
cmsFloat64Number a_p = (1 + G ) * a1;
cmsFloat64Number b_p = b1;
cmsFloat64Number C_p = sqrt( Sqr(a_p) + Sqr(b_p));
cmsFloat64Number h_p = atan2deg(b_p, a_p);
cmsFloat64Number h_p = atan2deg(b_p, a_p);
cmsFloat64Number a_ps = (1 + G) * as;
cmsFloat64Number b_ps = bs;
cmsFloat64Number C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
cmsFloat64Number h_ps = atan2deg(b_ps, a_ps);
cmsFloat64Number meanC_p =(C_p + C_ps) / 2;
cmsFloat64Number hps_plus_hp = h_ps + h_p;
cmsFloat64Number hps_minus_hp = h_ps - h_p;
cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
(hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
(hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
(hps_plus_hp - 360)/2;
cmsFloat64Number delta_h = (hps_minus_hp) <= -180.000001 ? (hps_minus_hp + 360) :
(hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
(hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
(hps_minus_hp);
cmsFloat64Number delta_L = (Ls - L1);
cmsFloat64Number delta_C = (C_ps - C_p );
@@ -621,9 +621,9 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL
cmsFloat64Number delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANS(delta_h) / 2);
cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
+ 0.24 * cos(RADIANS(2*meanh_p))
+ 0.32 * cos(RADIANS(3*meanh_p + 6))
cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
+ 0.24 * cos(RADIANS(2*meanh_p))
+ 0.32 * cos(RADIANS(3*meanh_p + 6))
- 0.2 * cos(RADIANS(4*meanh_p - 63));
cmsFloat64Number Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) );
@@ -637,9 +637,9 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL
cmsFloat64Number Rt = -sin(2 * RADIANS(delta_ro)) * Rc;
cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
Sqr(delta_C/(Sc * Kc)) +
Sqr(delta_H/(Sh * Kh)) +
cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
Sqr(delta_C/(Sc * Kc)) +
Sqr(delta_H/(Sh * Kh)) +
Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh)));
return deltaE00;
@@ -662,41 +662,41 @@ int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsU
// HighResPrecalc is maximum resolution
if (dwFlags & cmsFLAGS_HIGHRESPRECALC) {
if (nChannels > 4)
if (nChannels > 4)
return 7; // 7 for Hifi
if (nChannels == 4) // 23 for CMYK
return 23;
return 49; // 49 for RGB and others
return 49; // 49 for RGB and others
}
// LowResPrecal is lower resolution
if (dwFlags & cmsFLAGS_LOWRESPRECALC) {
if (nChannels > 4)
if (nChannels > 4)
return 6; // 6 for more than 4 channels
if (nChannels == 1)
if (nChannels == 1)
return 33; // For monochrome
return 17; // 17 for remaining
}
// Default values
if (nChannels > 4)
if (nChannels > 4)
return 7; // 7 for Hifi
if (nChannels == 4)
return 17; // 17 for CMYK
return 33; // 33 for RGB
return 33; // 33 for RGB
}
cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
cmsUInt16Number **White,
cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
cmsUInt16Number **White,
cmsUInt16Number **Black,
cmsUInt32Number *nOutputs)
{
@@ -719,7 +719,7 @@ cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
if (Black) *Black = Grayblack;
if (nOutputs) *nOutputs = 1;
return TRUE;
case cmsSigRgbData: if (White) *White = RGBwhite;
if (Black) *Black = RGBblack;
if (nOutputs) *nOutputs = 3;
@@ -746,7 +746,7 @@ cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
return FALSE;
}
// Several utilities -------------------------------------------------------
@@ -799,9 +799,9 @@ cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation)
int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
{
{
switch (ProfileSpace) {
case cmsSigGrayData: return PT_GRAY;
case cmsSigRgbData: return PT_RGB;
case cmsSigCmyData: return PT_CMY;
@@ -814,52 +814,52 @@ int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
case cmsSigHsvData: return PT_HSV;
case cmsSigHlsData: return PT_HLS;
case cmsSigYxyData: return PT_Yxy;
case cmsSig1colorData:
case cmsSigMCH1Data: return PT_MCH1;
case cmsSig2colorData:
case cmsSigMCH2Data: return PT_MCH2;
case cmsSig3colorData:
case cmsSigMCH3Data: return PT_MCH3;
case cmsSig4colorData:
case cmsSigMCH4Data: return PT_MCH4;
case cmsSig5colorData:
case cmsSigMCH5Data: return PT_MCH5;
case cmsSig6colorData:
case cmsSigMCH6Data: return PT_MCH6;
case cmsSigMCH7Data:
case cmsSig7colorData:return PT_MCH7;
case cmsSigMCH8Data:
case cmsSig8colorData:return PT_MCH8;
case cmsSigMCH9Data:
case cmsSig9colorData:return PT_MCH9;
case cmsSigMCHAData:
case cmsSig10colorData:return PT_MCH10;
case cmsSigMCHBData:
case cmsSig11colorData:return PT_MCH11;
case cmsSigMCHCData:
case cmsSig12colorData:return PT_MCH12;
case cmsSigMCHDData:
case cmsSig13colorData:return PT_MCH13;
case cmsSigMCHEData:
case cmsSig14colorData:return PT_MCH14;
case cmsSigMCHFData:
case cmsSig15colorData:return PT_MCH15;
default: return (cmsColorSpaceSignature) (-1);
}
}
@@ -869,31 +869,36 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
{
switch (ColorSpace) {
case cmsSigMCH1Data:
case cmsSig1colorData:
case cmsSigGrayData: return 1;
case cmsSigMCH2Data:
case cmsSig2colorData: return 2;
case cmsSigXYZData:
case cmsSigLabData:
case cmsSigLuvData:
case cmsSigYCbCrData:
case cmsSigYxyData:
case cmsSigRgbData:
case cmsSigRgbData:
case cmsSigHsvData:
case cmsSigHlsData:
case cmsSigCmyData:
case cmsSigCmyData:
case cmsSigMCH3Data:
case cmsSig3colorData: return 3;
case cmsSigLuvKData:
case cmsSigCmykData:
case cmsSigMCH4Data:
case cmsSig4colorData: return 4;
case cmsSigMCH5Data:
case cmsSig5colorData: return 5;
case cmsSig5colorData: return 5;
case cmsSigMCH6Data:
case cmsSigMCH6Data:
case cmsSig6colorData: return 6;
case cmsSigMCH7Data:
case cmsSig7colorData: return 7;
@@ -908,7 +913,7 @@ cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
case cmsSigMCHBData:
case cmsSig11colorData: return 11;
case cmsSigMCHCData:
case cmsSig12colorData: return 12;

View File

@@ -3,22 +3,22 @@
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -44,7 +44,7 @@ cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word)
tmp = pByte[0];
pByte[0] = pByte[1];
pByte[1] = tmp;
#endif
#endif
return Word;
}
@@ -76,12 +76,12 @@ cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number DWord)
// 1 2 3 4 5 6 7 8
// 8 7 6 5 4 3 2 1
void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number QWord)
void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord)
{
#ifndef CMS_USE_BIG_ENDIAN
cmsUInt8Number* pIn = (cmsUInt8Number*) &QWord;
cmsUInt8Number* pIn = (cmsUInt8Number*) QWord;
cmsUInt8Number* pOut = (cmsUInt8Number*) Result;
_cmsAssert(Result != NULL);
@@ -91,15 +91,19 @@ void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number Q
pOut[5] = pIn[2];
pOut[4] = pIn[3];
pOut[3] = pIn[4];
pOut[2] = pIn[5];
pOut[2] = pIn[5];
pOut[1] = pIn[6];
pOut[0] = pIn[7];
#else
_cmsAssert(Result != NULL);
*Result = QWord;
# ifdef CMS_DONT_USE_INT64
(*Result)[0] = QWord[0];
(*Result)[1] = QWord[1];
# else
*Result = *QWord;
# endif
#endif
}
@@ -110,8 +114,8 @@ cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)
return FALSE;
if (n != NULL) *n = tmp;
return TRUE;
@@ -123,8 +127,8 @@ cmsBool CMSEXPORT _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n)
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1)
return FALSE;
if (n != NULL) *n = _cmsAdjustEndianess16(tmp);
return TRUE;
@@ -155,8 +159,8 @@ cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
return FALSE;
if (n != NULL) *n = _cmsAdjustEndianess32(tmp);
return TRUE;
@@ -168,8 +172,8 @@ cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1)
return FALSE;
if (n != NULL) {
@@ -186,10 +190,10 @@ cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
return FALSE;
if (n != NULL) _cmsAdjustEndianess64(n, tmp);
if (n != NULL) _cmsAdjustEndianess64(n, &tmp);
return TRUE;
}
@@ -200,8 +204,8 @@ cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n
_cmsAssert(io != NULL);
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
return FALSE;
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
return FALSE;
if (n != NULL) {
*n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp));
@@ -250,9 +254,9 @@ cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n)
{
_cmsAssert(io != NULL);
if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1)
return FALSE;
return TRUE;
}
@@ -263,9 +267,9 @@ cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n)
_cmsAssert(io != NULL);
tmp = _cmsAdjustEndianess16(n);
if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1)
return FALSE;
return TRUE;
}
@@ -290,9 +294,9 @@ cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)
_cmsAssert(io != NULL);
tmp = _cmsAdjustEndianess32(n);
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
return TRUE;
}
@@ -305,22 +309,22 @@ cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)
tmp = *(cmsUInt32Number*) &n;
tmp = _cmsAdjustEndianess32(tmp);
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
return TRUE;
}
cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number n)
cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
{
cmsUInt64Number tmp;
_cmsAssert(io != NULL);
_cmsAdjustEndianess64(&tmp, n);
if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1)
return FALSE;
return TRUE;
}
@@ -331,16 +335,16 @@ cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n
_cmsAssert(io != NULL);
tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n));
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
return TRUE;
}
cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)
{
cmsEncodedXYZNumber xyz;
_cmsAssert(io != NULL);
_cmsAssert(XYZ != NULL);
@@ -365,7 +369,7 @@ cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)
cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
{
cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val);
return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);
return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);
}
// from Fixed point 15.16 to double
@@ -386,13 +390,13 @@ cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)
return sign * floater;
}
// from double to Fixed point 15.16
// from double to Fixed point 15.16
cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v)
{
return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5));
}
// Date/Time functions
// Date/Time functions
void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest)
{
@@ -431,7 +435,7 @@ cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io)
_cmsAssert(io != NULL);
if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1)
if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1)
return (cmsTagTypeSignature) 0;
return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig);
@@ -454,7 +458,7 @@ cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io)
cmsUInt8Number Buffer[4];
cmsUInt32Number NextAligned, At;
cmsUInt32Number BytesToNextAlignedPos;
_cmsAssert(io != NULL);
At = io -> Tell(io);
@@ -502,7 +506,7 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
if (len < 0) return FALSE; // Truncated, which is a fatal error for us
rc = io ->Write(io, len, Buffer);
va_end(args);
return rc;
@@ -511,80 +515,102 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
// Plugin memory management -------------------------------------------------------------------------------------------------
static _cmsSubAllocator* PluginPool = NULL;
// Specialized malloc for plug-ins, that is freed upon exit.
void* _cmsPluginMalloc(cmsUInt32Number size)
void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)
{
if (PluginPool == NULL)
PluginPool = _cmsCreateSubAlloc(0, 4*1024);
struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);
return _cmsSubAlloc(PluginPool, size);
if (ctx ->MemPool == NULL) {
if (ContextID == NULL) {
ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024);
}
else {
cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");
return NULL;
}
}
return _cmsSubAlloc(ctx->MemPool, size);
}
// Main plug-in dispatcher
cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
{
return cmsPluginTHR(NULL, Plug_in);
}
cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
{
cmsPluginBase* Plugin;
for (Plugin = (cmsPluginBase*) Plug_in;
Plugin != NULL;
for (Plugin = (cmsPluginBase*) Plug_in;
Plugin != NULL;
Plugin = Plugin -> Next) {
if (Plugin -> Magic != cmsPluginMagicNumber) {
cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
return FALSE;
}
if (Plugin ->ExpectedVersion > LCMS_VERSION) {
cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
Plugin ->ExpectedVersion, LCMS_VERSION);
return FALSE;
}
if (Plugin ->ExpectedVersion > LCMS_VERSION) {
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
Plugin ->ExpectedVersion, LCMS_VERSION);
return FALSE;
}
switch (Plugin -> Type) {
case cmsPluginMemHandlerSig:
if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE;
if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginInterpolationSig:
if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE;
if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTagTypeSig:
if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE;
if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTagSig:
if (!_cmsRegisterTagPlugin(Plugin)) return FALSE;
if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginFormattersSig:
if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE;
if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginRenderingIntentSig:
if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE;
if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginParametricCurveSig:
if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE;
if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginMultiProcessElementSig:
if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE;
if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginOptimizationSig:
if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE;
if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTransformSig:
if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginMutexSig:
if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;
break;
default:
cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
return FALSE;
}
}
}
// Keep a reference to the plug-in
@@ -595,18 +621,337 @@ cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
// Revert all plug-ins to default
void CMSEXPORT cmsUnregisterPlugins(void)
{
_cmsRegisterMemHandlerPlugin(NULL);
_cmsRegisterInterpPlugin(NULL);
_cmsRegisterTagTypePlugin(NULL);
_cmsRegisterTagPlugin(NULL);
_cmsRegisterFormattersPlugin(NULL);
_cmsRegisterRenderingIntentPlugin(NULL);
_cmsRegisterParametricCurvesPlugin(NULL);
_cmsRegisterMultiProcessElementPlugin(NULL);
_cmsRegisterOptimizationPlugin(NULL);
if (PluginPool != NULL)
_cmsSubAllocDestroy(PluginPool);
PluginPool = NULL;
cmsUnregisterPluginsTHR(NULL);
}
// The Global storage for system context. This is the one and only global variable
// pointers structure. All global vars are referenced here.
static struct _cmsContext_struct globalContext = {
NULL, // Not in the linked list
NULL, // No suballocator
{
NULL, // UserPtr,
&_cmsLogErrorChunk, // Logger,
&_cmsAlarmCodesChunk, // AlarmCodes,
&_cmsAdaptationStateChunk, // AdaptationState,
&_cmsMemPluginChunk, // MemPlugin,
&_cmsInterpPluginChunk, // InterpPlugin,
&_cmsCurvesPluginChunk, // CurvesPlugin,
&_cmsFormattersPluginChunk, // FormattersPlugin,
&_cmsTagTypePluginChunk, // TagTypePlugin,
&_cmsTagPluginChunk, // TagPlugin,
&_cmsIntentsPluginChunk, // IntentPlugin,
&_cmsMPETypePluginChunk, // MPEPlugin,
&_cmsOptimizationPluginChunk, // OptimizationPlugin,
&_cmsTransformPluginChunk, // TransformPlugin,
&_cmsMutexPluginChunk // MutexPlugin
},
{ NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
};
// The context pool (linked list head)
static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
// Internal, get associated pointer, with guessing. Never returns NULL.
struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
{
struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
struct _cmsContext_struct* ctx;
// On 0, use global settings
if (id == NULL)
return &globalContext;
// Search
for (ctx = _cmsContextPoolHead;
ctx != NULL;
ctx = ctx ->Next) {
// Found it?
if (id == ctx)
return ctx; // New-style context,
}
return &globalContext;
}
// Internal: get the memory area associanted with each context client
// Returns the block assigned to the specific zone.
void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
{
struct _cmsContext_struct* ctx;
void *ptr;
if (mc < 0 || mc >= MemoryClientMax) {
cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client");
return NULL;
}
ctx = _cmsGetContext(ContextID);
ptr = ctx ->chunks[mc];
if (ptr != NULL)
return ptr;
// A null ptr means no special settings for that context, and this
// reverts to Context0 globals
return globalContext.chunks[mc];
}
// This function returns the given context its default pristine state,
// as no plug-ins were declared. There is no way to unregister a single
// plug-in, as a single call to cmsPluginTHR() function may register
// many different plug-ins simultaneously, then there is no way to
// identify which plug-in to unregister.
void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
{
_cmsRegisterMemHandlerPlugin(ContextID, NULL);
_cmsRegisterInterpPlugin(ContextID, NULL);
_cmsRegisterTagTypePlugin(ContextID, NULL);
_cmsRegisterTagPlugin(ContextID, NULL);
_cmsRegisterFormattersPlugin(ContextID, NULL);
_cmsRegisterRenderingIntentPlugin(ContextID, NULL);
_cmsRegisterParametricCurvesPlugin(ContextID, NULL);
_cmsRegisterMultiProcessElementPlugin(ContextID, NULL);
_cmsRegisterOptimizationPlugin(ContextID, NULL);
_cmsRegisterTransformPlugin(ContextID, NULL);
_cmsRegisterMutexPlugin(ContextID, NULL);
}
// Returns the memory manager plug-in, if any, from the Plug-in bundle
static
cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle)
{
cmsPluginBase* Plugin;
for (Plugin = (cmsPluginBase*) PluginBundle;
Plugin != NULL;
Plugin = Plugin -> Next) {
if (Plugin -> Magic == cmsPluginMagicNumber &&
Plugin -> ExpectedVersion <= LCMS_VERSION &&
Plugin -> Type == cmsPluginMemHandlerSig) {
// Found!
return (cmsPluginMemHandler*) Plugin;
}
}
// Nope, revert to defaults
return NULL;
}
// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
// data that will be forwarded to plug-ins and logger.
cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
{
struct _cmsContext_struct* ctx;
struct _cmsContext_struct fakeContext;
_cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
fakeContext.chunks[UserPtr] = UserData;
fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
// Create the context structure.
ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
if (ctx == NULL)
return NULL; // Something very wrong happened!
// Init the structure and the memory manager
memset(ctx, 0, sizeof(struct _cmsContext_struct));
// Keep memory manager
memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
// Maintain the linked list (with proper locking)
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
ctx ->Next = _cmsContextPoolHead;
_cmsContextPoolHead = ctx;
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
ctx ->chunks[UserPtr] = UserData;
ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
// Now we can allocate the pool by using default memory manager
ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers
if (ctx ->MemPool == NULL) {
cmsDeleteContext(ctx);
return NULL;
}
_cmsAllocLogErrorChunk(ctx, NULL);
_cmsAllocAlarmCodesChunk(ctx, NULL);
_cmsAllocAdaptationStateChunk(ctx, NULL);
_cmsAllocMemPluginChunk(ctx, NULL);
_cmsAllocInterpPluginChunk(ctx, NULL);
_cmsAllocCurvesPluginChunk(ctx, NULL);
_cmsAllocFormattersPluginChunk(ctx, NULL);
_cmsAllocTagTypePluginChunk(ctx, NULL);
_cmsAllocMPETypePluginChunk(ctx, NULL);
_cmsAllocTagPluginChunk(ctx, NULL);
_cmsAllocIntentsPluginChunk(ctx, NULL);
_cmsAllocOptimizationPluginChunk(ctx, NULL);
_cmsAllocTransformPluginChunk(ctx, NULL);
_cmsAllocMutexPluginChunk(ctx, NULL);
// Setup the plug-ins
if (!cmsPluginTHR(ctx, Plugin)) {
cmsDeleteContext(ctx);
return NULL;
}
return (cmsContext) ctx;
}
// Duplicates a context with all associated plug-ins.
// Caller may specify an optional pointer to user-defined
// data that will be forwarded to plug-ins and logger.
cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
{
int i;
struct _cmsContext_struct* ctx;
const struct _cmsContext_struct* src = _cmsGetContext(ContextID);
void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr];
ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct));
if (ctx == NULL)
return NULL; // Something very wrong happened
// Setup default memory allocators
memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
// Maintain the linked list
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
ctx ->Next = _cmsContextPoolHead;
_cmsContextPoolHead = ctx;
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
ctx ->chunks[UserPtr] = userData;
ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));
if (ctx ->MemPool == NULL) {
cmsDeleteContext(ctx);
return NULL;
}
// Allocate all required chunks.
_cmsAllocLogErrorChunk(ctx, src);
_cmsAllocAlarmCodesChunk(ctx, src);
_cmsAllocAdaptationStateChunk(ctx, src);
_cmsAllocMemPluginChunk(ctx, src);
_cmsAllocInterpPluginChunk(ctx, src);
_cmsAllocCurvesPluginChunk(ctx, src);
_cmsAllocFormattersPluginChunk(ctx, src);
_cmsAllocTagTypePluginChunk(ctx, src);
_cmsAllocMPETypePluginChunk(ctx, src);
_cmsAllocTagPluginChunk(ctx, src);
_cmsAllocIntentsPluginChunk(ctx, src);
_cmsAllocOptimizationPluginChunk(ctx, src);
_cmsAllocTransformPluginChunk(ctx, src);
_cmsAllocMutexPluginChunk(ctx, src);
// Make sure no one failed
for (i=Logger; i < MemoryClientMax; i++) {
if (src ->chunks[i] == NULL) {
cmsDeleteContext((cmsContext) ctx);
return NULL;
}
}
return (cmsContext) ctx;
}
static
struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
{
struct _cmsContext_struct* prev;
// Search for previous
for (prev = _cmsContextPoolHead;
prev != NULL;
prev = prev ->Next)
{
if (prev ->Next == id)
return prev;
}
return NULL; // List is empty or only one element!
}
// Frees any resources associated with the given context,
// and destroys the context placeholder.
// The ContextID can no longer be used in any THR operation.
void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
{
if (ContextID != NULL) {
struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
struct _cmsContext_struct fakeContext;
struct _cmsContext_struct* prev;
memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
// Get rid of plugins
cmsUnregisterPluginsTHR(ContextID);
// Since all memory is allocated in the private pool, all what we need to do is destroy the pool
if (ctx -> MemPool != NULL)
_cmsSubAllocDestroy(ctx ->MemPool);
ctx -> MemPool = NULL;
// Maintain list
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
if (_cmsContextPoolHead == ctx) {
_cmsContextPoolHead = ctx->Next;
}
else {
// Search for previous
for (prev = _cmsContextPoolHead;
prev != NULL;
prev = prev ->Next)
{
if (prev -> Next == ctx) {
prev -> Next = ctx ->Next;
break;
}
}
}
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
// free the memory block itself
_cmsFree(&fakeContext, ctx);
}
}
// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation
void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)
{
return _cmsContextGetClientChunk(ContextID, UserPtr);
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,22 +3,22 @@
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -27,29 +27,31 @@
#include "lcms2_internal.h"
#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
#define cmsmax(a, b) (((a) > (b)) ? (a) : (b))
// This file contains routines for resampling and LUT optimization, black point detection
// and black preservation.
// and black preservation.
// Black point detection -------------------------------------------------------------------------
// PCS -> PCS round trip transform, always uses relative intent on the device -> pcs
// PCS -> PCS round trip transform, always uses relative intent on the device -> pcs
static
cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent)
{
cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsHPROFILE hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
cmsHTRANSFORM xform;
cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE };
cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 };
cmsHPROFILE hProfiles[4];
cmsUInt32Number Intents[4];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab;
Intents[0] = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC;
xform = cmsCreateExtendedTransform(ContextID, 4, hProfiles, BPC, Intents,
xform = cmsCreateExtendedTransform(ContextID, 4, hProfiles, BPC, Intents,
States, NULL, 0, TYPE_Lab_DBL, TYPE_Lab_DBL, cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
cmsCloseProfile(hLab);
@@ -59,7 +61,7 @@ cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent
// Use darker colorants to obtain black point. This works in the relative colorimetric intent and
// assumes more ink results in darker colors. No ink limit is assumed.
static
cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
cmsUInt32Number Intent,
cmsCIEXYZ* BlackPoint,
cmsUInt32Number dwFlags)
@@ -68,28 +70,28 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
cmsHTRANSFORM xform;
cmsColorSpaceSignature Space;
cmsUInt32Number nChannels;
cmsUInt32Number dwFormat;
cmsUInt32Number dwFormat;
cmsHPROFILE hLab;
cmsCIELab Lab;
cmsCIEXYZ BlackXYZ;
cmsCIEXYZ BlackXYZ;
cmsContext ContextID = cmsGetProfileContextID(hInput);
// If the profile does not support input direction, assume Black point 0
// If the profile does not support input direction, assume Black point 0
if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Create a formatter which has n channels and floating point
dwFormat = cmsFormatterForColorspaceOfProfile(hInput, 2, FALSE);
// Try to get black by using black colorant
// Try to get black by using black colorant
Space = cmsGetColorSpace(hInput);
// This function returns darker colorant in 16 bits for several spaces
if (!_cmsEndPointsBySpace(Space, NULL, &Black, &nChannels)) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
@@ -103,21 +105,21 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
hLab = cmsCreateLab2ProfileTHR(ContextID, NULL);
if (hLab == NULL) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
return FALSE;
}
// Create the transform
xform = cmsCreateTransformTHR(ContextID, hInput, dwFormat,
hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
cmsCloseProfile(hLab);
if (xform == NULL) {
// Something went wrong. Get rid of open resources and return zero as black
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Convert black to Lab
cmsDoTransform(xform, Black, &Lab, 1);
@@ -125,38 +127,37 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
Lab.a = Lab.b = 0;
if (Lab.L > 50) Lab.L = 50;
// Free the resources
// Free the resources
cmsDeleteTransform(xform);
// Convert from Lab (which is now clipped) to XYZ.
cmsLab2XYZ(NULL, &BlackXYZ, &Lab);
if (BlackPoint != NULL)
*BlackPoint = BlackXYZ;
return TRUE;
cmsUNUSED_PARAMETER(dwFlags);
}
// Get a black point of output CMYK profile, discounting any ink-limiting embedded
// Get a black point of output CMYK profile, discounting any ink-limiting embedded
// in the profile. For doing that, we use perceptual intent in input direction:
// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
static
cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile)
{
cmsHTRANSFORM hRoundTrip;
{
cmsHTRANSFORM hRoundTrip;
cmsCIELab LabIn, LabOut;
cmsCIEXYZ BlackXYZ;
cmsCIEXYZ BlackXYZ;
// Is the intent supported by the profile?
if (!cmsIsIntentSupported(hProfile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT)) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return TRUE;
}
hRoundTrip = CreateRoundtripXForm(hProfile, INTENT_PERCEPTUAL);
if (hRoundTrip == NULL) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
@@ -171,10 +172,10 @@ cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfi
LabOut.a = LabOut.b = 0;
cmsDeleteTransform(hRoundTrip);
// Convert it to XYZ
cmsLab2XYZ(NULL, &BlackXYZ, &LabOut);
cmsLab2XYZ(NULL, &BlackXYZ, &LabOut);
if (BlackPoint != NULL)
*BlackPoint = BlackXYZ;
@@ -182,34 +183,43 @@ cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfi
}
// This function shouldn't exist at all -- there is such quantity of broken
// profiles on black point tag, that we must somehow fix chromaticity to
// profiles on black point tag, that we must somehow fix chromaticity to
// avoid huge tint when doing Black point compensation. This function does
// just that. There is a special flag for using black point tag, but turned
// off by default because it is bogus on most profiles. The detection algorithm
// involves to turn BP to neutral and to use only L component.
// just that. There is a special flag for using black point tag, but turned
// off by default because it is bogus on most profiles. The detection algorithm
// involves to turn BP to neutral and to use only L component.
cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
{
{
cmsProfileClassSignature devClass;
// Zero for black point
if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
// Make sure the device class is adequate
devClass = cmsGetDeviceClass(hProfile);
if (devClass == cmsSigLinkClass ||
devClass == cmsSigAbstractClass ||
devClass == cmsSigNamedColorClass) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it. Black point tag is deprecated in V4.
// Make sure intent is adequate
if (Intent != INTENT_PERCEPTUAL &&
Intent != INTENT_RELATIVE_COLORIMETRIC &&
Intent != INTENT_SATURATION) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
// v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it. Black point tag is deprecated in V4.
if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
(Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
// Matrix shaper share MRC & perceptual intents
if (cmsIsMatrixShaper(hProfile))
if (cmsIsMatrixShaper(hProfile))
return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, 0);
// Get Perceptual black out of v4 profiles. That is fixed for perceptual & saturation intents
BlackPoint -> X = cmsPERCEPTUAL_BLACK_X;
BlackPoint -> X = cmsPERCEPTUAL_BLACK_X;
BlackPoint -> Y = cmsPERCEPTUAL_BLACK_Y;
BlackPoint -> Z = cmsPERCEPTUAL_BLACK_Z;
@@ -220,13 +230,13 @@ cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfil
#ifdef CMS_USE_PROFILE_BLACK_POINT_TAG
// v2, v4 rel/abs colorimetric
if (cmsIsTag(hProfile, cmsSigMediaBlackPointTag) &&
if (cmsIsTag(hProfile, cmsSigMediaBlackPointTag) &&
Intent == INTENT_RELATIVE_COLORIMETRIC) {
cmsCIEXYZ *BlackPtr, BlackXYZ, UntrustedBlackPoint, TrustedBlackPoint, MediaWhite;
cmsCIELab Lab;
// If black point is specified, then use it,
// If black point is specified, then use it,
BlackPtr = cmsReadTag(hProfile, cmsSigMediaBlackPointTag);
if (BlackPtr != NULL) {
@@ -245,16 +255,16 @@ cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfil
if (BlackPoint != NULL)
*BlackPoint = TrustedBlackPoint;
return TRUE;
}
}
#endif
// That is about v2 profiles.
// That is about v2 profiles.
// If output profile, discount ink-limiting and that's all
if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
(cmsGetDeviceClass(hProfile) == cmsSigOutputClass) &&
(cmsGetColorSpace(hProfile) == cmsSigCmykData))
return BlackPointUsingPerceptualBlack(BlackPoint, hProfile);
@@ -264,3 +274,299 @@ cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfil
}
// ---------------------------------------------------------------------------------------------------------
// Least Squares Fit of a Quadratic Curve to Data
// http://www.personal.psu.edu/jhm/f90/lectures/lsq2.html
static
cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[], cmsFloat64Number y[])
{
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
double sum_y = 0, sum_yx = 0, sum_yx2 = 0;
double d, a, b, c;
int i;
cmsMAT3 m;
cmsVEC3 v, res;
if (n < 4) return 0;
for (i=0; i < n; i++) {
double xn = x[i];
double yn = y[i];
sum_x += xn;
sum_x2 += xn*xn;
sum_x3 += xn*xn*xn;
sum_x4 += xn*xn*xn*xn;
sum_y += yn;
sum_yx += yn*xn;
sum_yx2 += yn*xn*xn;
}
_cmsVEC3init(&m.v[0], n, sum_x, sum_x2);
_cmsVEC3init(&m.v[1], sum_x, sum_x2, sum_x3);
_cmsVEC3init(&m.v[2], sum_x2, sum_x3, sum_x4);
_cmsVEC3init(&v, sum_y, sum_yx, sum_yx2);
if (!_cmsMAT3solve(&res, &m, &v)) return 0;
a = res.n[2];
b = res.n[1];
c = res.n[0];
if (fabs(a) < 1.0E-10) {
return cmsmin(0, cmsmax(50, -c/b ));
}
else {
d = b*b - 4.0 * a * c;
if (d <= 0) {
return 0;
}
else {
double rt = (-b + sqrt(d)) / (2.0 * a);
return cmsmax(0, cmsmin(50, rt));
}
}
}
/*
static
cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
{
int i;
cmsFloat64Number last;
last = Table[n-1];
for (i = n-2; i >= 0; --i) {
if (Table[i] > last)
return FALSE;
else
last = Table[i];
}
return TRUE;
}
*/
// Calculates the black point of a destination profile.
// This algorithm comes from the Adobe paper disclosing its black point compensation method.
cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
{
cmsColorSpaceSignature ColorSpace;
cmsHTRANSFORM hRoundTrip = NULL;
cmsCIELab InitialLab, destLab, Lab;
cmsFloat64Number inRamp[256], outRamp[256];
cmsFloat64Number MinL, MaxL;
cmsBool NearlyStraightMidrange = TRUE;
cmsFloat64Number yRamp[256];
cmsFloat64Number x[256], y[256];
cmsFloat64Number lo, hi;
int n, l;
cmsProfileClassSignature devClass;
// Make sure the device class is adequate
devClass = cmsGetDeviceClass(hProfile);
if (devClass == cmsSigLinkClass ||
devClass == cmsSigAbstractClass ||
devClass == cmsSigNamedColorClass) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Make sure intent is adequate
if (Intent != INTENT_PERCEPTUAL &&
Intent != INTENT_RELATIVE_COLORIMETRIC &&
Intent != INTENT_SATURATION) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it. Black point tag is deprecated in V4.
if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
(Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
// Matrix shaper share MRC & perceptual intents
if (cmsIsMatrixShaper(hProfile))
return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, 0);
// Get Perceptual black out of v4 profiles. That is fixed for perceptual & saturation intents
BlackPoint -> X = cmsPERCEPTUAL_BLACK_X;
BlackPoint -> Y = cmsPERCEPTUAL_BLACK_Y;
BlackPoint -> Z = cmsPERCEPTUAL_BLACK_Z;
return TRUE;
}
// Check if the profile is lut based and gray, rgb or cmyk (7.2 in Adobe's document)
ColorSpace = cmsGetColorSpace(hProfile);
if (!cmsIsCLUT(hProfile, Intent, LCMS_USED_AS_OUTPUT ) ||
(ColorSpace != cmsSigGrayData &&
ColorSpace != cmsSigRgbData &&
ColorSpace != cmsSigCmykData)) {
// In this case, handle as input case
return cmsDetectBlackPoint(BlackPoint, hProfile, Intent, dwFlags);
}
// It is one of the valid cases!, use Adobe algorithm
// Set a first guess, that should work on good profiles.
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
cmsCIEXYZ IniXYZ;
// calculate initial Lab as source black point
if (!cmsDetectBlackPoint(&IniXYZ, hProfile, Intent, dwFlags)) {
return FALSE;
}
// convert the XYZ to lab
cmsXYZ2Lab(NULL, &InitialLab, &IniXYZ);
} else {
// set the initial Lab to zero, that should be the black point for perceptual and saturation
InitialLab.L = 0;
InitialLab.a = 0;
InitialLab.b = 0;
}
// Step 2
// ======
// Create a roundtrip. Define a Transform BT for all x in L*a*b*
hRoundTrip = CreateRoundtripXForm(hProfile, Intent);
if (hRoundTrip == NULL) return FALSE;
// Compute ramps
for (l=0; l < 256; l++) {
Lab.L = (cmsFloat64Number) (l * 100.0) / 255.0;
Lab.a = cmsmin(50, cmsmax(-50, InitialLab.a));
Lab.b = cmsmin(50, cmsmax(-50, InitialLab.b));
cmsDoTransform(hRoundTrip, &Lab, &destLab, 1);
inRamp[l] = Lab.L;
outRamp[l] = destLab.L;
}
// Make monotonic
for (l = 254; l > 0; --l) {
outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
}
// Check
if (! (outRamp[0] < outRamp[255])) {
cmsDeleteTransform(hRoundTrip);
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// Test for mid range straight (only on relative colorimetric)
NearlyStraightMidrange = TRUE;
MinL = outRamp[0]; MaxL = outRamp[255];
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
for (l=0; l < 256; l++) {
if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
(fabs(inRamp[l] - outRamp[l]) < 4.0 )))
NearlyStraightMidrange = FALSE;
}
// If the mid range is straight (as determined above) then the
// DestinationBlackPoint shall be the same as initialLab.
// Otherwise, the DestinationBlackPoint shall be determined
// using curve fitting.
if (NearlyStraightMidrange) {
cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
cmsDeleteTransform(hRoundTrip);
return TRUE;
}
}
// curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
// with a corner and a nearly straight line to the white point.
for (l=0; l < 256; l++) {
yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
}
// find the black point using the least squares error quadratic curve fitting
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
lo = 0.1;
hi = 0.5;
}
else {
// Perceptual and saturation
lo = 0.03;
hi = 0.25;
}
// Capture shadow points for the fitting.
n = 0;
for (l=0; l < 256; l++) {
cmsFloat64Number ff = yRamp[l];
if (ff >= lo && ff < hi) {
x[n] = inRamp[l];
y[n] = yRamp[l];
n++;
}
}
// No suitable points
if (n < 3 ) {
cmsDeleteTransform(hRoundTrip);
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
return FALSE;
}
// fit and get the vertex of quadratic curve
Lab.L = RootOfLeastSquaresFitQuadraticCurve(n, x, y);
if (Lab.L < 0.0) { // clip to zero L* if the vertex is negative
Lab.L = 0;
}
Lab.a = InitialLab.a;
Lab.b = InitialLab.b;
cmsLab2XYZ(NULL, BlackPoint, &Lab);
cmsDeleteTransform(hRoundTrip);
return TRUE;
}

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2011 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -36,7 +36,7 @@
// alpha = Hab
// theta = L*
#define SECTORS 16 // number of divisions in alpha and theta
#define SECTORS 16 // number of divisions in alpha and theta
// Spherical coordinates
typedef struct {
@@ -47,7 +47,7 @@ typedef struct {
} cmsSpherical;
typedef enum {
typedef enum {
GP_EMPTY,
GP_SPECIFIED,
GP_MODELED
@@ -101,7 +101,7 @@ static
cmsFloat64Number _cmsAtan2(cmsFloat64Number y, cmsFloat64Number x)
{
cmsFloat64Number a;
// Deal with undefined case
if (x == 0.0 && y == 0.0) return 0;
@@ -120,20 +120,20 @@ void ToSpherical(cmsSpherical* sp, const cmsVEC3* v)
{
cmsFloat64Number L, a, b;
L = v ->n[VX];
a = v ->n[VY];
b = v ->n[VZ];
sp ->r = sqrt( L*L + a*a + b*b );
if (sp ->r == 0) {
sp ->alpha = sp ->theta = 0;
return;
}
sp ->alpha = _cmsAtan2(a, b);
sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L);
sp ->alpha = _cmsAtan2(a, b);
sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L);
}
@@ -153,7 +153,7 @@ void ToCartesian(cmsVEC3* v, const cmsSpherical* sp)
cos_theta = cos((M_PI * sp ->theta) / 180.0);
a = sp ->r * sin_theta * sin_alpha;
b = sp ->r * sin_theta * cos_alpha;
b = sp ->r * sin_theta * cos_alpha;
L = sp ->r * cos_theta;
v ->n[VX] = L;
@@ -166,14 +166,14 @@ void ToCartesian(cmsVEC3* v, const cmsSpherical* sp)
// The limits are the centers of each sector, so
static
void QuantizeToSector(const cmsSpherical* sp, int* alpha, int* theta)
{
*alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) );
*theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) );
{
*alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) );
*theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) );
if (*alpha >= SECTORS)
*alpha = SECTORS-1;
if (*theta >= SECTORS)
*theta = SECTORS-1;
if (*alpha >= SECTORS)
*alpha = SECTORS-1;
if (*theta >= SECTORS)
*theta = SECTORS-1;
}
@@ -183,19 +183,19 @@ void LineOf2Points(cmsLine* line, cmsVEC3* a, cmsVEC3* b)
{
_cmsVEC3init(&line ->a, a ->n[VX], a ->n[VY], a ->n[VZ]);
_cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX],
b ->n[VY] - a ->n[VY],
b ->n[VZ] - a ->n[VZ]);
_cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX],
b ->n[VY] - a ->n[VY],
b ->n[VZ] - a ->n[VZ]);
}
// Evaluate parametric line
// Evaluate parametric line
static
void GetPointOfLine(cmsVEC3* p, const cmsLine* line, cmsFloat64Number t)
{
p ->n[VX] = line ->a.n[VX] + t * line->u.n[VX];
p ->n[VY] = line ->a.n[VY] + t * line->u.n[VY];
p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ];
p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ];
}
@@ -217,7 +217,7 @@ static
cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2)
{
cmsFloat64Number a, b, c, d, e, D;
cmsFloat64Number sc, sN, sD;
cmsFloat64Number sc, sN, sD;
cmsFloat64Number tc, tN, tD;
cmsVEC3 w0;
@@ -271,9 +271,9 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2
}
}
else if (tN > tD) { // tc > 1 => the t=1 edge is visible
tN = tD;
// recompute sc for this edge
if ((-d + b) < 0.0)
sN = 0;
@@ -302,7 +302,7 @@ cmsHANDLE CMSEXPORT cmsGBDAlloc(cmsContext ContextID)
{
cmsGDB* gbd = (cmsGDB*) _cmsMallocZero(ContextID, sizeof(cmsGDB));
if (gbd == NULL) return NULL;
gbd -> ContextID = ContextID;
return (cmsHANDLE) gbd;
@@ -310,9 +310,9 @@ cmsHANDLE CMSEXPORT cmsGBDAlloc(cmsContext ContextID)
void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD)
{
{
cmsGDB* gbd = (cmsGDB*) hGBD;
if (hGBD != NULL)
if (hGBD != NULL)
_cmsFree(gbd->ContextID, (void*) gbd);
}
@@ -321,20 +321,20 @@ void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD)
static
cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
{
cmsVEC3 v;
cmsVEC3 v;
int alpha, theta;
// Housekeeping
_cmsAssert(gbd != NULL);
_cmsAssert(Lab != NULL);
_cmsAssert(sp != NULL);
_cmsAssert(Lab != NULL);
_cmsAssert(sp != NULL);
// Center L* by substracting half of its domain, that's 50
// Center L* by substracting half of its domain, that's 50
_cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b);
// Convert to spherical coordinates
ToSpherical(sp, &v);
if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) {
cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range");
return NULL;
@@ -342,7 +342,7 @@ cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
// On which sector it falls?
QuantizeToSector(sp, &alpha, &theta);
if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) {
cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range");
return NULL;
@@ -352,7 +352,7 @@ cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
return &gbd ->Gamut[theta][alpha];
}
// Add a point to gamut descriptor. Point to add is in Lab color space.
// Add a point to gamut descriptor. Point to add is in Lab color space.
// GBD is centered on a=b=0 and L*=50
cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
{
@@ -388,7 +388,7 @@ cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
// Check if a given point falls inside gamut
cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
{
cmsGDB* gbd = (cmsGDB*) hGBD;
cmsGDB* gbd = (cmsGDB*) hGBD;
cmsGDBPoint* ptr;
cmsSpherical sp;
@@ -406,7 +406,7 @@ cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
// -----------------------------------------------------------------------------------------------------------------------
// Find near sectors. The list of sectors found is returned on Close[].
// Find near sectors. The list of sectors found is returned on Close[].
// The function returns the number of sectors as well.
// 24 9 10 11 12
@@ -416,21 +416,21 @@ cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
// 20 19 18 17 16
//
// Those are the relative movements
// {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
// {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
// {-2,-1}, {-1, -1}, {0, -1}, {+1, -1}, {+2, -1},
// {-2, 0}, {-1, 0}, {0, 0}, {+1, 0}, {+2, 0},
// {-2,+1}, {-1, +1}, {0, +1}, {+1, +1}, {+2, +1},
// {-2,+2}, {-1, +2}, {0, +2}, {+1, +2}, {+2, +2}};
static
const struct _spiral {
static
const struct _spiral {
int AdvX, AdvY;
} Spiral[] = { {0, -1}, {+1, -1}, {+1, 0}, {+1, +1}, {0, +1}, {-1, +1},
{-1, 0}, {-1, -1}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
{+2, -1}, {+2, 0}, {+2, +1}, {+2, +2}, {+1, +2}, {0, +2},
} Spiral[] = { {0, -1}, {+1, -1}, {+1, 0}, {+1, +1}, {0, +1}, {-1, +1},
{-1, 0}, {-1, -1}, {-1, -2}, {0, -2}, {+1, -2}, {+2, -2},
{+2, -1}, {+2, 0}, {+2, +1}, {+2, +2}, {+1, +2}, {0, +2},
{-1, +2}, {-2, +2}, {-2, +1}, {-2, 0}, {-2, -1}, {-2, -2} };
#define NSTEPS (sizeof(Spiral) / sizeof(struct _spiral))
@@ -439,7 +439,8 @@ static
int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
{
int nSectors = 0;
int i, a, t;
int a, t;
cmsUInt32Number i;
cmsGDBPoint* pt;
for (i=0; i < NSTEPS; i++) {
@@ -453,14 +454,14 @@ int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
// Cycle at the begin
if (a < 0) a = SECTORS + a;
if (t < 0) t = SECTORS + t;
if (t < 0) t = SECTORS + t;
pt = &gbd ->Gamut[t][a];
if (pt -> Type != GP_EMPTY) {
Close[nSectors++] = pt;
}
}
}
return nSectors;
@@ -470,17 +471,17 @@ int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
// Interpolate a missing sector. Method identifies whatever this is top, bottom or mid
static
cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
{
{
cmsSpherical sp;
cmsVEC3 Lab;
cmsVEC3 Centre;
cmsLine ray;
int nCloseSectors;
cmsGDBPoint* Close[NSTEPS];
cmsGDBPoint* Close[NSTEPS + 1];
cmsSpherical closel, templ;
cmsLine edge;
int k, m;
// Is that point already specified?
if (gbd ->Gamut[theta][alpha].Type != GP_EMPTY) return TRUE;
@@ -488,10 +489,10 @@ cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
nCloseSectors = FindNearSectors(gbd, alpha, theta, Close);
// Find a central point on the sector
// Find a central point on the sector
sp.alpha = (cmsFloat64Number) ((alpha + 0.5) * 360.0) / (SECTORS);
sp.theta = (cmsFloat64Number) ((theta + 0.5) * 180.0) / (SECTORS);
sp.r = 50.0;
sp.r = 50.0;
// Convert to Cartesian
ToCartesian(&Lab, &sp);
@@ -510,28 +511,28 @@ cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
for(m = k+1; m < nCloseSectors; m++) {
cmsVEC3 temp, a1, a2;
// A line from sector to sector
ToCartesian(&a1, &Close[k]->p);
ToCartesian(&a2, &Close[m]->p);
LineOf2Points(&edge, &a1, &a2);
// Find a line
// Find a line
ClosestLineToLine(&temp, &ray, &edge);
// Convert to spherical
ToSpherical(&templ, &temp);
if ( templ.r > closel.r &&
templ.theta >= (theta*180.0/SECTORS) &&
if ( templ.r > closel.r &&
templ.theta >= (theta*180.0/SECTORS) &&
templ.theta <= ((theta+1)*180.0/SECTORS) &&
templ.alpha >= (alpha*360.0/SECTORS) &&
templ.alpha <= ((alpha+1)*360.0/SECTORS)) {
closel = templ;
}
closel = templ;
}
}
}
@@ -553,13 +554,13 @@ cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags)
_cmsAssert(hGBD != NULL);
// Interpolate black
for (alpha = 0; alpha <= SECTORS; alpha++) {
for (alpha = 0; alpha < SECTORS; alpha++) {
if (!InterpolateMissingSector(gbd, alpha, 0)) return FALSE;
}
// Interpolate white
for (alpha = 0; alpha <= SECTORS; alpha++) {
for (alpha = 0; alpha < SECTORS; alpha++) {
if (!InterpolateMissingSector(gbd, alpha, SECTORS-1)) return FALSE;
}
@@ -567,7 +568,7 @@ cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags)
// Interpolate Mid
for (theta = 1; theta < SECTORS; theta++) {
for (alpha = 0; alpha <= SECTORS; alpha++) {
for (alpha = 0; alpha < SECTORS; alpha++) {
if (!InterpolateMissingSector(gbd, alpha, theta)) return FALSE;
}
@@ -600,34 +601,34 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
fprintf (fp, "#VRML V2.0 utf8\n");
// set the viewing orientation and distance
// set the viewing orientation and distance
fprintf (fp, "DEF CamTest Group {\n");
fprintf (fp, "\tchildren [\n");
fprintf (fp, "\t\tDEF Cameras Group {\n");
fprintf (fp, "\t\t\tchildren [\n");
fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n");
fprintf (fp, "\t\t\t\t\tposition 0 0 340\n");
fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n");
fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n");
fprintf (fp, "\t\t\t\t}\n");
fprintf (fp, "\t\t\t]\n");
fprintf (fp, "\t\t},\n");
fprintf (fp, "\t]\n");
fprintf (fp, "}\n");
fprintf (fp, "\tchildren [\n");
fprintf (fp, "\t\tDEF Cameras Group {\n");
fprintf (fp, "\t\t\tchildren [\n");
fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n");
fprintf (fp, "\t\t\t\t\tposition 0 0 340\n");
fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n");
fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n");
fprintf (fp, "\t\t\t\t}\n");
fprintf (fp, "\t\t\t]\n");
fprintf (fp, "\t\t},\n");
fprintf (fp, "\t]\n");
fprintf (fp, "}\n");
// Output the background stuff
// Output the background stuff
fprintf (fp, "Background {\n");
fprintf (fp, "\tskyColor [\n");
fprintf (fp, "\t\t.5 .5 .5\n");
fprintf (fp, "\t]\n");
fprintf (fp, "}\n");
// Output the shape stuff
// Output the shape stuff
fprintf (fp, "Transform {\n");
fprintf (fp, "\tscale .3 .3 .3\n");
fprintf (fp, "\tchildren [\n");
// Draw the axes as a shape:
// Draw the axes as a shape:
fprintf (fp, "\t\tShape {\n");
fprintf (fp, "\t\t\tappearance Appearance {\n");
fprintf (fp, "\t\t\t\tmaterial Material {\n");
@@ -651,7 +652,7 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
fprintf (fp, "\t\t\t}\n");
fprintf (fp, "\t\t}\n");
fprintf (fp, "\t\tShape {\n");
fprintf (fp, "\t\t\tappearance Appearance {\n");
fprintf (fp, "\t\t\t\tmaterial Material {\n");
@@ -661,8 +662,8 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
fprintf (fp, "\t\t\t\t}\n");
fprintf (fp, "\t\t\t}\n");
fprintf (fp, "\t\t\tgeometry PointSet {\n");
// fill in the points here
// fill in the points here
fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
fprintf (fp, "\t\t\t\t\tpoint [\n");
@@ -677,7 +678,7 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
fprintf (fp, "\t\t\t\t\t%g %g %g", v.n[0]+50, v.n[1], v.n[2]);
if ((j == SECTORS - 1) && (i == SECTORS - 1))
if ((j == SECTORS - 1) && (i == SECTORS - 1))
fprintf (fp, "]\n");
else
fprintf (fp, ",\n");
@@ -688,7 +689,7 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
// fill in the face colors
// fill in the face colors
fprintf (fp, "\t\t\t\tcolor Color {\n");
fprintf (fp, "\t\t\t\t\tcolor [\n");
@@ -696,30 +697,30 @@ cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
for (j=0; j < SECTORS; j++) {
cmsVEC3 v;
pt = &gbd ->Gamut[i][j];
ToCartesian(&v, &pt ->p);
if (pt ->Type == GP_EMPTY)
if (pt ->Type == GP_EMPTY)
fprintf (fp, "\t\t\t\t\t%g %g %g", 0.0, 0.0, 0.0);
else
if (pt ->Type == GP_MODELED)
fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, .5, .5);
else {
else {
fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, 1.0, 1.0);
}
}
if ((j == SECTORS - 1) && (i == SECTORS - 1))
if ((j == SECTORS - 1) && (i == SECTORS - 1))
fprintf (fp, "]\n");
else
fprintf (fp, ",\n");
}
fprintf (fp, "\t\t\t}\n");
fprintf (fp, "\t\t\t}\n");
fprintf (fp, "\t\t}\n");

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -35,7 +35,7 @@ cmsBool SetTextTags(cmsHPROFILE hProfile, const wchar_t* Description)
cmsMLU *DescriptionMLU, *CopyrightMLU;
cmsBool rc = FALSE;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
DescriptionMLU = cmsMLUalloc(ContextID, 1);
CopyrightMLU = cmsMLUalloc(ContextID, 1);
@@ -45,8 +45,8 @@ cmsBool SetTextTags(cmsHPROFILE hProfile, const wchar_t* Description)
if (!cmsMLUsetWide(CopyrightMLU, "en", "US", L"No copyright, use freely")) goto Error;
if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag, DescriptionMLU)) goto Error;
if (!cmsWriteTag(hProfile, cmsSigCopyrightTag, CopyrightMLU)) goto Error;
if (!cmsWriteTag(hProfile, cmsSigCopyrightTag, CopyrightMLU)) goto Error;
rc = TRUE;
Error:
@@ -57,7 +57,7 @@ Error:
cmsMLUfree(CopyrightMLU);
return rc;
}
static
cmsBool SetSeqDescTag(cmsHPROFILE hProfile, const char* Model)
@@ -72,10 +72,10 @@ cmsBool SetSeqDescTag(cmsHPROFILE hProfile, const char* Model)
Seq->seq[0].deviceModel = (cmsSignature) 0;
#ifdef CMS_DONT_USE_INT64
Seq->seq[0].attributes[0] = 0;
Seq->seq[0].attributes[1] = 0;
Seq->seq[0].attributes[0] = 0;
Seq->seq[0].attributes[1] = 0;
#else
Seq->seq[0].attributes = 0;
Seq->seq[0].attributes = 0;
#endif
Seq->seq[0].technology = (cmsTechnologySignature) 0;
@@ -84,11 +84,11 @@ cmsBool SetSeqDescTag(cmsHPROFILE hProfile, const char* Model)
cmsMLUsetASCII( Seq->seq[0].Model, cmsNoLanguage, cmsNoCountry, Model);
if (!_cmsWriteProfileSequence(hProfile, Seq)) goto Error;
rc = TRUE;
Error:
if (Seq)
if (Seq)
cmsFreeProfileSequenceDescription(Seq);
return rc;
@@ -103,7 +103,7 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
const cmsCIExyYTRIPLE* Primaries,
cmsToneCurve* const TransferFunction[3])
{
cmsHPROFILE hICC;
cmsHPROFILE hICC;
cmsMAT3 MColorants;
cmsCIEXYZTRIPLE Colorants;
cmsCIExyY MaxWhite;
@@ -114,13 +114,13 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.2);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigDisplayClass);
cmsSetColorSpace(hICC, cmsSigRgbData);
cmsSetPCS(hICC, cmsSigXYZData);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Implement profile using following tags:
@@ -137,7 +137,7 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
// This conforms a standard RGB DisplayProfile as says ICC, and then I add (As per addendum II)
// 10 cmsSigChromaticityTag
if (!SetTextTags(hICC, L"RGB built-in")) goto Error;
if (WhitePoint) {
@@ -145,9 +145,9 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
cmsxyY2XYZ(&WhitePointXYZ, WhitePoint);
_cmsAdaptationMatrix(&CHAD, NULL, &WhitePointXYZ, cmsD50_XYZ());
_cmsAdaptationMatrix(&CHAD, NULL, &WhitePointXYZ, cmsD50_XYZ());
// This is a V4 tag, but many CMM does read and understand it no matter which version
// This is a V4 tag, but many CMM does read and understand it no matter which version
if (!cmsWriteTag(hICC, cmsSigChromaticAdaptationTag, (void*) &CHAD)) goto Error;
}
@@ -157,8 +157,8 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
MaxWhite.y = WhitePoint -> y;
MaxWhite.Y = 1.0;
if (!_cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries)) goto Error;
if (!_cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries)) goto Error;
Colorants.Red.X = MColorants.v[0].n[0];
Colorants.Red.Y = MColorants.v[1].n[0];
Colorants.Red.Z = MColorants.v[2].n[0];
@@ -178,10 +178,27 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
if (TransferFunction) {
// Tries to minimize space. Thanks to Richard Hughes for this nice idea
if (!cmsWriteTag(hICC, cmsSigRedTRCTag, (void*) TransferFunction[0])) goto Error;
if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
if (TransferFunction[1] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigGreenTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
}
if (TransferFunction[2] == TransferFunction[0]) {
if (!cmsLinkTag (hICC, cmsSigBlueTRCTag, cmsSigRedTRCTag)) goto Error;
} else {
if (!cmsWriteTag(hICC, cmsSigBlueTRCTag, (void*) TransferFunction[2])) goto Error;
}
}
if (Primaries) {
@@ -212,18 +229,18 @@ cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
const cmsToneCurve* TransferFunction)
{
cmsHPROFILE hICC;
cmsCIEXYZ tmp;
cmsCIEXYZ tmp;
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.2);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigDisplayClass);
cmsSetColorSpace(hICC, cmsSigGrayData);
cmsSetPCS(hICC, cmsSigXYZData);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Implement profile using following tags:
@@ -232,7 +249,7 @@ cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
// 2 cmsSigMediaWhitePointTag
// 3 cmsSigGrayTRCTag
// This conforms a standard Gray DisplayProfile
// This conforms a standard Gray DisplayProfile
// Fill-in the tags
@@ -274,20 +291,19 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
{
cmsHPROFILE hICC;
cmsPipeline* Pipeline;
cmsStage* Lin;
int nChannels;
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC)
if (!hICC)
return NULL;
cmsSetProfileVersion(hICC, 4.2);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigLinkClass);
cmsSetColorSpace(hICC, ColorSpace);
cmsSetPCS(hICC, ColorSpace);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Set up channels
nChannels = cmsChannelsOf(ColorSpace);
@@ -298,14 +314,12 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
// Copy tables to Pipeline
Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions);
if (Lin == NULL) goto Error;
if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions)))
goto Error;
cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);
// Create tags
if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline)) goto Error;
// Create tags
if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline)) goto Error;
if (!SetSeqDescTag(hICC, "Linearization built-in")) goto Error;
// Pipeline is already on virtual profile
@@ -315,6 +329,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
return hICC;
Error:
cmsPipelineFree(Pipeline);
if (hICC)
cmsCloseProfile(hICC);
@@ -330,13 +345,13 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLink(cmsColorSpaceSignature Co
// Ink-limiting algorithm
//
// Sum = C + M + Y + K
// If Sum > InkLimit
// Sum = C + M + Y + K
// If Sum > InkLimit
// Ratio= 1 - (Sum - InkLimit) / (C + M + Y)
// if Ratio <0
// if Ratio <0
// Ratio=0
// endif
// Else
// endif
// Else
// Ratio=1
// endif
//
@@ -354,7 +369,7 @@ int InkLimitingSampler(register const cmsUInt16Number In[], register cmsUInt16Nu
InkLimit = (InkLimit * 655.35);
SumCMY = In[0] + In[1] + In[2];
SumCMYK = SumCMY + In[3];
SumCMYK = SumCMY + In[3];
if (SumCMYK > InkLimit) {
@@ -375,7 +390,7 @@ int InkLimitingSampler(register const cmsUInt16Number In[], register cmsUInt16Nu
// This is a devicelink operating in CMYK for ink-limiting
cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
cmsColorSpaceSignature ColorSpace,
cmsFloat64Number Limit)
{
@@ -383,7 +398,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
cmsPipeline* LUT;
cmsStage* CLUT;
int nChannels;
if (ColorSpace != cmsSigCmykData) {
cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
return NULL;
@@ -391,7 +406,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
if (Limit < 0.0 || Limit > 400) {
cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
if (Limit < 0) Limit = 0;
if (Limit > 400) Limit = 400;
@@ -401,37 +416,38 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.2);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigLinkClass);
cmsSetColorSpace(hICC, ColorSpace);
cmsSetPCS(hICC, ColorSpace);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Creates a Pipeline with 3D grid only
LUT = cmsPipelineAlloc(ContextID, 4, 4);
if (LUT == NULL) goto Error;
nChannels = cmsChannelsOf(ColorSpace);
CLUT = cmsStageAllocCLut16bit(ContextID, 17, nChannels, nChannels, NULL);
if (CLUT == NULL) goto Error;
if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels));
cmsPipelineInsertStage(LUT, cmsAT_END, CLUT);
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels));
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels)) ||
!cmsPipelineInsertStage(LUT, cmsAT_END, CLUT) ||
!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels)))
goto Error;
// Create tags
if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;
if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) LUT)) goto Error;
if (!SetSeqDescTag(hICC, "ink-limiting built-in")) goto Error;
// cmsPipeline is already on virtual profile
cmsPipelineFree(LUT);
@@ -457,9 +473,9 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature Colo
// Creates a fake Lab identity.
cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint)
{
cmsHPROFILE hProfile;
cmsHPROFILE hProfile;
cmsPipeline* LUT = NULL;
hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
if (hProfile == NULL) return NULL;
@@ -475,7 +491,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIE
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3));
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -503,13 +520,13 @@ cmsHPROFILE CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint)
// Creates a fake Lab V4 identity.
cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint)
{
cmsHPROFILE hProfile;
cmsHPROFILE hProfile;
cmsPipeline* LUT = NULL;
hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetProfileVersion(hProfile, 4.2);
cmsSetProfileVersion(hProfile, 4.3);
cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
cmsSetColorSpace(hProfile, cmsSigLabData);
@@ -521,7 +538,8 @@ cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIE
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -548,13 +566,13 @@ cmsHPROFILE CMSEXPORT cmsCreateLab4Profile(const cmsCIExyY* WhitePoint)
// Creates a fake XYZ identity
cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
{
cmsHPROFILE hProfile;
cmsHPROFILE hProfile;
cmsPipeline* LUT = NULL;
hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetProfileVersion(hProfile, 4.2);
cmsSetProfileVersion(hProfile, 4.3);
cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
cmsSetColorSpace(hProfile, cmsSigXYZData);
@@ -566,7 +584,8 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
LUT = cmsPipelineAlloc(ContextID, 3, 3);
if (LUT == NULL) goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3)))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
cmsPipelineFree(LUT);
@@ -615,12 +634,12 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
Parameters[1] = 1. / 1.055;
Parameters[2] = 0.055 / 1.055;
Parameters[3] = 1. / 12.92;
Parameters[4] = 0.04045;
Parameters[4] = 0.04045;
return cmsBuildParametricToneCurve(ContextID, 4, Parameters);
}
// Create the ICC virtual profile for sRGB space
// Create the ICC virtual profile for sRGB space
cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
{
cmsCIExyY D65;
@@ -631,11 +650,11 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
};
cmsToneCurve* Gamma22[3];
cmsHPROFILE hsRGB;
cmsWhitePointFromTemp(&D65, 6504);
Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
if (Gamma22[0] == NULL) return NULL;
hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22);
cmsFreeToneCurve(Gamma22[0]);
if (hsRGB == NULL) return NULL;
@@ -672,31 +691,31 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
cmsCIELCh LChIn, LChOut;
cmsCIEXYZ XYZ;
LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;
cmsLabEncoded2Float(&LabIn, In);
cmsLab2LCh(&LChIn, &LabIn);
// Do some adjusts on LCh
LChOut.L = LChIn.L * bchsw ->Contrast + bchsw ->Brightness;
LChOut.C = LChIn.C + bchsw -> Saturation;
LChOut.h = LChIn.h + bchsw -> Hue;
cmsLCh2Lab(&LabOut, &LChOut);
// Move white point in Lab
cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut);
cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ);
// Back to encoded
cmsFloat2LabEncoded(Out, &LabOut);
return TRUE;
}
@@ -705,101 +724,103 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
// contrast, Saturation and white point displacement
cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
int nLUTPoints,
cmsFloat64Number Bright,
cmsFloat64Number Contrast,
cmsFloat64Number Hue,
cmsFloat64Number Saturation,
int TempSrc,
int TempDest)
int nLUTPoints,
cmsFloat64Number Bright,
cmsFloat64Number Contrast,
cmsFloat64Number Hue,
cmsFloat64Number Saturation,
int TempSrc,
int TempDest)
{
cmsHPROFILE hICC;
cmsPipeline* Pipeline;
BCHSWADJUSTS bchsw;
cmsCIExyY WhitePnt;
cmsStage* CLUT;
cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
int i;
cmsHPROFILE hICC;
cmsPipeline* Pipeline;
BCHSWADJUSTS bchsw;
cmsCIExyY WhitePnt;
cmsStage* CLUT;
cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
int i;
bchsw.Brightness = Bright;
bchsw.Contrast = Contrast;
bchsw.Hue = Hue;
bchsw.Saturation = Saturation;
cmsWhitePointFromTemp(&WhitePnt, TempSrc );
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
cmsWhitePointFromTemp(&WhitePnt, TempDest);
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC) // can't allocate
return NULL;
bchsw.Brightness = Bright;
bchsw.Contrast = Contrast;
bchsw.Hue = Hue;
bchsw.Saturation = Saturation;
cmsWhitePointFromTemp(&WhitePnt, TempSrc );
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
cmsSetDeviceClass(hICC, cmsSigAbstractClass);
cmsSetColorSpace(hICC, cmsSigLabData);
cmsSetPCS(hICC, cmsSigLabData);
cmsWhitePointFromTemp(&WhitePnt, TempDest);
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC) // can't allocate
return NULL;
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
cmsSetDeviceClass(hICC, cmsSigAbstractClass);
cmsSetColorSpace(hICC, cmsSigLabData);
cmsSetPCS(hICC, cmsSigLabData);
// Creates a Pipeline with 3D grid only
Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
if (Pipeline == NULL) {
cmsCloseProfile(hICC);
return NULL;
}
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
if (CLUT == NULL) return NULL;
// Creates a Pipeline with 3D grid only
Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
if (Pipeline == NULL) {
cmsCloseProfile(hICC);
return NULL;
}
for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
if (CLUT == NULL) return NULL;
if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
// Shouldn't reach here
cmsPipelineFree(Pipeline);
cmsCloseProfile(hICC);
return NULL;
}
// Shouldn't reach here
goto Error;
}
cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT);
if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT)) {
goto Error;
}
// Create tags
if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
// Create tags
if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
// Pipeline is already on virtual profile
cmsPipelineFree(Pipeline);
cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
// Ok, done
return hICC;
cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
// Pipeline is already on virtual profile
cmsPipelineFree(Pipeline);
// Ok, done
return hICC;
Error:
cmsPipelineFree(Pipeline);
cmsCloseProfile(hICC);
return NULL;
}
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
cmsFloat64Number Bright,
cmsFloat64Number Bright,
cmsFloat64Number Contrast,
cmsFloat64Number Hue,
cmsFloat64Number Saturation,
int TempSrc,
int TempSrc,
int TempDest)
{
return cmsCreateBCHSWabstractProfileTHR(NULL, nLUTPoints, Bright, Contrast, Hue, Saturation, TempSrc, TempDest);
}
// Creates a fake NULL profile. This profile return 1 channel as always 0.
// Creates a fake NULL profile. This profile return 1 channel as always 0.
// Is useful only for gamut checking tricks
cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
{
cmsHPROFILE hProfile;
cmsHPROFILE hProfile;
cmsPipeline* LUT = NULL;
cmsStage* PostLin;
cmsToneCurve* EmptyTab;
@@ -809,11 +830,11 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
if (!hProfile) // can't allocate
return NULL;
cmsSetProfileVersion(hProfile, 4.2);
cmsSetProfileVersion(hProfile, 4.3);
if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;
if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;
cmsSetDeviceClass(hProfile, cmsSigOutputClass);
cmsSetColorSpace(hProfile, cmsSigGrayData);
@@ -823,16 +844,17 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
LUT = cmsPipelineAlloc(ContextID, 1, 1);
if (LUT == NULL) goto Error;
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
cmsFreeToneCurve(EmptyTab);
cmsPipelineInsertStage(LUT, cmsAT_END, PostLin);
if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
goto Error;
if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
cmsPipelineFree(LUT);
cmsPipelineFree(LUT);
return hProfile;
Error:
@@ -861,14 +883,14 @@ int IsPCS(cmsColorSpaceSignature ColorSpace)
static
void FixColorSpaces(cmsHPROFILE hProfile,
cmsColorSpaceSignature ColorSpace,
void FixColorSpaces(cmsHPROFILE hProfile,
cmsColorSpaceSignature ColorSpace,
cmsColorSpaceSignature PCS,
cmsUInt32Number dwFlags)
{
if (dwFlags & cmsFLAGS_GUESSDEVICECLASS) {
if (IsPCS(ColorSpace) && IsPCS(PCS)) {
if (IsPCS(ColorSpace) && IsPCS(PCS)) {
cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
cmsSetColorSpace(hProfile, ColorSpace);
@@ -880,7 +902,7 @@ void FixColorSpaces(cmsHPROFILE hProfile,
cmsSetDeviceClass(hProfile, cmsSigOutputClass);
cmsSetPCS(hProfile, ColorSpace);
cmsSetColorSpace(hProfile, PCS);
cmsSetColorSpace(hProfile, PCS);
return;
}
@@ -908,7 +930,7 @@ static
cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
{
_cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
cmsHPROFILE hICC = NULL;
cmsHPROFILE hICC = NULL;
int i, nColors;
cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;
@@ -922,7 +944,7 @@ cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
cmsSetPCS(hICC, cmsSigLabData);
// Tag profile with information
if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;
if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;
Original = cmsGetNamedColorList(xform);
if (Original == NULL) goto Error;
@@ -931,9 +953,14 @@ cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
nc2 = cmsDupNamedColorList(Original);
if (nc2 == NULL) goto Error;
// Colorant count now depends on the output space
// Colorant count now depends on the output space
nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut);
// Make sure we have proper formatters
cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX,
FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace))
| BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace)));
// Apply the transfor to colorants.
for (i=0; i < nColors; i++) {
cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
@@ -963,8 +990,9 @@ typedef struct {
static const cmsAllowedLUT AllowedLUTTypes[] = {
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
@@ -987,17 +1015,17 @@ cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut)
for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) {
if (n > Tab ->nTypes) return FALSE;
if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
}
return (n == Tab ->nTypes);
}
static
static
const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTagSignature DestinationTag)
{
int n;
cmsUInt32Number n;
for (n=0; n < SIZE_OF_ALLOWED_LUT; n++) {
@@ -1011,7 +1039,7 @@ const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTa
return NULL;
}
// Does convert a transform into a device link profile
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
@@ -1025,12 +1053,13 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
cmsContext ContextID = cmsGetTransformContextID(hTransform);
const cmsAllowedLUT* AllowedLUT;
cmsTagSignature DestinationTag;
cmsProfileClassSignature deviceClass;
_cmsAssert(hTransform != NULL);
// Get the first mpe to check for named color
mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);
// Check if is a named color transform
if (mpe != NULL) {
@@ -1046,22 +1075,24 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
// Time to fix the Lab2/Lab4 issue.
if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID));
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
goto Error;
}
// On the output side too
if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID));
if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
goto Error;
}
hProfile = cmsCreateProfilePlaceholder(ContextID);
if (!hProfile) goto Error; // can't allocate
if (!hProfile) goto Error; // can't allocate
cmsSetProfileVersion(hProfile, Version);
FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);
FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);
// Optimize the LUT and precalculate a devicelink
@@ -1074,8 +1105,9 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
FrmIn = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);
deviceClass = cmsGetDeviceClass(hProfile);
if (cmsGetDeviceClass(hProfile) == cmsSigOutputClass)
if (deviceClass == cmsSigOutputClass)
DestinationTag = cmsSigBToA0Tag;
else
DestinationTag = cmsSigAToB0Tag;
@@ -1084,12 +1116,12 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (dwFlags & cmsFLAGS_FORCE_CLUT)
AllowedLUT = NULL;
else
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
if (AllowedLUT == NULL) {
// Try to optimize
_cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
_cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
}
@@ -1098,14 +1130,16 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (AllowedLUT == NULL) {
dwFlags |= cmsFLAGS_FORCE_CLUT;
_cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
_cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
// Put identity curves if needed
if (cmsPipelineStageCount(LUT) == 1) {
if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn)))
goto Error;
cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn));
cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut));
}
if (cmsPipelineGetPtrToLastStage(LUT) ->Type != cmsSigCurveSetElemType)
if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, ChansOut)))
goto Error;
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
}
@@ -1116,16 +1150,16 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
}
if (dwFlags & cmsFLAGS_8BITS_DEVICELINK)
if (dwFlags & cmsFLAGS_8BITS_DEVICELINK)
cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE);
// Tag profile with information
if (!SetTextTags(hProfile, L"devicelink")) goto Error;
// Store result
if (!SetTextTags(hProfile, L"devicelink")) goto Error;
// Store result
if (!cmsWriteTag(hProfile, DestinationTag, LUT)) goto Error;
if (xform -> InputColorant != NULL) {
if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error;
}
@@ -1133,16 +1167,28 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (xform -> OutputColorant != NULL) {
if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
}
if (xform ->Sequence != NULL) {
if ((deviceClass == cmsSigLinkClass) && (xform ->Sequence != NULL)) {
if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
}
cmsPipelineFree(LUT);
// Set the white point
if (deviceClass == cmsSigInputClass) {
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->EntryWhitePoint)) goto Error;
}
else {
if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, &xform ->ExitWhitePoint)) goto Error;
}
// Per 7.2.15 in spec 4.3
cmsSetHeaderRenderingIntent(hProfile, xform ->RenderingIntent);
cmsPipelineFree(LUT);
return hProfile;
Error:
if (LUT != NULL) cmsPipelineFree(LUT);
if (LUT != NULL) cmsPipelineFree(LUT);
cmsCloseProfile(hProfile);
return NULL;
}

View File

@@ -1,24 +1,24 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// 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
// 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
// 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.
//
//---------------------------------------------------------------------------------
@@ -47,63 +47,63 @@ const cmsCIExyY* CMSEXPORT cmsD50_xyY(void)
// Obtains WhitePoint from Temperature
cmsBool CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK)
{
cmsFloat64Number x, y;
cmsFloat64Number T, T2, T3;
// cmsFloat64Number M1, M2;
cmsFloat64Number x, y;
cmsFloat64Number T, T2, T3;
// cmsFloat64Number M1, M2;
_cmsAssert(WhitePoint != NULL);
_cmsAssert(WhitePoint != NULL);
T = TempK;
T2 = T*T; // Square
T3 = T2*T; // Cube
T = TempK;
T2 = T*T; // Square
T3 = T2*T; // Cube
// For correlated color temperature (T) between 4000K and 7000K:
// For correlated color temperature (T) between 4000K and 7000K:
if (T >= 4000. && T <= 7000.)
{
x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
}
else
// or for correlated color temperature (T) between 7000K and 25000K:
if (T >= 4000. && T <= 7000.)
{
x = -4.6070*(1E9/T3) + 2.9678*(1E6/T2) + 0.09911*(1E3/T) + 0.244063;
}
else
// or for correlated color temperature (T) between 7000K and 25000K:
if (T > 7000.0 && T <= 25000.0)
{
x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
}
else {
cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
return FALSE;
}
if (T > 7000.0 && T <= 25000.0)
{
x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
}
else {
cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
return FALSE;
}
// Obtain y(x)
// Obtain y(x)
y = -3.000*(x*x) + 2.870*x - 0.275;
y = -3.000*(x*x) + 2.870*x - 0.275;
// wave factors (not used, but here for futures extensions)
// wave factors (not used, but here for futures extensions)
// M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
// M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
// M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
// M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
WhitePoint -> x = x;
WhitePoint -> y = y;
WhitePoint -> Y = 1.0;
WhitePoint -> x = x;
WhitePoint -> y = y;
WhitePoint -> Y = 1.0;
return TRUE;
return TRUE;
}
typedef struct {
cmsFloat64Number mirek; // temp (in microreciprocal kelvin)
cmsFloat64Number ut; // u coord of intersection w/ blackbody locus
cmsFloat64Number vt; // v coord of intersection w/ blackbody locus
cmsFloat64Number tt; // slope of ISOTEMPERATURE. line
cmsFloat64Number mirek; // temp (in microreciprocal kelvin)
cmsFloat64Number ut; // u coord of intersection w/ blackbody locus
cmsFloat64Number vt; // v coord of intersection w/ blackbody locus
cmsFloat64Number tt; // slope of ISOTEMPERATURE. line
} ISOTEMPERATURE;
static ISOTEMPERATURE isotempdata[] = {
// {Mirek, Ut, Vt, Tt }
// {Mirek, Ut, Vt, Tt }
{0, 0.18006, 0.26352, -0.24341},
{10, 0.18066, 0.26589, -0.25479},
{20, 0.18133, 0.26846, -0.26876},
@@ -143,50 +143,50 @@ static ISOTEMPERATURE isotempdata[] = {
// Robertson's method
cmsBool CMSEXPORT cmsTempFromWhitePoint(cmsFloat64Number* TempK, const cmsCIExyY* WhitePoint)
{
int j;
cmsFloat64Number us,vs;
cmsFloat64Number uj,vj,tj,di,dj,mi,mj;
cmsFloat64Number xs, ys;
cmsUInt32Number j;
cmsFloat64Number us,vs;
cmsFloat64Number uj,vj,tj,di,dj,mi,mj;
cmsFloat64Number xs, ys;
_cmsAssert(WhitePoint != NULL);
_cmsAssert(WhitePoint != NULL);
_cmsAssert(TempK != NULL);
di = mi = 0;
xs = WhitePoint -> x;
ys = WhitePoint -> y;
di = mi = 0;
xs = WhitePoint -> x;
ys = WhitePoint -> y;
// convert (x,y) to CIE 1960 (u,WhitePoint)
// convert (x,y) to CIE 1960 (u,WhitePoint)
us = (2*xs) / (-xs + 6*ys + 1.5);
vs = (3*ys) / (-xs + 6*ys + 1.5);
us = (2*xs) / (-xs + 6*ys + 1.5);
vs = (3*ys) / (-xs + 6*ys + 1.5);
for (j=0; j < NISO; j++) {
for (j=0; j < NISO; j++) {
uj = isotempdata[j].ut;
vj = isotempdata[j].vt;
tj = isotempdata[j].tt;
mj = isotempdata[j].mirek;
uj = isotempdata[j].ut;
vj = isotempdata[j].vt;
tj = isotempdata[j].tt;
mj = isotempdata[j].mirek;
dj = ((vs - vj) - tj * (us - uj)) / sqrt(1.0 + tj * tj);
dj = ((vs - vj) - tj * (us - uj)) / sqrt(1.0 + tj * tj);
if ((j != 0) && (di/dj < 0.0)) {
if ((j != 0) && (di/dj < 0.0)) {
// Found a match
*TempK = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
return TRUE;
}
// Found a match
*TempK = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
return TRUE;
}
di = dj;
mi = mj;
}
di = dj;
mi = mj;
}
// Not found
return FALSE;
// Not found
return FALSE;
}
// Compute chromatic adaptation matrix using Chad as cone matrix
// Compute chromatic adaptation matrix using Chad as cone matrix
static
cmsBool ComputeChromaticAdaptation(cmsMAT3* Conversion,
@@ -195,7 +195,7 @@ cmsBool ComputeChromaticAdaptation(cmsMAT3* Conversion,
const cmsMAT3* Chad)
{
cmsMAT3 Chad_Inv;
cmsVEC3 ConeSourceXYZ, ConeSourceRGB;
cmsVEC3 ConeDestXYZ, ConeDestRGB;
@@ -226,41 +226,41 @@ cmsBool ComputeChromaticAdaptation(cmsMAT3* Conversion,
_cmsMAT3per(&Tmp, &Cone, Chad);
_cmsMAT3per(Conversion, &Chad_Inv, &Tmp);
return TRUE;
return TRUE;
}
// Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll
// The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed
cmsBool _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll)
{
cmsMAT3 LamRigg = {{ // Bradford matrix
{{ 0.8951, 0.2664, -0.1614 }},
{{ -0.7502, 1.7135, 0.0367 }},
{{ 0.0389, -0.0685, 1.0296 }}
}};
cmsMAT3 LamRigg = {{ // Bradford matrix
{{ 0.8951, 0.2664, -0.1614 }},
{{ -0.7502, 1.7135, 0.0367 }},
{{ 0.0389, -0.0685, 1.0296 }}
}};
if (ConeMatrix == NULL)
ConeMatrix = &LamRigg;
if (ConeMatrix == NULL)
ConeMatrix = &LamRigg;
return ComputeChromaticAdaptation(r, FromIll, ToIll, ConeMatrix);
return ComputeChromaticAdaptation(r, FromIll, ToIll, ConeMatrix);
}
// Same as anterior, but assuming D50 destination. White point is given in xyY
static
cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt)
{
cmsCIEXYZ Dn;
cmsMAT3 Bradford;
cmsMAT3 Tmp;
cmsCIEXYZ Dn;
cmsMAT3 Bradford;
cmsMAT3 Tmp;
cmsxyY2XYZ(&Dn, SourceWhitePt);
cmsxyY2XYZ(&Dn, SourceWhitePt);
if (!_cmsAdaptationMatrix(&Bradford, NULL, &Dn, cmsD50_XYZ())) return FALSE;
if (!_cmsAdaptationMatrix(&Bradford, NULL, &Dn, cmsD50_XYZ())) return FALSE;
Tmp = *r;
_cmsMAT3per(r, &Bradford, &Tmp);
Tmp = *r;
_cmsMAT3per(r, &Bradford, &Tmp);
return TRUE;
return TRUE;
}
// Build a White point, primary chromas transfer matrix from RGB to CIE XYZ
@@ -278,74 +278,74 @@ cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt)
//
cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePt, const cmsCIExyYTRIPLE* Primrs)
{
cmsVEC3 WhitePoint, Coef;
cmsMAT3 Result, Primaries;
cmsFloat64Number xn, yn;
cmsFloat64Number xr, yr;
cmsFloat64Number xg, yg;
cmsFloat64Number xb, yb;
cmsVEC3 WhitePoint, Coef;
cmsMAT3 Result, Primaries;
cmsFloat64Number xn, yn;
cmsFloat64Number xr, yr;
cmsFloat64Number xg, yg;
cmsFloat64Number xb, yb;
xn = WhitePt -> x;
yn = WhitePt -> y;
xr = Primrs -> Red.x;
yr = Primrs -> Red.y;
xg = Primrs -> Green.x;
yg = Primrs -> Green.y;
xb = Primrs -> Blue.x;
yb = Primrs -> Blue.y;
xn = WhitePt -> x;
yn = WhitePt -> y;
xr = Primrs -> Red.x;
yr = Primrs -> Red.y;
xg = Primrs -> Green.x;
yg = Primrs -> Green.y;
xb = Primrs -> Blue.x;
yb = Primrs -> Blue.y;
// Build Primaries matrix
_cmsVEC3init(&Primaries.v[0], xr, xg, xb);
_cmsVEC3init(&Primaries.v[1], yr, yg, yb);
_cmsVEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg), (1-xb-yb));
// Build Primaries matrix
_cmsVEC3init(&Primaries.v[0], xr, xg, xb);
_cmsVEC3init(&Primaries.v[1], yr, yg, yb);
_cmsVEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg), (1-xb-yb));
// Result = Primaries ^ (-1) inverse matrix
if (!_cmsMAT3inverse(&Primaries, &Result))
return FALSE;
// Result = Primaries ^ (-1) inverse matrix
if (!_cmsMAT3inverse(&Primaries, &Result))
return FALSE;
_cmsVEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
_cmsVEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
// Across inverse primaries ...
_cmsMAT3eval(&Coef, &Result, &WhitePoint);
// Across inverse primaries ...
_cmsMAT3eval(&Coef, &Result, &WhitePoint);
// Give us the Coefs, then I build transformation matrix
_cmsVEC3init(&r -> v[0], Coef.n[VX]*xr, Coef.n[VY]*xg, Coef.n[VZ]*xb);
_cmsVEC3init(&r -> v[1], Coef.n[VX]*yr, Coef.n[VY]*yg, Coef.n[VZ]*yb);
_cmsVEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
// Give us the Coefs, then I build transformation matrix
_cmsVEC3init(&r -> v[0], Coef.n[VX]*xr, Coef.n[VY]*xg, Coef.n[VZ]*xb);
_cmsVEC3init(&r -> v[1], Coef.n[VX]*yr, Coef.n[VY]*yg, Coef.n[VZ]*yb);
_cmsVEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
return _cmsAdaptMatrixToD50(r, WhitePt);
return _cmsAdaptMatrixToD50(r, WhitePt);
}
// Adapts a color to a given illuminant. Original color is expected to have
// a SourceWhitePt white point.
cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result,
const cmsCIEXYZ* SourceWhitePt,
const cmsCIEXYZ* Illuminant,
const cmsCIEXYZ* Value)
// a SourceWhitePt white point.
cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result,
const cmsCIEXYZ* SourceWhitePt,
const cmsCIEXYZ* Illuminant,
const cmsCIEXYZ* Value)
{
cmsMAT3 Bradford;
cmsVEC3 In, Out;
cmsMAT3 Bradford;
cmsVEC3 In, Out;
_cmsAssert(Result != NULL);
_cmsAssert(SourceWhitePt != NULL);
_cmsAssert(Illuminant != NULL);
_cmsAssert(Value != NULL);
_cmsAssert(Result != NULL);
_cmsAssert(SourceWhitePt != NULL);
_cmsAssert(Illuminant != NULL);
_cmsAssert(Value != NULL);
if (!_cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant)) return FALSE;
if (!_cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant)) return FALSE;
_cmsVEC3init(&In, Value -> X, Value -> Y, Value -> Z);
_cmsMAT3eval(&Out, &Bradford, &In);
_cmsVEC3init(&In, Value -> X, Value -> Y, Value -> Z);
_cmsMAT3eval(&Out, &Bradford, &In);
Result -> X = Out.n[0];
Result -> Y = Out.n[1];
Result -> Z = Out.n[2];
Result -> X = Out.n[0];
Result -> Y = Out.n[1];
Result -> Z = Out.n[2];
return TRUE;
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,300 +1,341 @@
LIBRARY LCMS2.DLL
EXPORTS
_cms15Fixed16toDouble = _cms15Fixed16toDouble
_cms8Fixed8toDouble = _cms8Fixed8toDouble
cmsAdaptToIlluminant = cmsAdaptToIlluminant
_cmsAdjustEndianess16 = _cmsAdjustEndianess16
_cmsAdjustEndianess32 = _cmsAdjustEndianess32
_cmsAdjustEndianess64 = _cmsAdjustEndianess64
cmsAllocNamedColorList = cmsAllocNamedColorList
cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
cmsAppendNamedColor = cmsAppendNamedColor
cmsBFDdeltaE = cmsBFDdeltaE
cmsBuildGamma = cmsBuildGamma
cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
_cmsCalloc = _cmsCalloc
cmsChannelsOf = cmsChannelsOf
cmsCIE2000DeltaE = cmsCIE2000DeltaE
cmsCIE94DeltaE = cmsCIE94DeltaE
cmsCIECAM02Done = cmsCIECAM02Done
cmsCIECAM02Forward = cmsCIECAM02Forward
cmsCIECAM02Init = cmsCIECAM02Init
cmsCIECAM02Reverse = cmsCIECAM02Reverse
cmsCloseIOhandler = cmsCloseIOhandler
cmsCloseProfile = cmsCloseProfile
cmsCMCdeltaE = cmsCMCdeltaE
cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
cmsCreateExtendedTransform = cmsCreateExtendedTransform
cmsCreateGrayProfile = cmsCreateGrayProfile
cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
cmsCreateLab2Profile = cmsCreateLab2Profile
cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
cmsCreateLab4Profile = cmsCreateLab4Profile
cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
cmsCreateNULLProfile = cmsCreateNULLProfile
cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
cmsCreateProofingTransform = cmsCreateProofingTransform
cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
cmsCreateRGBProfile = cmsCreateRGBProfile
cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
cmsCreateTransform = cmsCreateTransform
cmsCreateTransformTHR = cmsCreateTransformTHR
cmsCreateXYZProfile = cmsCreateXYZProfile
cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
cmsD50_xyY = cmsD50_xyY
cmsD50_XYZ = cmsD50_XYZ
_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
_cmsDefaultICCintents = _cmsDefaultICCintents
cmsDeleteTransform = cmsDeleteTransform
cmsDeltaE = cmsDeltaE
cmsDetectBlackPoint = cmsDetectBlackPoint
cmsDetectTAC = cmsDetectTAC
cmsDesaturateLab = cmsDesaturateLab
cmsDoTransform = cmsDoTransform
_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
_cmsDupMem = _cmsDupMem
cmsDupNamedColorList = cmsDupNamedColorList
cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
cmsDupToneCurve = cmsDupToneCurve
_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
cmsEstimateGamma = cmsEstimateGamma
cmsEvalToneCurve16 = cmsEvalToneCurve16
cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
cmsfilelength = cmsfilelength
cmsFloat2LabEncoded = cmsFloat2LabEncoded
cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
_cmsFree = _cmsFree
cmsFreeNamedColorList = cmsFreeNamedColorList
cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
cmsFreeToneCurve = cmsFreeToneCurve
cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
cmsGBDAlloc = cmsGBDAlloc
cmsGBDFree = cmsGBDFree
cmsGDBAddPoint = cmsGDBAddPoint
cmsGDBCheckPoint = cmsGDBCheckPoint
cmsGDBCompute = cmsGDBCompute
cmsGetAlarmCodes = cmsGetAlarmCodes
cmsGetColorSpace = cmsGetColorSpace
cmsGetDeviceClass = cmsGetDeviceClass
cmsGetEncodedICCversion = cmsGetEncodedICCversion
cmsGetHeaderAttributes = cmsGetHeaderAttributes
cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
cmsGetHeaderFlags = cmsGetHeaderFlags
cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
cmsGetHeaderModel = cmsGetHeaderModel
cmsGetHeaderProfileID = cmsGetHeaderProfileID
cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
cmsGetNamedColorList = cmsGetNamedColorList
cmsGetPCS = cmsGetPCS
cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
cmsGetPostScriptCRD = cmsGetPostScriptCRD
cmsGetPostScriptCSA = cmsGetPostScriptCSA
cmsGetProfileInfo = cmsGetProfileInfo
cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
cmsGetProfileContextID = cmsGetProfileContextID
cmsGetProfileVersion = cmsGetProfileVersion
cmsGetSupportedIntents = cmsGetSupportedIntents
cmsGetTagCount = cmsGetTagCount
cmsGetTagSignature = cmsGetTagSignature
cmsGetTransformContextID = cmsGetTransformContextID
_cmsICCcolorSpace = _cmsICCcolorSpace
_cmsIOPrintf = _cmsIOPrintf
cmsIsCLUT = cmsIsCLUT
cmsIsIntentSupported = cmsIsIntentSupported
cmsIsMatrixShaper = cmsIsMatrixShaper
cmsIsTag = cmsIsTag
cmsIsToneCurveDescending = cmsIsToneCurveDescending
cmsIsToneCurveLinear = cmsIsToneCurveLinear
cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
cmsIT8Alloc = cmsIT8Alloc
cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
cmsIT8EnumProperties = cmsIT8EnumProperties
cmsIT8Free = cmsIT8Free
cmsIT8GetData = cmsIT8GetData
cmsIT8GetDataDbl = cmsIT8GetDataDbl
cmsIT8FindDataFormat = cmsIT8FindDataFormat
cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
cmsIT8GetPatchName = cmsIT8GetPatchName
cmsIT8GetProperty = cmsIT8GetProperty
cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
cmsIT8GetSheetType = cmsIT8GetSheetType
cmsIT8LoadFromFile = cmsIT8LoadFromFile
cmsIT8LoadFromMem = cmsIT8LoadFromMem
cmsIT8SaveToFile = cmsIT8SaveToFile
cmsIT8SaveToMem = cmsIT8SaveToMem
cmsIT8SetComment = cmsIT8SetComment
cmsIT8SetData = cmsIT8SetData
cmsIT8SetDataDbl = cmsIT8SetDataDbl
cmsIT8SetDataFormat = cmsIT8SetDataFormat
cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
cmsIT8SetSheetType = cmsIT8SetSheetType
cmsIT8SetTable = cmsIT8SetTable
cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
cmsIT8TableCount = cmsIT8TableCount
cmsJoinToneCurve = cmsJoinToneCurve
cmsLab2LCh = cmsLab2LCh
cmsLab2XYZ = cmsLab2XYZ
cmsLabEncoded2Float = cmsLabEncoded2Float
cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
cmsLCh2Lab = cmsLCh2Lab
_cmsLCMScolorSpace = _cmsLCMScolorSpace
cmsLinkTag = cmsLinkTag
cmsPipelineAlloc = cmsPipelineAlloc
cmsPipelineCat = cmsPipelineCat
cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
cmsPipelineDup = cmsPipelineDup
cmsPipelineStageCount = cmsPipelineStageCount
cmsPipelineEval16 = cmsPipelineEval16
cmsPipelineEvalFloat = cmsPipelineEvalFloat
cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
cmsPipelineFree = cmsPipelineFree
cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
cmsPipelineInputChannels = cmsPipelineInputChannels
cmsPipelineInsertStage = cmsPipelineInsertStage
cmsPipelineOutputChannels = cmsPipelineOutputChannels
cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
_cmsMalloc = _cmsMalloc
_cmsMallocZero = _cmsMallocZero
_cmsMAT3eval = _cmsMAT3eval
_cmsMAT3identity = _cmsMAT3identity
_cmsMAT3inverse = _cmsMAT3inverse
_cmsMAT3isIdentity = _cmsMAT3isIdentity
_cmsMAT3per = _cmsMAT3per
_cmsMAT3solve = _cmsMAT3solve
cmsMD5computeID = cmsMD5computeID
cmsMLUalloc = cmsMLUalloc
cmsMLUdup = cmsMLUdup
cmsMLUfree = cmsMLUfree
cmsMLUgetASCII = cmsMLUgetASCII
cmsMLUgetTranslation = cmsMLUgetTranslation
cmsMLUgetWide = cmsMLUgetWide
cmsMLUsetASCII = cmsMLUsetASCII
cmsMLUsetWide = cmsMLUsetWide
cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
cmsStageAllocToneCurves = cmsStageAllocToneCurves
cmsStageAllocIdentity = cmsStageAllocIdentity
cmsStageAllocMatrix = cmsStageAllocMatrix
_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
cmsStageDup = cmsStageDup
cmsStageFree = cmsStageFree
cmsStageNext = cmsStageNext
cmsStageInputChannels = cmsStageInputChannels
cmsStageOutputChannels = cmsStageOutputChannels
cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
cmsStageType = cmsStageType
cmsStageData = cmsStageData
cmsNamedColorCount = cmsNamedColorCount
cmsNamedColorIndex = cmsNamedColorIndex
cmsNamedColorInfo = cmsNamedColorInfo
cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
cmsOpenProfileFromFile = cmsOpenProfileFromFile
cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
cmsOpenProfileFromMem = cmsOpenProfileFromMem
cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
cmsOpenProfileFromStream = cmsOpenProfileFromStream
cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
cmsPlugin = cmsPlugin
_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
_cmsReadAlignment = _cmsReadAlignment
_cmsReadFloat32Number = _cmsReadFloat32Number
cmsReadRawTag = cmsReadRawTag
cmsReadTag = cmsReadTag
_cmsReadTypeBase = _cmsReadTypeBase
_cmsReadUInt16Array = _cmsReadUInt16Array
_cmsReadUInt16Number = _cmsReadUInt16Number
_cmsReadUInt32Number = _cmsReadUInt32Number
_cmsReadUInt64Number = _cmsReadUInt64Number
_cmsReadUInt8Number = _cmsReadUInt8Number
_cmsReadXYZNumber = _cmsReadXYZNumber
_cmsRealloc = _cmsRealloc
cmsReverseToneCurve = cmsReverseToneCurve
cmsReverseToneCurveEx = cmsReverseToneCurveEx
cmsSaveProfileToFile = cmsSaveProfileToFile
cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
cmsSaveProfileToMem = cmsSaveProfileToMem
cmsSaveProfileToStream = cmsSaveProfileToStream
cmsSetAdaptationState = cmsSetAdaptationState
cmsSetAlarmCodes = cmsSetAlarmCodes
cmsSetColorSpace = cmsSetColorSpace
cmsSetDeviceClass = cmsSetDeviceClass
cmsSetEncodedICCversion = cmsSetEncodedICCversion
cmsSetHeaderAttributes = cmsSetHeaderAttributes
cmsSetHeaderFlags = cmsSetHeaderFlags
cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
cmsSetHeaderModel = cmsSetHeaderModel
cmsSetHeaderProfileID = cmsSetHeaderProfileID
cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
cmsSetLogErrorHandler = cmsSetLogErrorHandler
cmsSetPCS = cmsSetPCS
cmsSetProfileVersion = cmsSetProfileVersion
cmsSignalError = cmsSignalError
cmsSmoothToneCurve = cmsSmoothToneCurve
cmsstrcasecmp = cmsstrcasecmp
cmsTempFromWhitePoint = cmsTempFromWhitePoint
cmsTransform2DeviceLink = cmsTransform2DeviceLink
cmsUnregisterPlugins = cmsUnregisterPlugins
_cmsVEC3cross = _cmsVEC3cross
_cmsVEC3distance = _cmsVEC3distance
_cmsVEC3dot = _cmsVEC3dot
_cmsVEC3init = _cmsVEC3init
_cmsVEC3length = _cmsVEC3length
_cmsVEC3minus = _cmsVEC3minus
cmsWhitePointFromTemp = cmsWhitePointFromTemp
_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
_cmsWriteAlignment = _cmsWriteAlignment
_cmsWriteFloat32Number = _cmsWriteFloat32Number
cmsWriteRawTag = cmsWriteRawTag
cmsWriteTag = cmsWriteTag
_cmsWriteTypeBase = _cmsWriteTypeBase
_cmsWriteUInt16Array = _cmsWriteUInt16Array
_cmsWriteUInt16Number = _cmsWriteUInt16Number
_cmsWriteUInt32Number = _cmsWriteUInt32Number
_cmsWriteUInt64Number = _cmsWriteUInt64Number
_cmsWriteUInt8Number = _cmsWriteUInt8Number
_cmsWriteXYZNumber = _cmsWriteXYZNumber
cmsxyY2XYZ = cmsxyY2XYZ
cmsXYZ2Lab = cmsXYZ2Lab
cmsXYZ2xyY = cmsXYZ2xyY
cmsXYZEncoded2Float = cmsXYZEncoded2Float
cmsSliceSpace16 = cmsSliceSpace16
cmsSliceSpaceFloat = cmsSliceSpaceFloat
cmsChangeBuffersFormat = cmsChangeBuffersFormat
LIBRARY LCMS2.DLL
EXPORTS
_cms15Fixed16toDouble = _cms15Fixed16toDouble
_cms8Fixed8toDouble = _cms8Fixed8toDouble
cmsAdaptToIlluminant = cmsAdaptToIlluminant
_cmsAdjustEndianess16 = _cmsAdjustEndianess16
_cmsAdjustEndianess32 = _cmsAdjustEndianess32
_cmsAdjustEndianess64 = _cmsAdjustEndianess64
cmsAllocNamedColorList = cmsAllocNamedColorList
cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
cmsAppendNamedColor = cmsAppendNamedColor
cmsBFDdeltaE = cmsBFDdeltaE
cmsBuildGamma = cmsBuildGamma
cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
_cmsCalloc = _cmsCalloc
cmsChannelsOf = cmsChannelsOf
cmsCIE2000DeltaE = cmsCIE2000DeltaE
cmsCIE94DeltaE = cmsCIE94DeltaE
cmsCIECAM02Done = cmsCIECAM02Done
cmsCIECAM02Forward = cmsCIECAM02Forward
cmsCIECAM02Init = cmsCIECAM02Init
cmsCIECAM02Reverse = cmsCIECAM02Reverse
cmsCloseIOhandler = cmsCloseIOhandler
cmsCloseProfile = cmsCloseProfile
cmsCMCdeltaE = cmsCMCdeltaE
cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
cmsCreateExtendedTransform = cmsCreateExtendedTransform
cmsCreateGrayProfile = cmsCreateGrayProfile
cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
cmsCreateLab2Profile = cmsCreateLab2Profile
cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
cmsCreateLab4Profile = cmsCreateLab4Profile
cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
cmsCreateNULLProfile = cmsCreateNULLProfile
cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
cmsCreateProofingTransform = cmsCreateProofingTransform
cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
cmsCreateRGBProfile = cmsCreateRGBProfile
cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
cmsCreateTransform = cmsCreateTransform
cmsCreateTransformTHR = cmsCreateTransformTHR
cmsCreateXYZProfile = cmsCreateXYZProfile
cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
cmsD50_xyY = cmsD50_xyY
cmsD50_XYZ = cmsD50_XYZ
_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
_cmsDefaultICCintents = _cmsDefaultICCintents
cmsDeleteTransform = cmsDeleteTransform
cmsDeltaE = cmsDeltaE
cmsDetectBlackPoint = cmsDetectBlackPoint
cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint
cmsDetectTAC = cmsDetectTAC
cmsDesaturateLab = cmsDesaturateLab
cmsDoTransform = cmsDoTransform
cmsDoTransformStride = cmsDoTransformStride
_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
_cmsDupMem = _cmsDupMem
cmsDupNamedColorList = cmsDupNamedColorList
cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
cmsDupToneCurve = cmsDupToneCurve
_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
cmsEstimateGamma = cmsEstimateGamma
cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries
cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable
cmsEvalToneCurve16 = cmsEvalToneCurve16
cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
cmsfilelength = cmsfilelength
cmsFloat2LabEncoded = cmsFloat2LabEncoded
cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
_cmsFree = _cmsFree
cmsFreeNamedColorList = cmsFreeNamedColorList
cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
cmsFreeToneCurve = cmsFreeToneCurve
cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
cmsGBDAlloc = cmsGBDAlloc
cmsGBDFree = cmsGBDFree
cmsGDBAddPoint = cmsGDBAddPoint
cmsGDBCheckPoint = cmsGDBCheckPoint
cmsGDBCompute = cmsGDBCompute
cmsGetAlarmCodes = cmsGetAlarmCodes
cmsGetColorSpace = cmsGetColorSpace
cmsGetDeviceClass = cmsGetDeviceClass
cmsGetEncodedICCversion = cmsGetEncodedICCversion
cmsGetHeaderAttributes = cmsGetHeaderAttributes
cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
cmsGetHeaderFlags = cmsGetHeaderFlags
cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
cmsGetHeaderModel = cmsGetHeaderModel
cmsGetHeaderProfileID = cmsGetHeaderProfileID
cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
cmsGetNamedColorList = cmsGetNamedColorList
cmsGetPCS = cmsGetPCS
cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
cmsGetPostScriptCRD = cmsGetPostScriptCRD
cmsGetPostScriptCSA = cmsGetPostScriptCSA
cmsGetProfileInfo = cmsGetProfileInfo
cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
cmsGetProfileContextID = cmsGetProfileContextID
cmsGetProfileVersion = cmsGetProfileVersion
cmsGetSupportedIntents = cmsGetSupportedIntents
cmsGetTagCount = cmsGetTagCount
cmsGetTagSignature = cmsGetTagSignature
cmsGetTransformContextID = cmsGetTransformContextID
_cmsICCcolorSpace = _cmsICCcolorSpace
_cmsIOPrintf = _cmsIOPrintf
cmsIsCLUT = cmsIsCLUT
cmsIsIntentSupported = cmsIsIntentSupported
cmsIsMatrixShaper = cmsIsMatrixShaper
cmsIsTag = cmsIsTag
cmsIsToneCurveDescending = cmsIsToneCurveDescending
cmsIsToneCurveLinear = cmsIsToneCurveLinear
cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
cmsIT8Alloc = cmsIT8Alloc
cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
cmsIT8EnumProperties = cmsIT8EnumProperties
cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti
cmsIT8Free = cmsIT8Free
cmsIT8GetData = cmsIT8GetData
cmsIT8GetDataDbl = cmsIT8GetDataDbl
cmsIT8FindDataFormat = cmsIT8FindDataFormat
cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
cmsIT8GetPatchName = cmsIT8GetPatchName
cmsIT8GetPatchByName = cmsIT8GetPatchByName
cmsIT8GetProperty = cmsIT8GetProperty
cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti
cmsIT8GetSheetType = cmsIT8GetSheetType
cmsIT8LoadFromFile = cmsIT8LoadFromFile
cmsIT8LoadFromMem = cmsIT8LoadFromMem
cmsIT8SaveToFile = cmsIT8SaveToFile
cmsIT8SaveToMem = cmsIT8SaveToMem
cmsIT8SetComment = cmsIT8SetComment
cmsIT8SetData = cmsIT8SetData
cmsIT8SetDataDbl = cmsIT8SetDataDbl
cmsIT8SetDataFormat = cmsIT8SetDataFormat
cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti
cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
cmsIT8SetSheetType = cmsIT8SetSheetType
cmsIT8SetTable = cmsIT8SetTable
cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
cmsIT8SetIndexColumn = cmsIT8SetIndexColumn
cmsIT8TableCount = cmsIT8TableCount
cmsJoinToneCurve = cmsJoinToneCurve
cmsLab2LCh = cmsLab2LCh
cmsLab2XYZ = cmsLab2XYZ
cmsLabEncoded2Float = cmsLabEncoded2Float
cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
cmsLCh2Lab = cmsLCh2Lab
_cmsLCMScolorSpace = _cmsLCMScolorSpace
cmsLinkTag = cmsLinkTag
cmsTagLinkedTo = cmsTagLinkedTo
cmsPipelineAlloc = cmsPipelineAlloc
cmsPipelineCat = cmsPipelineCat
cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
cmsPipelineDup = cmsPipelineDup
cmsPipelineStageCount = cmsPipelineStageCount
cmsPipelineEval16 = cmsPipelineEval16
cmsPipelineEvalFloat = cmsPipelineEvalFloat
cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
cmsPipelineFree = cmsPipelineFree
cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
cmsPipelineInputChannels = cmsPipelineInputChannels
cmsPipelineInsertStage = cmsPipelineInsertStage
cmsPipelineOutputChannels = cmsPipelineOutputChannels
cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
_cmsMalloc = _cmsMalloc
_cmsMallocZero = _cmsMallocZero
_cmsMAT3eval = _cmsMAT3eval
_cmsMAT3identity = _cmsMAT3identity
_cmsMAT3inverse = _cmsMAT3inverse
_cmsMAT3isIdentity = _cmsMAT3isIdentity
_cmsMAT3per = _cmsMAT3per
_cmsMAT3solve = _cmsMAT3solve
cmsMD5computeID = cmsMD5computeID
cmsMLUalloc = cmsMLUalloc
cmsMLUdup = cmsMLUdup
cmsMLUfree = cmsMLUfree
cmsMLUgetASCII = cmsMLUgetASCII
cmsMLUgetTranslation = cmsMLUgetTranslation
cmsMLUgetWide = cmsMLUgetWide
cmsMLUsetASCII = cmsMLUsetASCII
cmsMLUsetWide = cmsMLUsetWide
cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
cmsStageAllocToneCurves = cmsStageAllocToneCurves
cmsStageAllocIdentity = cmsStageAllocIdentity
cmsStageAllocMatrix = cmsStageAllocMatrix
_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
cmsStageDup = cmsStageDup
cmsStageFree = cmsStageFree
cmsStageNext = cmsStageNext
cmsStageInputChannels = cmsStageInputChannels
cmsStageOutputChannels = cmsStageOutputChannels
cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
cmsStageType = cmsStageType
cmsStageData = cmsStageData
cmsNamedColorCount = cmsNamedColorCount
cmsNamedColorIndex = cmsNamedColorIndex
cmsNamedColorInfo = cmsNamedColorInfo
cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
cmsOpenProfileFromFile = cmsOpenProfileFromFile
cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
cmsOpenProfileFromMem = cmsOpenProfileFromMem
cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
cmsOpenProfileFromStream = cmsOpenProfileFromStream
cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
cmsPlugin = cmsPlugin
_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
_cmsReadAlignment = _cmsReadAlignment
_cmsReadFloat32Number = _cmsReadFloat32Number
cmsReadRawTag = cmsReadRawTag
cmsReadTag = cmsReadTag
_cmsReadTypeBase = _cmsReadTypeBase
_cmsReadUInt16Array = _cmsReadUInt16Array
_cmsReadUInt16Number = _cmsReadUInt16Number
_cmsReadUInt32Number = _cmsReadUInt32Number
_cmsReadUInt64Number = _cmsReadUInt64Number
_cmsReadUInt8Number = _cmsReadUInt8Number
_cmsReadXYZNumber = _cmsReadXYZNumber
_cmsRealloc = _cmsRealloc
cmsReverseToneCurve = cmsReverseToneCurve
cmsReverseToneCurveEx = cmsReverseToneCurveEx
cmsSaveProfileToFile = cmsSaveProfileToFile
cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
cmsSaveProfileToMem = cmsSaveProfileToMem
cmsSaveProfileToStream = cmsSaveProfileToStream
cmsSetAdaptationState = cmsSetAdaptationState
cmsSetAlarmCodes = cmsSetAlarmCodes
cmsSetColorSpace = cmsSetColorSpace
cmsSetDeviceClass = cmsSetDeviceClass
cmsSetEncodedICCversion = cmsSetEncodedICCversion
cmsSetHeaderAttributes = cmsSetHeaderAttributes
cmsSetHeaderFlags = cmsSetHeaderFlags
cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
cmsSetHeaderModel = cmsSetHeaderModel
cmsSetHeaderProfileID = cmsSetHeaderProfileID
cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
cmsSetLogErrorHandler = cmsSetLogErrorHandler
cmsSetPCS = cmsSetPCS
cmsSetProfileVersion = cmsSetProfileVersion
cmsSignalError = cmsSignalError
cmsSmoothToneCurve = cmsSmoothToneCurve
cmsstrcasecmp = cmsstrcasecmp
cmsTempFromWhitePoint = cmsTempFromWhitePoint
cmsTransform2DeviceLink = cmsTransform2DeviceLink
cmsUnregisterPlugins = cmsUnregisterPlugins
_cmsVEC3cross = _cmsVEC3cross
_cmsVEC3distance = _cmsVEC3distance
_cmsVEC3dot = _cmsVEC3dot
_cmsVEC3init = _cmsVEC3init
_cmsVEC3length = _cmsVEC3length
_cmsVEC3minus = _cmsVEC3minus
cmsWhitePointFromTemp = cmsWhitePointFromTemp
_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
_cmsWriteAlignment = _cmsWriteAlignment
_cmsWriteFloat32Number = _cmsWriteFloat32Number
cmsWriteRawTag = cmsWriteRawTag
cmsWriteTag = cmsWriteTag
_cmsWriteTypeBase = _cmsWriteTypeBase
_cmsWriteUInt16Array = _cmsWriteUInt16Array
_cmsWriteUInt16Number = _cmsWriteUInt16Number
_cmsWriteUInt32Number = _cmsWriteUInt32Number
_cmsWriteUInt64Number = _cmsWriteUInt64Number
_cmsWriteUInt8Number = _cmsWriteUInt8Number
_cmsWriteXYZNumber = _cmsWriteXYZNumber
cmsxyY2XYZ = cmsxyY2XYZ
cmsXYZ2Lab = cmsXYZ2Lab
cmsXYZ2xyY = cmsXYZ2xyY
cmsXYZEncoded2Float = cmsXYZEncoded2Float
cmsSliceSpace16 = cmsSliceSpace16
cmsSliceSpaceFloat = cmsSliceSpaceFloat
cmsChangeBuffersFormat = cmsChangeBuffersFormat
cmsDictAlloc = cmsDictAlloc
cmsDictFree = cmsDictFree
cmsDictDup = cmsDictDup
cmsDictAddEntry = cmsDictAddEntry
cmsDictGetEntryList = cmsDictGetEntryList
cmsDictNextEntry = cmsDictNextEntry
_cmsGetTransformUserData = _cmsGetTransformUserData
_cmsSetTransformUserData = _cmsSetTransformUserData
_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16
_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat
cmsGetHeaderCreator = cmsGetHeaderCreator
cmsPluginTHR = cmsPluginTHR
cmsGetPipelineContextID = cmsGetPipelineContextID
cmsGetTransformInputFormat = cmsGetTransformInputFormat
cmsGetTransformOutputFormat = cmsGetTransformOutputFormat
cmsCreateContext = cmsCreateContext
cmsDupContext = cmsDupContext
cmsDeleteContext = cmsDeleteContext
cmsGetContextUserData = cmsGetContextUserData
cmsUnregisterPluginsTHR = cmsUnregisterPluginsTHR
cmsSetAlarmCodesTHR = cmsSetAlarmCodesTHR
cmsGetAlarmCodesTHR = cmsGetAlarmCodesTHR
cmsSetAdaptationStateTHR = cmsSetAdaptationStateTHR
cmsSetLogErrorHandlerTHR = cmsSetLogErrorHandlerTHR
cmsGetSupportedIntentsTHR = cmsGetSupportedIntentsTHR
cmsMLUtranslationsCount = cmsMLUtranslationsCount
cmsMLUtranslationsCodes = cmsMLUtranslationsCodes
_cmsCreateMutex = _cmsCreateMutex
_cmsDestroyMutex = _cmsDestroyMutex
_cmsLockMutex = _cmsLockMutex
_cmsUnlockMutex = _cmsUnlockMutex

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ INCLUDE_DIRECTORIES(
FILE(GLOB SRCS *.c)
FILE(GLOB HDRS *.h)
SET(EXT_HDRS
SET(EXT_HDRS
${OPENJPEG_SOURCE_DIR}/thirdparty/include/zlib.h
${OPENJPEG_SOURCE_DIR}/thirdparty/include/zconf.h
)
@@ -23,7 +23,7 @@ ENDIF(MSVC)
TARGET_LINK_LIBRARIES(${LIBTARGET} ${Z_LIBNAME} ${M_LIBRARY})
#
SET_TARGET_PROPERTIES(${LIBTARGET}
PROPERTIES
PROPERTIES
OUTPUT_NAME "${LIBTARGET}"
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/thirdparty/lib)
#

View File

@@ -10,8 +10,8 @@ this sentence.
This code is released under the libpng license.
libpng versions 1.2.6, August 15, 2004, through 1.4.4, September 23, 2010, are
Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
libpng versions 1.2.6, August 15, 2004, through 1.6.17, March 26, 2015, are
Copyright (c) 2004, 2006-2015 Glenn Randers-Pehrson, and are
distributed according to the same disclaimer and license as libpng-1.2.5
with the following individual added to the list of Contributing Authors
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative.
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
September 23, 2010
March 26, 2015

View File

@@ -1,838 +0,0 @@
#if 0 /* in case someone actually tries to compile this */
/* example.c - an example of using libpng
* Last changed in libpng 1.4.2 [May 6, 2010]
* This file has been placed in the public domain by the authors.
* Maintained 1998-2010 Glenn Randers-Pehrson
* Maintained 1996, 1997 Andreas Dilger)
* Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*/
/* This is an example of how to use libpng to read and write PNG files.
* The file libpng.txt is much more verbose then this. If you have not
* read it, do so first. This was designed to be a starting point of an
* implementation. This is not officially part of libpng, is hereby placed
* in the public domain, and therefore does not require a copyright notice.
*
* This file does not currently compile, because it is missing certain
* parts, like allocating memory to hold an image. You will have to
* supply these parts to get it to compile. For an example of a minimal
* working PNG reader/writer, see pngtest.c, included in this distribution;
* see also the programs in the contrib directory.
*/
#include "png.h"
/* The png_jmpbuf() macro, used in error handling, became available in
* libpng version 1.0.6. If you want to be able to run your code with older
* versions of libpng, you must define the macro yourself (but only if it
* is not already defined by libpng!).
*/
#ifndef png_jmpbuf
# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
#endif
/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
* returns zero if the image is a PNG and nonzero if it isn't a PNG.
*
* The function check_if_png() shown here, but not used, returns nonzero (true)
* if the file can be opened and is a PNG, 0 (false) otherwise.
*
* If this call is successful, and you are going to keep the file open,
* you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
* you have created the png_ptr, so that libpng knows your application
* has read that many bytes from the start of the file. Make sure you
* don't call png_set_sig_bytes() with more than 8 bytes read or give it
* an incorrect number of bytes read, or you will either have read too
* many bytes (your fault), or you are telling libpng to read the wrong
* number of magic bytes (also your fault).
*
* Many applications already read the first 2 or 4 bytes from the start
* of the image to determine the file type, so it would be easiest just
* to pass the bytes to png_sig_cmp() or even skip that if you know
* you have a PNG file, and call png_set_sig_bytes().
*/
#define PNG_BYTES_TO_CHECK 4
int check_if_png(char *file_name, FILE **fp)
{
char buf[PNG_BYTES_TO_CHECK];
/* Open the prospective PNG file. */
if ((*fp = fopen(file_name, "rb")) == NULL)
return 0;
/* Read in some of the signature bytes */
if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
return 0;
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
Return nonzero (true) if they match */
return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}
/* Read a PNG file. You may want to return an error code if the read
* fails (depending upon the failure). There are two "prototypes" given
* here - one where we are given the filename, and we need to open the
* file, and the other where we are given an open file (possibly with
* some or all of the magic bytes read - see comments above).
*/
#ifdef open_file /* prototype 1 */
void read_png(char *file_name) /* We need to open the file */
{
png_structp png_ptr;
png_infop info_ptr;
unsigned int sig_read = 0;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
FILE *fp;
if ((fp = fopen(file_name, "rb")) == NULL)
return (ERROR);
#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
{
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
#endif no_open_file /* Only use one prototype! */
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
* you can supply NULL for the last three parameters. We also supply the
* the compiler header file version, so that we know if the application
* was compiled with a compatible version of the library. REQUIRED
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
png_voidp user_error_ptr, user_error_fn, user_warning_fn);
if (png_ptr == NULL)
{
fclose(fp);
return (ERROR);
}
/* Allocate/initialize the memory for image information. REQUIRED. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
fclose(fp);
png_destroy_read_struct(&png_ptr, NULL, NULL);
return (ERROR);
}
/* Set error handling if you are using the setjmp/longjmp method (this is
* the normal method of doing things with libpng). REQUIRED unless you
* set up your own error handlers in the png_create_read_struct() earlier.
*/
if (setjmp(png_jmpbuf(png_ptr)))
{
/* Free all of the memory associated with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
/* If we get here, we had a problem reading the file */
return (ERROR);
}
/* One of the following I/O initialization methods is REQUIRED */
#ifdef streams /* PNG file I/O method 1 */
/* Set up the input control if you are using standard C streams */
png_init_io(png_ptr, fp);
#else no_streams /* PNG file I/O method 2 */
/* If you are using replacement read functions, instead of calling
* png_init_io() here you would call:
*/
png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
/* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Use only one I/O method! */
/* If we have already read some of the signature */
png_set_sig_bytes(png_ptr, sig_read);
#ifdef hilevel
/*
* If you have enough memory to read in the entire image at once,
* and you need to specify only transforms that can be controlled
* with one of the PNG_TRANSFORM_* bits (this presently excludes
* quantizing, filling, setting background, and doing gamma
* adjustment), then you can read the entire image (including
* pixels) into the info structure with this call:
*/
png_read_png(png_ptr, info_ptr, png_transforms, NULL);
#else
/* OK, you're doing it the hard way, with the lower-level functions */
/* The call to png_read_info() gives us all of the information from the
* PNG file before the first IDAT (image data chunk). REQUIRED
*/
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
/* Set up the data transformations you want. Note that these are all
* optional. Only call them if you want/need them. Many of the
* transformations only work on specific types of images, and many
* are mutually exclusive.
*/
/* Tell libpng to strip 16 bit/color files down to 8 bits/color */
png_set_strip_16(png_ptr);
/* Strip alpha bytes from the input data without combining with the
* background (not recommended).
*/
png_set_strip_alpha(png_ptr);
/* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
* byte into separate bytes (useful for paletted and grayscale images).
*/
png_set_packing(png_ptr);
/* Change the order of packed pixels to least significant bit first
* (not useful if you are using png_set_packing). */
png_set_packswap(png_ptr);
/* Expand paletted colors into true RGB triplets */
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
/* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
/* Expand paletted or RGB images with transparency to full alpha channels
* so the data will be available as RGBA quartets.
*/
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
/* Set the background color to draw transparent and alpha images over.
* It is possible to set the red, green, and blue components directly
* for paletted images instead of supplying a palette index. Note that
* even if the PNG file supplies a background, you are not required to
* use it - you should use the (solid) application background if it has one.
*/
png_color_16 my_background, *image_background;
if (png_get_bKGD(png_ptr, info_ptr, &image_background))
png_set_background(png_ptr, image_background,
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
/* Some suggestions as to how to get a screen gamma value
*
* Note that screen gamma is the display_exponent, which includes
* the CRT_exponent and any correction for viewing conditions
*/
if (/* We have a user-defined screen gamma value */)
{
screen_gamma = user-defined screen_gamma;
}
/* This is one way that applications share the same screen gamma value */
else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
{
screen_gamma = atof(gamma_str);
}
/* If we don't have another value */
else
{
screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly
lit room */
screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */
}
/* Tell libpng to handle the gamma conversion for you. The final call
* is a good guess for PC generated images, but it should be configurable
* by the user at run time by the user. It is strongly suggested that
* your application support gamma correction.
*/
int intent;
if (png_get_sRGB(png_ptr, info_ptr, &intent))
png_set_gamma(png_ptr, screen_gamma, 0.45455);
else
{
double image_gamma;
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
png_set_gamma(png_ptr, screen_gamma, image_gamma);
else
png_set_gamma(png_ptr, screen_gamma, 0.45455);
}
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* Quantize RGB files down to 8 bit palette or reduce palettes
* to the number of colors available on your screen.
*/
if (color_type & PNG_COLOR_MASK_COLOR)
{
int num_palette;
png_colorp palette;
/* This reduces the image to the application supplied palette */
if (/* We have our own palette */)
{
/* An array of colors to which the image should be quantized */
png_color std_color_cube[MAX_SCREEN_COLORS];
/* Prior to libpng-1.4.2, this was png_set_dither(). */
png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
MAX_SCREEN_COLORS, NULL, 0);
}
/* This reduces the image to the palette supplied in the file */
else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette))
{
png_uint_16p histogram = NULL;
png_get_hIST(png_ptr, info_ptr, &histogram);
png_set_quantize(png_ptr, palette, num_palette,
max_screen_colors, histogram, 0);
}
}
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
/* Invert monochrome files to have 0 as white and 1 as black */
png_set_invert_mono(png_ptr);
/* If you want to shift the pixel values from the range [0,255] or
* [0,65535] to the original [0,7] or [0,31], or whatever range the
* colors were originally in:
*/
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
{
png_color_8p sig_bit_p;
png_get_sBIT(png_ptr, info_ptr, &sig_bit_p);
png_set_shift(png_ptr, sig_bit_p);
}
/* Flip the RGB pixels to BGR (or RGBA to BGRA) */
if (color_type & PNG_COLOR_MASK_COLOR)
png_set_bgr(png_ptr);
/* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
png_set_swap_alpha(png_ptr);
/* Swap bytes of 16 bit files to least significant byte first */
png_set_swap(png_ptr);
/* Add filler (or alpha) byte (before/after each RGB triplet) */
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
/* Turn on interlace handling. REQUIRED if you are not using
* png_read_image(). To see how to handle interlacing passes,
* see the png_read_row() method below:
*/
number_passes = png_set_interlace_handling(png_ptr);
/* Optional call to gamma correct and add the background to the palette
* and update info structure. REQUIRED if you are expecting libpng to
* update the palette for you (ie you selected such a transform above).
*/
png_read_update_info(png_ptr, info_ptr);
/* Allocate the memory to hold the image using the fields of info_ptr. */
/* The easiest way to read the image: */
png_bytep row_pointers[height];
/* Clear the pointer array */
for (row = 0; row < height; row++)
row_pointers[row] = NULL;
for (row = 0; row < height; row++)
row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
info_ptr));
/* Now it's time to read the image. One of these methods is REQUIRED */
#ifdef entire /* Read the entire image in one go */
png_read_image(png_ptr, row_pointers);
#else no_entire /* Read the image one or more scanlines at a time */
/* The other way to read images - deal with interlacing: */
for (pass = 0; pass < number_passes; pass++)
{
#ifdef single /* Read the image a single row at a time */
for (y = 0; y < height; y++)
{
png_read_rows(png_ptr, &row_pointers[y], NULL, 1);
}
#else no_single /* Read the image several rows at a time */
for (y = 0; y < height; y += number_of_rows)
{
#ifdef sparkle /* Read the image using the "sparkle" effect. */
png_read_rows(png_ptr, &row_pointers[y], NULL,
number_of_rows);
#else no_sparkle /* Read the image using the "rectangle" effect */
png_read_rows(png_ptr, NULL, &row_pointers[y],
number_of_rows);
#endif no_sparkle /* Use only one of these two methods */
}
/* If you want to display the image after every pass, do so here */
#endif no_single /* Use only one of these two methods */
}
#endif no_entire /* Use only one of these two methods */
/* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
png_read_end(png_ptr, info_ptr);
#endif hilevel
/* At this point you have read the entire image */
/* Clean up after the read, and free any memory allocated - REQUIRED */
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* Close the file */
fclose(fp);
/* That's it */
return (OK);
}
/* Progressively read a file */
int
initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
{
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
* you can supply NULL for the last three parameters. We also check that
* the library version is compatible in case we are using dynamically
* linked libraries.
*/
*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
png_voidp user_error_ptr, user_error_fn, user_warning_fn);
if (*png_ptr == NULL)
{
*info_ptr = NULL;
return (ERROR);
}
*info_ptr = png_create_info_struct(png_ptr);
if (*info_ptr == NULL)
{
png_destroy_read_struct(png_ptr, info_ptr, NULL);
return (ERROR);
}
if (setjmp(png_jmpbuf((*png_ptr))))
{
png_destroy_read_struct(png_ptr, info_ptr, NULL);
return (ERROR);
}
/* This one's new. You will need to provide all three
* function callbacks, even if you aren't using them all.
* If you aren't using all functions, you can specify NULL
* parameters. Even when all three functions are NULL,
* you need to call png_set_progressive_read_fn().
* These functions shouldn't be dependent on global or
* static variables if you are decoding several images
* simultaneously. You should store stream specific data
* in a separate struct, given as the second parameter,
* and retrieve the pointer from inside the callbacks using
* the function png_get_progressive_ptr(png_ptr).
*/
png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
info_callback, row_callback, end_callback);
return (OK);
}
int
process_data(png_structp *png_ptr, png_infop *info_ptr,
png_bytep buffer, png_uint_32 length)
{
if (setjmp(png_jmpbuf((*png_ptr))))
{
/* Free the png_ptr and info_ptr memory on error */
png_destroy_read_struct(png_ptr, info_ptr, NULL);
return (ERROR);
}
/* This one's new also. Simply give it chunks of data as
* they arrive from the data stream (in order, of course).
* On segmented machines, don't give it any more than 64K.
* The library seems to run fine with sizes of 4K, although
* you can give it much less if necessary (I assume you can
* give it chunks of 1 byte, but I haven't tried with less
* than 256 bytes yet). When this function returns, you may
* want to display any rows that were generated in the row
* callback, if you aren't already displaying them there.
*/
png_process_data(*png_ptr, *info_ptr, buffer, length);
return (OK);
}
info_callback(png_structp png_ptr, png_infop info)
{
/* Do any setup here, including setting any of the transformations
* mentioned in the Reading PNG files section. For now, you _must_
* call either png_start_read_image() or png_read_update_info()
* after all the transformations are set (even if you don't set
* any). You may start getting rows before png_process_data()
* returns, so this is your last chance to prepare for that.
*/
}
row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass)
{
/*
* This function is called for every row in the image. If the
* image is interlaced, and you turned on the interlace handler,
* this function will be called for every row in every pass.
*
* In this function you will receive a pointer to new row data from
* libpng called new_row that is to replace a corresponding row (of
* the same data format) in a buffer allocated by your application.
*
* The new row data pointer "new_row" may be NULL, indicating there is
* no new data to be replaced (in cases of interlace loading).
*
* If new_row is not NULL then you need to call
* png_progressive_combine_row() to replace the corresponding row as
* shown below:
*/
/* Get pointer to corresponding row in our
* PNG read buffer.
*/
png_bytep old_row = ((png_bytep *)our_data)[row_num];
/* If both rows are allocated then copy the new row
* data to the corresponding row data.
*/
if ((old_row != NULL) && (new_row != NULL))
png_progressive_combine_row(png_ptr, old_row, new_row);
/*
* The rows and passes are called in order, so you don't really
* need the row_num and pass, but I'm supplying them because it
* may make your life easier.
*
* For the non-NULL rows of interlaced images, you must call
* png_progressive_combine_row() passing in the new row and the
* old row, as demonstrated above. You can call this function for
* NULL rows (it will just return) and for non-interlaced images
* (it just does the png_memcpy for you) if it will make the code
* easier. Thus, you can just do this for all cases:
*/
png_progressive_combine_row(png_ptr, old_row, new_row);
/* where old_row is what was displayed for previous rows. Note
* that the first pass (pass == 0 really) will completely cover
* the old row, so the rows do not have to be initialized. After
* the first pass (and only for interlaced images), you will have
* to pass the current row as new_row, and the function will combine
* the old row and the new row.
*/
}
end_callback(png_structp png_ptr, png_infop info)
{
/* This function is called when the whole image has been read,
* including any chunks after the image (up to and including
* the IEND). You will usually have the same info chunk as you
* had in the header, although some data may have been added
* to the comments and time fields.
*
* Most people won't do much here, perhaps setting a flag that
* marks the image as finished.
*/
}
/* Write a png file */
void write_png(char *file_name /* , ... other image information ... */)
{
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_colorp palette;
/* Open the file */
fp = fopen(file_name, "wb");
if (fp == NULL)
return (ERROR);
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,
* you can supply NULL for the last three parameters. We also check that
* the library version is compatible with the one used at compile time,
* in case we are using dynamically linked libraries. REQUIRED.
*/
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
png_voidp user_error_ptr, user_error_fn, user_warning_fn);
if (png_ptr == NULL)
{
fclose(fp);
return (ERROR);
}
/* Allocate/initialize the image information data. REQUIRED */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
{
fclose(fp);
png_destroy_write_struct(&png_ptr, NULL);
return (ERROR);
}
/* Set error handling. REQUIRED if you aren't supplying your own
* error handling functions in the png_create_write_struct() call.
*/
if (setjmp(png_jmpbuf(png_ptr)))
{
/* If we get here, we had a problem writing the file */
fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
return (ERROR);
}
/* One of the following I/O initialization functions is REQUIRED */
#ifdef streams /* I/O initialization method 1 */
/* Set up the output control if you are using standard C streams */
png_init_io(png_ptr, fp);
#else no_streams /* I/O initialization method 2 */
/* If you are using replacement write functions, instead of calling
* png_init_io() here you would call
*/
png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
user_IO_flush_function);
/* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Only use one initialization method */
#ifdef hilevel
/* This is the easy way. Use it if you already have all the
* image info living in the structure. You could "|" many
* PNG_TRANSFORM flags into the png_transforms integer here.
*/
png_write_png(png_ptr, info_ptr, png_transforms, NULL);
#else
/* This is the hard way */
/* Set the image information here. Width and height are up to 2^31,
* bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
* PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???,
PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
/* Set the palette if there is one. REQUIRED for indexed-color images */
palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
* png_sizeof(png_color));
/* ... Set palette colors ... */
png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
/* You must not free palette here, because png_set_PLTE only makes a link to
* the palette that you malloced. Wait until you are about to destroy
* the png structure.
*/
/* Optional significant bit (sBIT) chunk */
png_color_8 sig_bit;
/* If we are dealing with a grayscale image then */
sig_bit.gray = true_bit_depth;
/* Otherwise, if we are dealing with a color image then */
sig_bit.red = true_red_bit_depth;
sig_bit.green = true_green_bit_depth;
sig_bit.blue = true_blue_bit_depth;
/* If the image has an alpha channel then */
sig_bit.alpha = true_alpha_bit_depth;
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
/* Optional gamma chunk is strongly suggested if you have any guess
* as to the correct gamma of the image.
*/
png_set_gAMA(png_ptr, info_ptr, gamma);
/* Optionally write comments into the image */
text_ptr[0].key = "Title";
text_ptr[0].text = "Mona Lisa";
text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr[1].key = "Author";
text_ptr[1].text = "Leonardo DaVinci";
text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr[2].key = "Description";
text_ptr[2].text = "<long text>";
text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
#ifdef PNG_iTXt_SUPPORTED
text_ptr[0].lang = NULL;
text_ptr[0].lang_key = NULL;
text_ptr[1].lang = NULL;
text_ptr[1].lang_key = NULL;
text_ptr[2].lang = NULL;
text_ptr[2].lang_key = NULL;
#endif
png_set_text(png_ptr, info_ptr, text_ptr, 3);
/* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */
/* Note that if sRGB is present the gAMA and cHRM chunks must be ignored
* on read and, if your application chooses to write them, they must
* be written in accordance with the sRGB profile
*/
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
/* If you want, you can write the info in two steps, in case you need to
* write your private chunk ahead of PLTE:
*
* png_write_info_before_PLTE(write_ptr, write_info_ptr);
* write_my_chunk();
* png_write_info(png_ptr, info_ptr);
*
* However, given the level of known- and unknown-chunk support in 1.2.0
* and up, this should no longer be necessary.
*/
/* Once we write out the header, the compression type on the text
* chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
* PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
* at the end.
*/
/* Set up the transformations you want. Note that these are
* all optional. Only call them if you want them.
*/
/* Invert monochrome pixels */
png_set_invert_mono(png_ptr);
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
*/
png_set_shift(png_ptr, &sig_bit);
/* Pack pixels into bytes */
png_set_packing(png_ptr);
/* Swap location of alpha bytes from ARGB to RGBA */
png_set_swap_alpha(png_ptr);
/* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
* RGB (4 channels -> 3 channels). The second parameter is not used.
*/
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
/* Flip BGR pixels to RGB */
png_set_bgr(png_ptr);
/* Swap bytes of 16-bit files to most significant byte first */
png_set_swap(png_ptr);
/* Swap bits of 1, 2, 4 bit packed pixel formats */
png_set_packswap(png_ptr);
/* Turn on interlace handling if you are not using png_write_image() */
if (interlacing)
number_passes = png_set_interlace_handling(png_ptr);
else
number_passes = 1;
/* The easiest way to write the image (you may have a different memory
* layout, however, so choose what fits your needs best). You need to
* use the first method if you aren't handling interlacing yourself.
*/
png_uint_32 k, height, width;
png_byte image[height][width*bytes_per_pixel];
png_bytep row_pointers[height];
if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
png_error (png_ptr, "Image is too tall to process in memory");
for (k = 0; k < height; k++)
row_pointers[k] = image + k*width*bytes_per_pixel;
/* One of the following output methods is REQUIRED */
#ifdef entire /* Write out the entire image data in one call */
png_write_image(png_ptr, row_pointers);
/* The other way to write the image - deal with interlacing */
#else no_entire /* Write out the image data by one or more scanlines */
/* The number of passes is either 1 for non-interlaced images,
* or 7 for interlaced images.
*/
for (pass = 0; pass < number_passes; pass++)
{
/* Write a few rows at a time. */
png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
/* If you are only writing one row at a time, this works */
for (y = 0; y < height; y++)
png_write_rows(png_ptr, &row_pointers[y], 1);
}
#endif no_entire /* Use only one output method */
/* You can write optional chunks like tEXt, zTXt, and tIME at the end
* as well. Shouldn't be necessary in 1.2.0 and up as all the public
* chunks are supported and you can use png_set_unknown_chunks() to
* register unknown chunks into the info structure to be written out.
*/
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr);
#endif hilevel
/* If you png_malloced a palette, free it here (don't free info_ptr->palette,
* as recommended in versions 1.0.5m and earlier of this example; if
* libpng mallocs info_ptr->palette, libpng will free it). If you
* allocated it with malloc() instead of png_malloc(), use free() instead
* of png_free().
*/
png_free(png_ptr, palette);
palette = NULL;
/* Similarly, if you png_malloced any data that you passed in with
* png_set_something(), such as a hist or trans array, free it here,
* when you can be sure that libpng is through with it.
*/
png_free(png_ptr, trans);
trans = NULL;
/* Whenever you use png_free() it is a good idea to set the pointer to
* NULL in case your application inadvertently tries to png_free() it
* again. When png_free() sees a NULL it returns without action, thus
* avoiding the double-free security problem.
*/
/* Clean up after the write, and free any memory allocated */
png_destroy_write_struct(&png_ptr, &info_ptr);
/* Close the file */
fclose(fp);
/* That's it */
return (OK);
}
#endif /* if 0 */

4362
thirdparty/libpng/png.c vendored

File diff suppressed because it is too large Load Diff

3397
thirdparty/libpng/png.h vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

153
thirdparty/libpng/pngdebug.h vendored Normal file
View File

@@ -0,0 +1,153 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
* Last changed in libpng 1.6.8 [December 19, 2013]
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* Define PNG_DEBUG at compile time for debugging information. Higher
* numbers for PNG_DEBUG mean more debugging information. This has
* only been added since version 0.95 so it is not implemented throughout
* libpng yet, but more support will be added as needed.
*
* png_debug[1-2]?(level, message ,arg{0-2})
* Expands to a statement (either a simple expression or a compound
* do..while(0) statement) that outputs a message with parameter
* substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG
* is undefined, 0 or 1 every png_debug expands to a simple expression
* (actually ((void)0)).
*
* level: level of detail of message, starting at 0. A level 'n'
* message is preceded by 'n' 3-space indentations (not implemented
* on Microsoft compilers unless PNG_DEBUG_FILE is also
* defined, to allow debug DLL compilation with no standard IO).
* message: a printf(3) style text string. A trailing '\n' is added
* to the message.
* arg: 0 to 2 arguments for printf(3) style substitution in message.
*/
#ifndef PNGDEBUG_H
#define PNGDEBUG_H
/* These settings control the formatting of messages in png.c and pngerror.c */
/* Moved to pngdebug.h at 1.5.0 */
# ifndef PNG_LITERAL_SHARP
# define PNG_LITERAL_SHARP 0x23
# endif
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
# endif
# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
# endif
# ifndef PNG_STRING_NEWLINE
# define PNG_STRING_NEWLINE "\n"
# endif
#ifdef PNG_DEBUG
# if (PNG_DEBUG > 0)
# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
# include <crtdbg.h>
# if (PNG_DEBUG > 1)
# ifndef _DEBUG
# define _DEBUG
# endif
# ifndef png_debug
# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
_RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
# endif
# endif
# else /* PNG_DEBUG_FILE || !_MSC_VER */
# ifndef PNG_STDIO_SUPPORTED
# include <stdio.h> /* not included yet */
# endif
# ifndef PNG_DEBUG_FILE
# define PNG_DEBUG_FILE stderr
# endif /* PNG_DEBUG_FILE */
# if (PNG_DEBUG > 1)
# ifdef __STDC__
# ifndef png_debug
# define png_debug(l,m) \
do { \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
(num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
} while (0)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
do { \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \
} while (0)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
do { \
int num_tabs=l; \
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
} while (0)
# endif
# else /* __STDC __ */
# ifndef png_debug
# define png_debug(l,m) \
do { \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format); \
} while (0)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
do { \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format,p1); \
} while (0)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
do { \
int num_tabs=l; \
char format[256]; \
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
m,PNG_STRING_NEWLINE); \
fprintf(PNG_DEBUG_FILE,format,p1,p2); \
} while (0)
# endif
# endif /* __STDC __ */
# endif /* (PNG_DEBUG > 1) */
# endif /* _MSC_VER */
# endif /* (PNG_DEBUG > 0) */
#endif /* PNG_DEBUG */
#ifndef png_debug
# define png_debug(l, m) ((void)0)
#endif
#ifndef png_debug1
# define png_debug1(l, m, p1) ((void)0)
#endif
#ifndef png_debug2
# define png_debug2(l, m, p1, p2) ((void)0)
#endif
#endif /* PNGDEBUG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

259
thirdparty/libpng/pnginfo.h vendored Normal file
View File

@@ -0,0 +1,259 @@
/* pnginfo.h - header file for PNG reference library
*
* Last changed in libpng 1.6.1 [March 28, 2013]
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* png_info is a structure that holds the information in a PNG file so
* that the application can find out the characteristics of the image.
* If you are reading the file, this structure will tell you what is
* in the PNG file. If you are writing the file, fill in the information
* you want to put into the PNG file, using png_set_*() functions, then
* call png_write_info().
*
* The names chosen should be very close to the PNG specification, so
* consult that document for information about the meaning of each field.
*
* With libpng < 0.95, it was only possible to directly set and read the
* the values in the png_info_struct, which meant that the contents and
* order of the values had to remain fixed. With libpng 0.95 and later,
* however, there are now functions that abstract the contents of
* png_info_struct from the application, so this makes it easier to use
* libpng with dynamic libraries, and even makes it possible to use
* libraries that don't have all of the libpng ancillary chunk-handing
* functionality. In libpng-1.5.0 this was moved into a separate private
* file that is not visible to applications.
*
* The following members may have allocated storage attached that should be
* cleaned up before the structure is discarded: palette, trans, text,
* pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
* splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
* are automatically freed when the info structure is deallocated, if they were
* allocated internally by libpng. This behavior can be changed by means
* of the png_data_freer() function.
*
* More allocation details: all the chunk-reading functions that
* change these members go through the corresponding png_set_*
* functions. A function to clear these members is available: see
* png_free_data(). The png_set_* functions do not depend on being
* able to point info structure members to any of the storage they are
* passed (they make their own copies), EXCEPT that the png_set_text
* functions use the same storage passed to them in the text_ptr or
* itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
* functions do not make their own copies.
*/
#ifndef PNGINFO_H
#define PNGINFO_H
struct png_info_def
{
/* The following are necessary for every PNG file */
png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
png_size_t rowbytes; /* bytes needed to hold an untransformed row */
png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */
png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
png_uint_16 num_trans; /* number of transparent palette color (tRNS) */
png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */
/* The following three should have been named *_method not *_type */
png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
/* The following are set by png_set_IHDR, called from the application on
* write, but the are never actually used by the write code.
*/
png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */
png_byte pixel_depth; /* number of bits per pixel */
png_byte spare_byte; /* to align the data, and for future use */
#ifdef PNG_READ_SUPPORTED
/* This is never set during write */
png_byte signature[8]; /* magic bytes read by libpng from start of file */
#endif
/* The rest of the data is optional. If you are reading, check the
* valid field to see if the information in these are valid. If you
* are writing, set the valid field to those chunks you want written,
* and initialize the appropriate fields below.
*/
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
/* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
* defined. When COLORSPACE is switched on all the colorspace-defining
* chunks should be enabled, when GAMMA is switched on all the gamma-defining
* chunks should be enabled. If this is not done it becomes possible to read
* inconsistent PNG files and assign a probably incorrect interpretation to
* the information. (In other words, by carefully choosing which chunks to
* recognize the system configuration can select an interpretation for PNG
* files containing ambiguous data and this will result in inconsistent
* behavior between different libpng builds!)
*/
png_colorspace colorspace;
#endif
#ifdef PNG_iCCP_SUPPORTED
/* iCCP chunk data. */
png_charp iccp_name; /* profile name */
png_bytep iccp_profile; /* International Color Consortium profile data */
png_uint_32 iccp_proflen; /* ICC profile data length */
#endif
#ifdef PNG_TEXT_SUPPORTED
/* The tEXt, and zTXt chunks contain human-readable textual data in
* uncompressed, compressed, and optionally compressed forms, respectively.
* The data in "text" is an array of pointers to uncompressed,
* null-terminated C strings. Each chunk has a keyword that describes the
* textual data contained in that chunk. Keywords are not required to be
* unique, and the text string may be empty. Any number of text chunks may
* be in an image.
*/
int num_text; /* number of comments read or comments to write */
int max_text; /* current size of text array */
png_textp text; /* array of comments read or comments to write */
#endif /* TEXT */
#ifdef PNG_tIME_SUPPORTED
/* The tIME chunk holds the last time the displayed image data was
* modified. See the png_time struct for the contents of this struct.
*/
png_time mod_time;
#endif
#ifdef PNG_sBIT_SUPPORTED
/* The sBIT chunk specifies the number of significant high-order bits
* in the pixel data. Values are in the range [1, bit_depth], and are
* only specified for the channels in the pixel data. The contents of
* the low-order bits is not specified. Data is valid if
* (valid & PNG_INFO_sBIT) is non-zero.
*/
png_color_8 sig_bit; /* significant bits in color channels */
#endif
#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
defined(PNG_READ_BACKGROUND_SUPPORTED)
/* The tRNS chunk supplies transparency data for paletted images and
* other image types that don't need a full alpha channel. There are
* "num_trans" transparency values for a paletted image, stored in the
* same order as the palette colors, starting from index 0. Values
* for the data are in the range [0, 255], ranging from fully transparent
* to fully opaque, respectively. For non-paletted images, there is a
* single color specified that should be treated as fully transparent.
* Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
*/
png_bytep trans_alpha; /* alpha values for paletted image */
png_color_16 trans_color; /* transparent color for non-palette image */
#endif
#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
/* The bKGD chunk gives the suggested image background color if the
* display program does not have its own background color and the image
* is needs to composited onto a background before display. The colors
* in "background" are normally in the same color space/depth as the
* pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
*/
png_color_16 background;
#endif
#ifdef PNG_oFFs_SUPPORTED
/* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
* and downwards from the top-left corner of the display, page, or other
* application-specific co-ordinate space. See the PNG_OFFSET_ defines
* below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero.
*/
png_int_32 x_offset; /* x offset on page */
png_int_32 y_offset; /* y offset on page */
png_byte offset_unit_type; /* offset units type */
#endif
#ifdef PNG_pHYs_SUPPORTED
/* The pHYs chunk gives the physical pixel density of the image for
* display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
* defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
*/
png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
png_uint_32 y_pixels_per_unit; /* vertical pixel density */
png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
#endif
#ifdef PNG_hIST_SUPPORTED
/* The hIST chunk contains the relative frequency or importance of the
* various palette entries, so that a viewer can intelligently select a
* reduced-color palette, if required. Data is an array of "num_palette"
* values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
* is non-zero.
*/
png_uint_16p hist;
#endif
#ifdef PNG_pCAL_SUPPORTED
/* The pCAL chunk describes a transformation between the stored pixel
* values and original physical data values used to create the image.
* The integer range [0, 2^bit_depth - 1] maps to the floating-point
* range given by [pcal_X0, pcal_X1], and are further transformed by a
* (possibly non-linear) transformation function given by "pcal_type"
* and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_
* defines below, and the PNG-Group's PNG extensions document for a
* complete description of the transformations and how they should be
* implemented, and for a description of the ASCII parameter strings.
* Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
*/
png_charp pcal_purpose; /* pCAL chunk description string */
png_int_32 pcal_X0; /* minimum value */
png_int_32 pcal_X1; /* maximum value */
png_charp pcal_units; /* Latin-1 string giving physical units */
png_charpp pcal_params; /* ASCII strings containing parameter values */
png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */
png_byte pcal_nparams; /* number of parameters given in pcal_params */
#endif
/* New members added in libpng-1.0.6 */
png_uint_32 free_me; /* flags items libpng is responsible for freeing */
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
/* Storage for unknown chunks that the library doesn't recognize. */
png_unknown_chunkp unknown_chunks;
/* The type of this field is limited by the type of
* png_struct::user_chunk_cache_max, else overflow can occur.
*/
int unknown_chunks_num;
#endif
#ifdef PNG_sPLT_SUPPORTED
/* Data on sPLT chunks (there may be more than one). */
png_sPLT_tp splt_palettes;
int splt_palettes_num; /* Match type returned by png_get API */
#endif
#ifdef PNG_sCAL_SUPPORTED
/* The sCAL chunk describes the actual physical dimensions of the
* subject matter of the graphic. The chunk contains a unit specification
* a byte value, and two ASCII strings representing floating-point
* values. The values are width and height corresponsing to one pixel
* in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
* non-zero.
*/
png_byte scal_unit; /* unit of physical scale */
png_charp scal_s_width; /* string containing height */
png_charp scal_s_height; /* string containing width */
#endif
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
non-zero */
/* Data valid if (valid & PNG_INFO_IDAT) non-zero */
png_bytepp row_pointers; /* the image bits */
#endif
};
#endif /* PNGINFO_H */

214
thirdparty/libpng/pnglibconf.h vendored Normal file
View File

@@ -0,0 +1,214 @@
/* libpng 1.6.17 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
/* Libpng version 1.6.17 - March 26, 2015 */
/* Copyright (c) 1998-2014 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
/* Machine generated file: DO NOT EDIT */
/* Derived from: scripts/pnglibconf.dfa */
#ifndef PNGLCONF_H
#define PNGLCONF_H
/* options */
#define PNG_16BIT_SUPPORTED
#define PNG_ALIGNED_MEMORY_SUPPORTED
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_COLORSPACE_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
#define PNG_EASY_ACCESS_SUPPORTED
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
#define PNG_ERROR_TEXT_SUPPORTED
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
#define PNG_FORMAT_AFIRST_SUPPORTED
#define PNG_FORMAT_BGR_SUPPORTED
#define PNG_GAMMA_SUPPORTED
#define PNG_GET_PALETTE_MAX_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED
#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_iTXt_SUPPORTED
#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_pCAL_SUPPORTED
#define PNG_READ_pHYs_SUPPORTED
#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_sPLT_SUPPORTED
#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
#define PNG_SAVE_INT_32_SUPPORTED
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
#define PNG_SETJMP_SUPPORTED
#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
#define PNG_SET_OPTION_SUPPORTED
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED
#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
#define PNG_SIMPLIFIED_READ_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
#define PNG_STDIO_SUPPORTED
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
#define PNG_USER_MEM_SUPPORTED
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
#define PNG_WARNINGS_SUPPORTED
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED
#define PNG_WRITE_iCCP_SUPPORTED
#define PNG_WRITE_iTXt_SUPPORTED
#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_pCAL_SUPPORTED
#define PNG_WRITE_pHYs_SUPPORTED
#define PNG_WRITE_sBIT_SUPPORTED
#define PNG_WRITE_sCAL_SUPPORTED
#define PNG_WRITE_sPLT_SUPPORTED
#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
#define PNG_bKGD_SUPPORTED
#define PNG_cHRM_SUPPORTED
#define PNG_gAMA_SUPPORTED
#define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED
#define PNG_iTXt_SUPPORTED
#define PNG_oFFs_SUPPORTED
#define PNG_pCAL_SUPPORTED
#define PNG_pHYs_SUPPORTED
#define PNG_sBIT_SUPPORTED
#define PNG_sCAL_SUPPORTED
#define PNG_sPLT_SUPPORTED
#define PNG_sRGB_SUPPORTED
#define PNG_tEXt_SUPPORTED
#define PNG_tIME_SUPPORTED
#define PNG_tRNS_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
/* settings */
#define PNG_API_RULE 0
#define PNG_COST_SHIFT 3
#define PNG_DEFAULT_READ_MACROS 1
#define PNG_GAMMA_THRESHOLD_FIXED 5000
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
#define PNG_INFLATE_BUF_SIZE 1024
#define PNG_MAX_GAMMA_8 11
#define PNG_QUANTIZE_BLUE_BITS 5
#define PNG_QUANTIZE_GREEN_BITS 5
#define PNG_QUANTIZE_RED_BITS 5
#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
#define PNG_USER_CHUNK_CACHE_MAX 1000
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
#define PNG_USER_HEIGHT_MAX 1000000
#define PNG_USER_WIDTH_MAX 1000000
#define PNG_WEIGHT_SHIFT 8
#define PNG_ZBUF_SIZE 8192
#define PNG_ZLIB_VERNUM 0 /* unknown */
#define PNG_Z_DEFAULT_COMPRESSION (-1)
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
#define PNG_Z_DEFAULT_STRATEGY 1
#define PNG_sCAL_PRECISION 5
#define PNG_sRGB_PROFILE_CHECKS 2
/* end of settings */
#endif /* PNGLCONF_H */

View File

@@ -1,8 +1,8 @@
/* pngmem.c - stub functions for memory allocation
*
* Last changed in libpng 1.4.2 [May 6, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* Last changed in libpng 1.6.15 [November 20, 2014]
* Copyright (c) 1998-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -17,575 +17,244 @@
* identify the replacement functions.
*/
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
#include "pngpriv.h"
/* Borland DOS special memory handler */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* If you change this, be sure to change the one in png.h also */
/* Allocate memory for a png_struct. The malloc and memset can be replaced
by a single call to calloc() if this is thought to improve performance. */
png_voidp /* PRIVATE */
png_create_struct(int type)
{
#ifdef PNG_USER_MEM_SUPPORTED
return (png_create_struct_2(type, NULL, NULL));
}
/* Alternate version of png_create_struct, for use with user-defined malloc. */
png_voidp /* PRIVATE */
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */
png_size_t size;
png_voidp struct_ptr;
if (type == PNG_STRUCT_INFO)
size = png_sizeof(png_info);
else if (type == PNG_STRUCT_PNG)
size = png_sizeof(png_struct);
else
return (png_get_copyright(NULL));
#ifdef PNG_USER_MEM_SUPPORTED
if (malloc_fn != NULL)
{
png_struct dummy_struct;
png_structp png_ptr = &dummy_struct;
png_ptr->mem_ptr=mem_ptr;
struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
}
else
#endif /* PNG_USER_MEM_SUPPORTED */
struct_ptr = (png_voidp)farmalloc(size);
if (struct_ptr != NULL)
png_memset(struct_ptr, 0, size);
return (struct_ptr);
}
/* Free memory allocated by a png_create_struct() call */
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* Free a png_struct */
void /* PRIVATE */
png_destroy_struct(png_voidp struct_ptr)
png_destroy_png_struct(png_structrp png_ptr)
{
#ifdef PNG_USER_MEM_SUPPORTED
png_destroy_struct_2(struct_ptr, NULL, NULL);
}
/* Free memory allocated by a png_create_struct() call */
void /* PRIVATE */
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
png_voidp mem_ptr)
{
#endif
if (struct_ptr != NULL)
if (png_ptr != NULL)
{
#ifdef PNG_USER_MEM_SUPPORTED
if (free_fn != NULL)
{
png_struct dummy_struct;
png_structp png_ptr = &dummy_struct;
png_ptr->mem_ptr=mem_ptr;
(*(free_fn))(png_ptr, struct_ptr);
return;
}
#endif /* PNG_USER_MEM_SUPPORTED */
farfree (struct_ptr);
/* png_free might call png_error and may certainly call
* png_get_mem_ptr, so fake a temporary png_struct to support this.
*/
png_struct dummy_struct = *png_ptr;
memset(png_ptr, 0, (sizeof *png_ptr));
png_free(&dummy_struct, png_ptr);
# ifdef PNG_SETJMP_SUPPORTED
/* We may have a jmp_buf left to deallocate. */
png_free_jmpbuf(&dummy_struct);
# endif
}
}
/* Allocate memory. For reasonable files, size should never exceed
* 64K. However, zlib may allocate more then 64K if you don't tell
* it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
*
* Borland seems to have a problem in DOS mode for exactly 64K.
* It gives you a segment with an offset of 8 (perhaps to store its
* memory stuff). zlib doesn't like this at all, so we have to
* detect and deal with it. This code should not be needed in
* Windows or OS/2 modes, and only in 16 bit mode. This code has
* been updated by Alexander Lehmann for version 0.89 to waste less
* memory.
*
* Note that we can't use png_size_t for the "size" declaration,
* since on some systems a png_size_t is a 16-bit quantity, and as a
* result, we would be truncating potentially larger memory requests
* (which should cause a fatal error) and introducing major problems.
*/
png_voidp PNGAPI
png_calloc(png_structp png_ptr, png_alloc_size_t size)
{
png_voidp ret;
ret = (png_malloc(png_ptr, size));
if (ret != NULL)
png_memset(ret,0,(png_size_t)size);
return (ret);
}
png_voidp PNGAPI
png_malloc(png_structp png_ptr, png_alloc_size_t size)
{
png_voidp ret;
if (png_ptr == NULL || size == 0)
return (NULL);
#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr->malloc_fn != NULL)
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
else
ret = (png_malloc_default(png_ptr, size));
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out of memory");
return (ret);
}
png_voidp PNGAPI
png_malloc_default(png_structp png_ptr, png_alloc_size_t size)
{
png_voidp ret;
#endif /* PNG_USER_MEM_SUPPORTED */
if (png_ptr == NULL || size == 0)
return (NULL);
#ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L)
{
png_warning(png_ptr, "Cannot Allocate > 64K");
ret = NULL;
}
else
#endif
if (size != (size_t)size)
ret = NULL;
else if (size == (png_uint_32)65536L)
{
if (png_ptr->offset_table == NULL)
{
/* Try to see if we need to do any of this fancy stuff */
ret = farmalloc(size);
if (ret == NULL || ((png_size_t)ret & 0xffff))
{
int num_blocks;
png_uint_32 total_size;
png_bytep table;
int i;
png_byte huge * hptr;
if (ret != NULL)
{
farfree(ret);
ret = NULL;
}
if (png_ptr->zlib_window_bits > 14)
num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
else
num_blocks = 1;
if (png_ptr->zlib_mem_level >= 7)
num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
else
num_blocks++;
total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
table = farmalloc(total_size);
if (table == NULL)
{
#ifndef PNG_USER_MEM_SUPPORTED
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */
else
png_warning(png_ptr, "Out Of Memory");
#endif
return (NULL);
}
if ((png_size_t)table & 0xfff0)
{
#ifndef PNG_USER_MEM_SUPPORTED
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr,
"Farmalloc didn't return normalized pointer");
else
png_warning(png_ptr,
"Farmalloc didn't return normalized pointer");
#endif
return (NULL);
}
png_ptr->offset_table = table;
png_ptr->offset_table_ptr = farmalloc(num_blocks *
png_sizeof(png_bytep));
if (png_ptr->offset_table_ptr == NULL)
{
#ifndef PNG_USER_MEM_SUPPORTED
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */
else
png_warning(png_ptr, "Out Of memory");
#endif
return (NULL);
}
hptr = (png_byte huge *)table;
if ((png_size_t)hptr & 0xf)
{
hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
}
for (i = 0; i < num_blocks; i++)
{
png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
}
png_ptr->offset_table_number = num_blocks;
png_ptr->offset_table_count = 0;
png_ptr->offset_table_count_free = 0;
}
}
if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
{
#ifndef PNG_USER_MEM_SUPPORTED
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */
else
png_warning(png_ptr, "Out of Memory");
#endif
return (NULL);
}
ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
}
else
ret = farmalloc(size);
#ifndef PNG_USER_MEM_SUPPORTED
if (ret == NULL)
{
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */
else
png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */
}
#endif
return (ret);
}
/* Free a pointer allocated by png_malloc(). In the default
* configuration, png_ptr is not used, but is passed in case it
* is needed. If ptr is NULL, return without taking any action.
*/
void PNGAPI
png_free(png_structp png_ptr, png_voidp ptr)
{
if (png_ptr == NULL || ptr == NULL)
return;
#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr->free_fn != NULL)
{
(*(png_ptr->free_fn))(png_ptr, ptr);
return;
}
else
png_free_default(png_ptr, ptr);
}
void PNGAPI
png_free_default(png_structp png_ptr, png_voidp ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */
if (png_ptr == NULL || ptr == NULL)
return;
if (png_ptr->offset_table != NULL)
{
int i;
for (i = 0; i < png_ptr->offset_table_count; i++)
{
if (ptr == png_ptr->offset_table_ptr[i])
{
ptr = NULL;
png_ptr->offset_table_count_free++;
break;
}
}
if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
{
farfree(png_ptr->offset_table);
farfree(png_ptr->offset_table_ptr);
png_ptr->offset_table = NULL;
png_ptr->offset_table_ptr = NULL;
}
}
if (ptr != NULL)
{
farfree(ptr);
}
}
#else /* Not the Borland DOS special memory handler */
/* Allocate memory for a png_struct or a png_info. The malloc and
memset can be replaced by a single call to calloc() if this is thought
to improve performance noticably. */
png_voidp /* PRIVATE */
png_create_struct(int type)
{
#ifdef PNG_USER_MEM_SUPPORTED
return (png_create_struct_2(type, NULL, NULL));
}
/* Allocate memory for a png_struct or a png_info. The malloc and
memset can be replaced by a single call to calloc() if this is thought
to improve performance noticably. */
png_voidp /* PRIVATE */
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */
png_size_t size;
png_voidp struct_ptr;
if (type == PNG_STRUCT_INFO)
size = png_sizeof(png_info);
else if (type == PNG_STRUCT_PNG)
size = png_sizeof(png_struct);
else
return (NULL);
#ifdef PNG_USER_MEM_SUPPORTED
if (malloc_fn != NULL)
{
png_struct dummy_struct;
png_structp png_ptr = &dummy_struct;
png_ptr->mem_ptr=mem_ptr;
struct_ptr = (*(malloc_fn))(png_ptr, size);
if (struct_ptr != NULL)
png_memset(struct_ptr, 0, size);
return (struct_ptr);
}
#endif /* PNG_USER_MEM_SUPPORTED */
#if defined(__TURBOC__) && !defined(__FLAT__)
struct_ptr = (png_voidp)farmalloc(size);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
struct_ptr = (png_voidp)halloc(size, 1);
# else
struct_ptr = (png_voidp)malloc(size);
# endif
#endif
if (struct_ptr != NULL)
png_memset(struct_ptr, 0, size);
return (struct_ptr);
}
/* Free memory allocated by a png_create_struct() call */
void /* PRIVATE */
png_destroy_struct(png_voidp struct_ptr)
{
#ifdef PNG_USER_MEM_SUPPORTED
png_destroy_struct_2(struct_ptr, NULL, NULL);
}
/* Free memory allocated by a png_create_struct() call */
void /* PRIVATE */
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
png_voidp mem_ptr)
{
#endif /* PNG_USER_MEM_SUPPORTED */
if (struct_ptr != NULL)
{
#ifdef PNG_USER_MEM_SUPPORTED
if (free_fn != NULL)
{
png_struct dummy_struct;
png_structp png_ptr = &dummy_struct;
png_ptr->mem_ptr=mem_ptr;
(*(free_fn))(png_ptr, struct_ptr);
return;
}
#endif /* PNG_USER_MEM_SUPPORTED */
#if defined(__TURBOC__) && !defined(__FLAT__)
farfree(struct_ptr);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
hfree(struct_ptr);
# else
free(struct_ptr);
# endif
#endif
}
}
/* Allocate memory. For reasonable files, size should never exceed
* 64K. However, zlib may allocate more then 64K if you don't tell
* 64K. However, zlib may allocate more than 64K if you don't tell
* it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
*/
png_voidp PNGAPI
png_calloc(png_structp png_ptr, png_alloc_size_t size)
PNG_FUNCTION(png_voidp,PNGAPI
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
ret = (png_malloc(png_ptr, size));
ret = png_malloc(png_ptr, size);
if (ret != NULL)
png_memset(ret,0,(png_size_t)size);
return (ret);
memset(ret, 0, size);
return ret;
}
png_voidp PNGAPI
png_malloc(png_structp png_ptr, png_alloc_size_t size)
/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
* allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
* Checking and error handling must happen outside this routine; it returns NULL
* if the allocation cannot be done (for any reason.)
*/
PNG_FUNCTION(png_voidp /* PRIVATE */,
png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{
png_voidp ret;
#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr == NULL || size == 0)
return (NULL);
if (png_ptr->malloc_fn != NULL)
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
else
ret = (png_malloc_default(png_ptr, size));
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out of Memory");
return (ret);
}
png_voidp PNGAPI
png_malloc_default(png_structp png_ptr, png_alloc_size_t size)
{
png_voidp ret;
#endif /* PNG_USER_MEM_SUPPORTED */
if (png_ptr == NULL || size == 0)
return (NULL);
#ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L)
{
/* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
* allocators have also been removed in 1.6.0, so any 16-bit system now has
* to implement a user memory handler. This checks to be sure it isn't
* called with big numbers.
*/
#ifndef PNG_USER_MEM_SUPPORTED
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Cannot Allocate > 64K");
PNG_UNUSED(png_ptr)
#endif
if (size > 0 && size <= PNG_SIZE_MAX
# ifdef PNG_MAX_MALLOC_64K
&& size <= 65536U
# endif
)
{
#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
else
#endif
return NULL;
return malloc((size_t)size); /* checked for truncation above */
}
#endif
/* Check for overflow */
#if defined(__TURBOC__) && !defined(__FLAT__)
if (size != (unsigned long)size)
ret = NULL;
else
ret = farmalloc(size);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
if (size != (unsigned long)size)
ret = NULL;
else
ret = halloc(size, 1);
# else
if (size != (size_t)size)
ret = NULL;
else
ret = malloc((size_t)size);
# endif
#endif
return NULL;
}
#ifndef PNG_USER_MEM_SUPPORTED
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
png_error(png_ptr, "Out of Memory");
#endif
#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
* that arises because of the checks in png_realloc_array that are repeated in
* png_malloc_array.
*/
static png_voidp
png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
size_t element_size)
{
png_alloc_size_t req = nelements; /* known to be > 0 */
return (ret);
if (req <= PNG_SIZE_MAX/element_size)
return png_malloc_base(png_ptr, req * element_size);
/* The failure case when the request is too large */
return NULL;
}
PNG_FUNCTION(png_voidp /* PRIVATE */,
png_malloc_array,(png_const_structrp png_ptr, int nelements,
size_t element_size),PNG_ALLOCATED)
{
if (nelements <= 0 || element_size == 0)
png_error(png_ptr, "internal error: array alloc");
return png_malloc_array_checked(png_ptr, nelements, element_size);
}
PNG_FUNCTION(png_voidp /* PRIVATE */,
png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
{
/* These are internal errors: */
if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
(old_array == NULL && old_elements > 0))
png_error(png_ptr, "internal error: array realloc");
/* Check for overflow on the elements count (so the caller does not have to
* check.)
*/
if (add_elements <= INT_MAX - old_elements)
{
png_voidp new_array = png_malloc_array_checked(png_ptr,
old_elements+add_elements, element_size);
if (new_array != NULL)
{
/* Because png_malloc_array worked the size calculations below cannot
* overflow.
*/
if (old_elements > 0)
memcpy(new_array, old_array, element_size*(unsigned)old_elements);
memset((char*)new_array + element_size*(unsigned)old_elements, 0,
element_size*(unsigned)add_elements);
return new_array;
}
}
return NULL; /* error */
}
#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
/* Various functions that have different error handling are derived from this.
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
* function png_malloc_default is also provided.
*/
PNG_FUNCTION(png_voidp,PNGAPI
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
if (png_ptr == NULL)
return NULL;
ret = png_malloc_base(png_ptr, size);
if (ret == NULL)
png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
return ret;
}
#ifdef PNG_USER_MEM_SUPPORTED
PNG_FUNCTION(png_voidp,PNGAPI
png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED PNG_DEPRECATED)
{
png_voidp ret;
if (png_ptr == NULL)
return NULL;
/* Passing 'NULL' here bypasses the application provided memory handler. */
ret = png_malloc_base(NULL/*use malloc*/, size);
if (ret == NULL)
png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
return ret;
}
#endif /* USER_MEM */
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
* function will issue a png_warning and return NULL instead of issuing a
* png_error, if it fails to allocate the requested memory.
*/
PNG_FUNCTION(png_voidp,PNGAPI
png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{
if (png_ptr != NULL)
{
png_voidp ret = png_malloc_base(png_ptr, size);
if (ret != NULL)
return ret;
png_warning(png_ptr, "Out of memory");
}
return NULL;
}
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
* without taking any action.
*/
void PNGAPI
png_free(png_structp png_ptr, png_voidp ptr)
png_free(png_const_structrp png_ptr, png_voidp ptr)
{
if (png_ptr == NULL || ptr == NULL)
return;
#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr->free_fn != NULL)
{
(*(png_ptr->free_fn))(png_ptr, ptr);
return;
}
png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
else
png_free_default(png_ptr, ptr);
}
void PNGAPI
png_free_default(png_structp png_ptr, png_voidp ptr)
PNG_FUNCTION(void,PNGAPI
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
{
if (png_ptr == NULL || ptr == NULL)
return;
#endif /* USER_MEM */
#endif /* PNG_USER_MEM_SUPPORTED */
#if defined(__TURBOC__) && !defined(__FLAT__)
farfree(ptr);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
hfree(ptr);
# else
free(ptr);
# endif
#endif
}
#endif /* Not Borland DOS special memory handler */
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
* function will set up png_malloc() to issue a png_warning and return NULL
* instead of issuing a png_error, if it fails to allocate the requested
* memory.
*/
png_voidp PNGAPI
png_malloc_warn(png_structp png_ptr, png_alloc_size_t size)
{
png_voidp ptr;
png_uint_32 save_flags;
if (png_ptr == NULL)
return (NULL);
save_flags = png_ptr->flags;
png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
png_ptr->flags=save_flags;
return(ptr);
}
#ifdef PNG_USER_MEM_SUPPORTED
/* This function is called when the application wants to use another method
* of allocating and freeing memory.
*/
void PNGAPI
png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
malloc_fn, png_free_ptr free_fn)
{
if (png_ptr != NULL)
@@ -601,11 +270,12 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
png_get_mem_ptr(png_structp png_ptr)
png_get_mem_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
return ((png_voidp)png_ptr->mem_ptr);
return NULL;
return png_ptr->mem_ptr;
}
#endif /* PNG_USER_MEM_SUPPORTED */
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
#endif /* USER_MEM */
#endif /* READ || WRITE */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/* pngrio.c - functions for data input
*
* Last changed in libpng 1.4.1 [February 25, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* Last changed in libpng 1.6.17 [March 26, 2015]
* Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,24 +18,24 @@
* libpng use it at run time with png_set_read_fn(...).
*/
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#ifdef PNG_READ_SUPPORTED
#include "pngpriv.h"
#ifdef PNG_READ_SUPPORTED
/* Read the data from whatever input you are using. The default routine
* reads from a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
* buffering if you are using unbuffered reads. This should never be asked
* to read more then 64K on a 16 bit machine.
* to read more than 64K on a 16 bit machine.
*/
void /* PRIVATE */
png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
{
png_debug1(4, "reading %d bytes", (int)length);
if (png_ptr->read_data_fn != NULL)
(*(png_ptr->read_data_fn))(png_ptr, data, length);
else
png_error(png_ptr, "Call to NULL read function");
}
@@ -46,80 +46,34 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* read_data function and use it at run time with png_set_read_fn(), rather
* than changing the library.
*/
#ifndef USE_FAR_KEYWORD
void PNGAPI
void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_size_t check;
if (png_ptr == NULL)
return;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
if (check != length)
png_error(png_ptr, "Read Error");
}
#else
/* This is the model-independent version. Since the standard I/O library
can't handle far buffers in the medium and small models, we have to copy
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
static void PNGAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_size_t check;
png_byte *n_data;
png_FILE_p io_ptr;
if (png_ptr == NULL)
return;
/* Check if data really is near. If so, use usual code. */
n_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)n_data == data)
{
check = fread(n_data, 1, length, io_ptr);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t read, remaining, err;
check = 0;
remaining = length;
do
{
read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, 1, read, io_ptr);
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if (err != read)
break;
else
check += err;
data += read;
remaining -= read;
}
while (remaining != 0);
}
if ((png_uint_32)check != (png_uint_32)length)
png_error(png_ptr, "read Error");
}
#endif
#endif
/* This function allows the application to supply a new input function
* for libpng if standard C streams aren't being used.
*
* This function takes as its arguments:
*
* png_ptr - pointer to a png input data structure
*
* io_ptr - pointer to user supplied structure containing info about
* the input functions. May be NULL.
*
* read_data_fn - pointer to a new input function that takes as its
* arguments a pointer to a png_struct, a pointer to
* a location where input data can be stored, and a 32-bit
@@ -130,34 +84,37 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* be used.
*/
void PNGAPI
png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn)
{
if (png_ptr == NULL)
return;
png_ptr->io_ptr = io_ptr;
#ifdef PNG_STDIO_SUPPORTED
if (read_data_fn != NULL)
png_ptr->read_data_fn = read_data_fn;
else
png_ptr->read_data_fn = png_default_read_data;
#else
png_ptr->read_data_fn = read_data_fn;
#endif
#ifdef PNG_WRITE_SUPPORTED
/* It is an error to write to a read device */
if (png_ptr->write_data_fn != NULL)
{
png_ptr->write_data_fn = NULL;
png_warning(png_ptr,
"It's an error to set both read_data_fn and write_data_fn in the ");
png_warning(png_ptr,
"same structure. Resetting write_data_fn to NULL");
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->output_flush_fn = NULL;
#endif
}
#endif /* PNG_READ_SUPPORTED */
#endif /* READ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

488
thirdparty/libpng/pngstruct.h vendored Normal file
View File

@@ -0,0 +1,488 @@
/* pngstruct.h - header file for PNG reference library
*
* Last changed in libpng 1.6.1 [March 28, 2013]
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* The structure that holds the information to read and write PNG files.
* The only people who need to care about what is inside of this are the
* people who will be modifying the library for their own special needs.
* It should NOT be accessed directly by an application.
*/
#ifndef PNGSTRUCT_H
#define PNGSTRUCT_H
/* zlib.h defines the structure z_stream, an instance of which is included
* in this structure and is required for decompressing the LZ compressed
* data in PNG files.
*/
#ifndef ZLIB_CONST
/* We must ensure that zlib uses 'const' in declarations. */
# define ZLIB_CONST
#endif
#include "zlib.h"
#ifdef const
/* zlib.h sometimes #defines const to nothing, undo this. */
# undef const
#endif
/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
* with older builds.
*/
#if ZLIB_VERNUM < 0x1260
# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
#else
# define PNGZ_MSG_CAST(s) (s)
# define PNGZ_INPUT_CAST(b) (b)
#endif
/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
* can handle at once. This type need be no larger than 16 bits (so maximum of
* 65535), this define allows us to discover how big it is, but limited by the
* maximuum for png_size_t. The value can be overriden in a library build
* (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
* lower value (e.g. 255 works). A lower value may help memory usage (slightly)
* and may even improve performance on some systems (and degrade it on others.)
*/
#ifndef ZLIB_IO_MAX
# define ZLIB_IO_MAX ((uInt)-1)
#endif
#ifdef PNG_WRITE_SUPPORTED
/* The type of a compression buffer list used by the write code. */
typedef struct png_compression_buffer
{
struct png_compression_buffer *next;
png_byte output[1]; /* actually zbuf_size */
} png_compression_buffer, *png_compression_bufferp;
#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
(offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
#endif
/* Colorspace support; structures used in png_struct, png_info and in internal
* functions to hold and communicate information about the color space.
*
* PNG_COLORSPACE_SUPPORTED is only required if the application will perform
* colorspace corrections, otherwise all the colorspace information can be
* skipped and the size of libpng can be reduced (significantly) by compiling
* out the colorspace support.
*/
#ifdef PNG_COLORSPACE_SUPPORTED
/* The chromaticities of the red, green and blue colorants and the chromaticity
* of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
*/
typedef struct png_xy
{
png_fixed_point redx, redy;
png_fixed_point greenx, greeny;
png_fixed_point bluex, bluey;
png_fixed_point whitex, whitey;
} png_xy;
/* The same data as above but encoded as CIE XYZ values. When this data comes
* from chromaticities the sum of the Y values is assumed to be 1.0
*/
typedef struct png_XYZ
{
png_fixed_point red_X, red_Y, red_Z;
png_fixed_point green_X, green_Y, green_Z;
png_fixed_point blue_X, blue_Y, blue_Z;
} png_XYZ;
#endif /* COLORSPACE */
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
/* A colorspace is all the above plus, potentially, profile information;
* however at present libpng does not use the profile internally so it is only
* stored in the png_info struct (if iCCP is supported.) The rendering intent
* is retained here and is checked.
*
* The file gamma encoding information is also stored here and gamma correction
* is done by libpng, whereas color correction must currently be done by the
* application.
*/
typedef struct png_colorspace
{
#ifdef PNG_GAMMA_SUPPORTED
png_fixed_point gamma; /* File gamma */
#endif
#ifdef PNG_COLORSPACE_SUPPORTED
png_xy end_points_xy; /* End points as chromaticities */
png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
png_uint_16 rendering_intent; /* Rendering intent of a profile */
#endif
/* Flags are always defined to simplify the code. */
png_uint_16 flags; /* As defined below */
} png_colorspace, * PNG_RESTRICT png_colorspacerp;
typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
/* General flags for the 'flags' field */
#define PNG_COLORSPACE_HAVE_GAMMA 0x0001
#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002
#define PNG_COLORSPACE_HAVE_INTENT 0x0004
#define PNG_COLORSPACE_FROM_gAMA 0x0008
#define PNG_COLORSPACE_FROM_cHRM 0x0010
#define PNG_COLORSPACE_FROM_sRGB 0x0020
#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */
#define PNG_COLORSPACE_INVALID 0x8000
#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags))
#endif /* COLORSPACE || GAMMA */
struct png_struct_def
{
#ifdef PNG_SETJMP_SUPPORTED
jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */
png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
size_t jmp_buf_size; /* size of the above, if allocated */
#endif
png_error_ptr error_fn; /* function for printing errors and aborting */
#ifdef PNG_WARNINGS_SUPPORTED
png_error_ptr warning_fn; /* function for printing warnings */
#endif
png_voidp error_ptr; /* user supplied struct for error functions */
png_rw_ptr write_data_fn; /* function for writing output data */
png_rw_ptr read_data_fn; /* function for reading input data */
png_voidp io_ptr; /* ptr to application struct for I/O functions */
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr read_user_transform_fn; /* user read transform */
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr write_user_transform_fn; /* user write transform */
#endif
/* These were added in libpng-1.0.2 */
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
png_voidp user_transform_ptr; /* user supplied struct for user transform */
png_byte user_transform_depth; /* bit depth of user transformed pixels */
png_byte user_transform_channels; /* channels in user transformed pixels */
#endif
#endif
png_uint_32 mode; /* tells us where we are in the PNG file */
png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations; /* which transformations to perform */
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
z_stream zstream; /* decompression structure */
#ifdef PNG_WRITE_SUPPORTED
png_compression_bufferp zbuffer_list; /* Created on demand during write */
uInt zbuffer_size; /* size of the actual buffer */
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
int zlib_window_bits; /* holds zlib compression window bits */
int zlib_mem_level; /* holds zlib compression memory level */
int zlib_strategy; /* holds zlib compression strategy */
#endif
/* Added at libpng 1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
int zlib_text_mem_level; /* holds zlib compression memory level */
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
/* End of material added at libpng 1.5.4 */
/* Added at libpng 1.6.0 */
#ifdef PNG_WRITE_SUPPORTED
int zlib_set_level; /* Actual values set into the zstream on write */
int zlib_set_method;
int zlib_set_window_bits;
int zlib_set_mem_level;
int zlib_set_strategy;
#endif
png_uint_32 width; /* width of image in pixels */
png_uint_32 height; /* height of image in pixels */
png_uint_32 num_rows; /* number of rows in current pass */
png_uint_32 usr_width; /* width of row at start of write */
png_size_t rowbytes; /* size of row in bytes */
png_uint_32 iwidth; /* width of current interlaced row in pixels */
png_uint_32 row_number; /* current row in interlace pass */
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
png_bytep prev_row; /* buffer to save previous (unfiltered) row.
* This is a pointer into big_prev_row
*/
png_bytep row_buf; /* buffer to save current (unfiltered) row.
* This is a pointer into big_row_buf
*/
#ifdef PNG_WRITE_SUPPORTED
png_bytep sub_row; /* buffer to save "sub" row when filtering */
png_bytep up_row; /* buffer to save "up" row when filtering */
png_bytep avg_row; /* buffer to save "avg" row when filtering */
png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */
#endif
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
png_uint_32 idat_size; /* current IDAT size for read */
png_uint_32 crc; /* current chunk CRC value */
png_colorp palette; /* palette from the input file */
png_uint_16 num_palette; /* number of color entries in palette */
/* Added at libpng-1.5.10 */
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
int num_palette_max; /* maximum palette index found in IDAT */
#endif
png_uint_16 num_trans; /* number of transparency values */
png_byte compression; /* file compression type (always 0) */
png_byte filter; /* file filter type (always 0) */
png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
png_byte pass; /* current interlace pass (0 - 6) */
png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */
png_byte color_type; /* color type of file */
png_byte bit_depth; /* bit depth of file */
png_byte usr_bit_depth; /* bit depth of users row: write only */
png_byte pixel_depth; /* number of bits per pixel */
png_byte channels; /* number of channels in file */
#ifdef PNG_WRITE_SUPPORTED
png_byte usr_channels; /* channels at start of write: write only */
#endif
png_byte sig_bytes; /* magic bytes read/written from start of file */
png_byte maximum_pixel_depth;
/* pixel depth used for the row buffers */
png_byte transformed_pixel_depth;
/* pixel depth after read/write transforms */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */
#endif
#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
defined(PNG_READ_ALPHA_MODE_SUPPORTED)
png_byte background_gamma_type;
png_fixed_point background_gamma;
png_color_16 background; /* background color in screen gamma space */
#ifdef PNG_READ_GAMMA_SUPPORTED
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
#endif /* bKGD */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */
png_uint_32 flush_rows; /* number of rows written since last flush */
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */
png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
png_bytep gamma_table; /* gamma table for 8-bit depth files */
png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
png_bytep gamma_from_1; /* converts from 1.0 to screen */
png_bytep gamma_to_1; /* converts from file to 1.0 */
png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
png_color_8 sig_bit; /* significant bits in each available channel */
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift; /* shift for significant bit tranformation */
#endif
#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
|| defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep trans_alpha; /* alpha values for paletted files */
png_color_16 trans_color; /* transparent color for non-paletted files */
#endif
png_read_status_ptr read_row_fn; /* called after each row is decoded */
png_write_status_ptr write_row_fn; /* called after each row is encoded */
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_progressive_info_ptr info_fn; /* called after header data fully read */
png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */
png_progressive_end_ptr end_fn; /* called after image is complete */
png_bytep save_buffer_ptr; /* current location in save_buffer */
png_bytep save_buffer; /* buffer for previously read data */
png_bytep current_buffer_ptr; /* current location in current_buffer */
png_bytep current_buffer; /* buffer for recently used data */
png_uint_32 push_length; /* size of current input chunk */
png_uint_32 skip_length; /* bytes to skip in input data */
png_size_t save_buffer_size; /* amount of data now in save_buffer */
png_size_t save_buffer_max; /* total size of save_buffer */
png_size_t buffer_size; /* total amount of available input data */
png_size_t current_buffer_size; /* amount of data now in current_buffer */
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
#endif /* PROGRESSIVE_READ */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* For the Borland special 64K segment handler */
png_bytepp offset_table_ptr;
png_bytep offset_table;
png_uint_16 offset_table_number;
png_uint_16 offset_table_count;
png_uint_16 offset_table_count_free;
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_bytep palette_lookup; /* lookup table for quantizing */
png_bytep quantize_index; /* index translation for palette files */
#endif
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
png_byte heuristic_method; /* heuristic for row filter selection */
png_byte num_prev_filters; /* number of weights for previous rows */
png_bytep prev_filters; /* filter type(s) of previous row(s) */
png_uint_16p filter_weights; /* weight(s) for previous line(s) */
png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */
png_uint_16p filter_costs; /* relative filter calculation cost */
png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */
#endif
/* Options */
#ifdef PNG_SET_OPTION_SUPPORTED
png_byte options; /* On/off state (up to 4 options) */
#endif
#if PNG_LIBPNG_VER < 10700
/* To do: remove this from libpng-1.7 */
#ifdef PNG_TIME_RFC1123_SUPPORTED
char time_buffer[29]; /* String to hold RFC 1123 time text */
#endif
#endif
/* New members added in libpng-1.0.6 */
png_uint_32 free_me; /* flags items libpng is responsible for freeing */
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp user_chunk_ptr;
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
#endif
#endif
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
int unknown_default; /* As PNG_HANDLE_* */
unsigned int num_chunk_list; /* Number of entries in the list */
png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
* followed by a PNG_HANDLE_* byte */
#endif
/* New members added in libpng-1.0.3 */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte rgb_to_gray_status;
/* Added in libpng 1.5.5 to record setting of coefficients: */
png_byte rgb_to_gray_coefficients_set;
/* These were changed from png_byte in libpng-1.0.6 */
png_uint_16 rgb_to_gray_red_coeff;
png_uint_16 rgb_to_gray_green_coeff;
/* deleted in 1.5.5: rgb_to_gray_blue_coeff; */
#endif
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
png_uint_32 mng_features_permitted;
#endif
/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_byte filter_type;
#endif
/* New members added in libpng-1.2.0 */
/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
#ifdef PNG_USER_MEM_SUPPORTED
png_voidp mem_ptr; /* user supplied struct for mem functions */
png_malloc_ptr malloc_fn; /* function for allocating memory */
png_free_ptr free_fn; /* function for freeing memory */
#endif
/* New member added in libpng-1.0.13 and 1.2.0 */
png_bytep big_row_buf; /* buffer to save current (unfiltered) row */
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* The following three members were added at version 1.0.14 and 1.2.4 */
png_bytep quantize_sort; /* working sort array */
png_bytep index_to_palette; /* where the original index currently is
in the palette */
png_bytep palette_to_index; /* which original index points to this
palette color */
#endif
/* New members added in libpng-1.0.16 and 1.2.6 */
png_byte compression_type;
#ifdef PNG_USER_LIMITS_SUPPORTED
png_uint_32 user_width_max;
png_uint_32 user_height_max;
/* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
* chunks that can be stored (0 means unlimited).
*/
png_uint_32 user_chunk_cache_max;
/* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
* can occupy when decompressed. 0 means unlimited.
*/
png_alloc_size_t user_chunk_malloc_max;
#endif
/* New member added in libpng-1.0.25 and 1.2.17 */
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Temporary storage for unknown chunk that the library doesn't recognize,
* used while reading the chunk.
*/
png_unknown_chunk unknown_chunk;
#endif
/* New member added in libpng-1.2.26 */
png_size_t old_big_row_buf_size;
#ifdef PNG_READ_SUPPORTED
/* New member added in libpng-1.2.30 */
png_bytep read_buffer; /* buffer for reading chunk data */
png_alloc_size_t read_buffer_size; /* current size of the buffer */
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
uInt IDAT_read_size; /* limit on read buffer size for IDAT */
#endif
#ifdef PNG_IO_STATE_SUPPORTED
/* New member added in libpng-1.4.0 */
png_uint_32 io_state;
#endif
/* New member added in libpng-1.5.6 */
png_bytep big_prev_row;
/* New member added in libpng-1.5.7 */
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row);
#ifdef PNG_READ_SUPPORTED
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
png_colorspace colorspace;
#endif
#endif
};
#endif /* PNGSTRUCT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
* Last changed in libpng 1.4.2 [April 29, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* Last changed in libpng 1.6.17 [March 26, 2015]
* Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,20 +11,20 @@
* and license in png.h
*/
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
#include "pngpriv.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Turn on BGR-to-RGB mapping */
void PNGAPI
png_set_bgr(png_structp png_ptr)
png_set_bgr(png_structrp png_ptr)
{
png_debug(1, "in png_set_bgr");
if (png_ptr == NULL)
return;
png_ptr->transformations |= PNG_BGR;
}
#endif
@@ -32,12 +32,13 @@ png_set_bgr(png_structp png_ptr)
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Turn on 16 bit byte swapping */
void PNGAPI
png_set_swap(png_structp png_ptr)
png_set_swap(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap");
if (png_ptr == NULL)
return;
if (png_ptr->bit_depth == 16)
png_ptr->transformations |= PNG_SWAP_BYTES;
}
@@ -46,16 +47,19 @@ png_set_swap(png_structp png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Turn on pixel packing */
void PNGAPI
png_set_packing(png_structp png_ptr)
png_set_packing(png_structrp png_ptr)
{
png_debug(1, "in png_set_packing");
if (png_ptr == NULL)
return;
if (png_ptr->bit_depth < 8)
{
png_ptr->transformations |= PNG_PACK;
png_ptr->usr_bit_depth = 8;
# ifdef PNG_WRITE_SUPPORTED
png_ptr->usr_bit_depth = 8;
# endif
}
}
#endif
@@ -63,12 +67,13 @@ png_set_packing(png_structp png_ptr)
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Turn on packed pixel swapping */
void PNGAPI
png_set_packswap(png_structp png_ptr)
png_set_packswap(png_structrp png_ptr)
{
png_debug(1, "in png_set_packswap");
if (png_ptr == NULL)
return;
if (png_ptr->bit_depth < 8)
png_ptr->transformations |= PNG_PACKSWAP;
}
@@ -76,12 +81,13 @@ png_set_packswap(png_structp png_ptr)
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void PNGAPI
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
{
png_debug(1, "in png_set_shift");
if (png_ptr == NULL)
return;
png_ptr->transformations |= PNG_SHIFT;
png_ptr->shift = *true_bits;
}
@@ -90,11 +96,11 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits)
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
int PNGAPI
png_set_interlace_handling(png_structp png_ptr)
png_set_interlace_handling(png_structrp png_ptr)
{
png_debug(1, "in png_set_interlace handling");
if (png_ptr && png_ptr->interlaced)
if (png_ptr != 0 && png_ptr->interlaced != 0)
{
png_ptr->transformations |= PNG_INTERLACE;
return (7);
@@ -111,48 +117,101 @@ png_set_interlace_handling(png_structp png_ptr)
* that don't like bytes as parameters.
*/
void PNGAPI
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_filler");
if (png_ptr == NULL)
return;
/* In libpng 1.6 it is possible to determine whether this is a read or write
* operation and therefore to do more checking here for a valid call.
*/
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
{
# ifdef PNG_READ_FILLER_SUPPORTED
/* On read png_set_filler is always valid, regardless of the base PNG
* format, because other transformations can give a format where the
* filler code can execute (basically an 8 or 16-bit component RGB or G
* format.)
*
* NOTE: usr_channels is not used by the read code! (This has led to
* confusion in the past.) The filler is only used in the read code.
*/
png_ptr->filler = (png_uint_16)filler;
# else
png_app_error(png_ptr, "png_set_filler not supported on read");
PNG_UNUSED(filler) /* not used in the write case */
return;
# endif
}
else /* write */
{
# ifdef PNG_WRITE_FILLER_SUPPORTED
/* On write the usr_channels parameter must be set correctly at the
* start to record the number of channels in the app-supplied data.
*/
switch (png_ptr->color_type)
{
case PNG_COLOR_TYPE_RGB:
png_ptr->usr_channels = 4;
break;
case PNG_COLOR_TYPE_GRAY:
if (png_ptr->bit_depth >= 8)
{
png_ptr->usr_channels = 2;
break;
}
else
{
/* There simply isn't any code in libpng to strip out bits
* from bytes when the components are less than a byte in
* size!
*/
png_app_error(png_ptr,
"png_set_filler is invalid for low bit depth gray output");
return;
}
default:
png_app_error(png_ptr,
"png_set_filler: inappropriate color type");
return;
}
# else
png_app_error(png_ptr, "png_set_filler not supported on write");
return;
# endif
}
/* Here on success - libpng supports the operation, set the transformation
* and the flag to say where the filler channel is.
*/
png_ptr->transformations |= PNG_FILLER;
png_ptr->filler = (png_uint_16)filler;
if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
/* This should probably go in the "do_read_filler" routine.
* I attempted to do that in libpng-1.0.1a but that caused problems
* so I restored it in libpng-1.0.2a
*/
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
png_ptr->usr_channels = 4;
}
/* Also I added this in libpng-1.0.2a (what happens when we expand
* a less-than-8-bit grayscale to GA? */
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
{
png_ptr->usr_channels = 2;
}
}
/* Added to libpng-1.2.7 */
void PNGAPI
png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_add_alpha");
if (png_ptr == NULL)
return;
png_set_filler(png_ptr, filler, filler_loc);
png_ptr->transformations |= PNG_ADD_ALPHA;
/* The above may fail to do anything. */
if ((png_ptr->transformations & PNG_FILLER) != 0)
png_ptr->transformations |= PNG_ADD_ALPHA;
}
#endif
@@ -160,12 +219,13 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
void PNGAPI
png_set_swap_alpha(png_structp png_ptr)
png_set_swap_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap_alpha");
if (png_ptr == NULL)
return;
png_ptr->transformations |= PNG_SWAP_ALPHA;
}
#endif
@@ -173,24 +233,26 @@ png_set_swap_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void PNGAPI
png_set_invert_alpha(png_structp png_ptr)
png_set_invert_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_alpha");
if (png_ptr == NULL)
return;
png_ptr->transformations |= PNG_INVERT_ALPHA;
}
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void PNGAPI
png_set_invert_mono(png_structp png_ptr)
png_set_invert_mono(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_mono");
if (png_ptr == NULL)
return;
png_ptr->transformations |= PNG_INVERT_MONO;
}
@@ -206,8 +268,8 @@ png_do_invert(png_row_infop row_info, png_bytep row)
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
png_bytep rp = row;
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
png_size_t i;
png_size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i++)
{
@@ -215,36 +277,41 @@ png_do_invert(png_row_infop row_info, png_bytep row)
rp++;
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
row_info->bit_depth == 8)
{
png_bytep rp = row;
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
png_size_t i;
png_size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i+=2)
for (i = 0; i < istop; i += 2)
{
*rp = (png_byte)(~(*rp));
rp+=2;
rp += 2;
}
}
#ifdef PNG_16BIT_SUPPORTED
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
row_info->bit_depth == 16)
{
png_bytep rp = row;
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
png_size_t i;
png_size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i+=4)
for (i = 0; i < istop; i += 4)
{
*rp = (png_byte)(~(*rp));
*(rp+1) = (png_byte)(~(*(rp+1)));
rp+=4;
*(rp + 1) = (png_byte)(~(*(rp + 1)));
rp += 4;
}
}
#endif
}
#endif
#ifdef PNG_16BIT_SUPPORTED
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Swaps byte order on 16 bit depth images */
void /* PRIVATE */
@@ -252,8 +319,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_swap");
if (
row_info->bit_depth == 16)
if (row_info->bit_depth == 16)
{
png_bytep rp = row;
png_uint_32 i;
@@ -261,13 +327,21 @@ png_do_swap(png_row_infop row_info, png_bytep row)
for (i = 0; i < istop; i++, rp += 2)
{
#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
/* Feature added to libpng-1.6.11 for testing purposes, not
* enabled by default.
*/
*(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
#else
png_byte t = *rp;
*rp = *(rp + 1);
*(rp + 1) = t;
#endif
}
}
}
#endif
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
static PNG_CONST png_byte onebppswaptable[256] = {
@@ -381,19 +455,22 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_packswap");
if (
row_info->bit_depth < 8)
if (row_info->bit_depth < 8)
{
png_bytep rp, end, table;
png_bytep rp;
png_const_bytep end, table;
end = row + row_info->rowbytes;
if (row_info->bit_depth == 1)
table = (png_bytep)onebppswaptable;
table = onebppswaptable;
else if (row_info->bit_depth == 2)
table = (png_bytep)twobppswaptable;
table = twobppswaptable;
else if (row_info->bit_depth == 4)
table = (png_bytep)fourbppswaptable;
table = fourbppswaptable;
else
return;
@@ -401,162 +478,123 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
*rp = table[*rp];
}
}
#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
#endif /* PACKSWAP || WRITE_PACKSWAP */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
/* Remove filler or alpha byte(s) */
/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
* somewhat weird combination of flags to determine what to do. All the calls
* to png_do_strip_filler are changed in 1.5.2 to call this instead with the
* correct arguments.
*
* The routine isn't general - the channel must be the channel at the start or
* end (not in the middle) of each pixel.
*/
void /* PRIVATE */
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
png_debug(1, "in png_do_strip_filler");
png_bytep sp = row; /* source pointer */
png_bytep dp = row; /* destination pointer */
png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
/* At the start sp will point to the first byte to copy and dp to where
* it is copied to. ep always points just beyond the end of the row, so
* the loop simply copies (channels-1) channels until sp reaches ep.
*
* at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
* nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
*/
/* GA, GX, XG cases */
if (row_info->channels == 2)
{
png_bytep sp=row;
png_bytep dp=row;
png_uint_32 row_width=row_info->width;
png_uint_32 i;
if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
(flags & PNG_FLAG_STRIP_ALPHA))) &&
row_info->channels == 4)
if (row_info->bit_depth == 8)
{
if (row_info->bit_depth == 8)
{
/* This converts from RGBX or RGBA to RGB */
if (flags & PNG_FLAG_FILLER_AFTER)
{
dp+=3; sp+=4;
for (i = 1; i < row_width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp++;
}
}
/* This converts from XRGB or ARGB to RGB */
else
{
for (i = 0; i < row_width; i++)
{
sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 24;
row_info->rowbytes = row_width * 3;
}
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
/* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
sp += 8; dp += 6;
for (i = 1; i < row_width; i++)
{
/* This could be (although png_memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
/* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
for (i = 0; i < row_width; i++)
{
/* This could be (although png_memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
/* For a 1 pixel wide image there is nothing to do */
while (sp < ep)
*dp++ = *sp, sp += 2;
sp+=2;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 48;
row_info->rowbytes = row_width * 6;
}
row_info->channels = 3;
row_info->pixel_depth = 8;
}
else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
(row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
(flags & PNG_FLAG_STRIP_ALPHA))) &&
row_info->channels == 2)
else if (row_info->bit_depth == 16)
{
if (row_info->bit_depth == 8)
{
/* This converts from GX or GA to G */
if (flags & PNG_FLAG_FILLER_AFTER)
{
for (i = 0; i < row_width; i++)
{
*dp++ = *sp++;
sp++;
}
}
/* This converts from XG or AG to G */
else
{
for (i = 0; i < row_width; i++)
{
sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 8;
row_info->rowbytes = row_width;
}
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
/* This converts from GGXX or GGAA to GG */
sp += 4; dp += 2;
for (i = 1; i < row_width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
/* This converts from XXGG or AAGG to GG */
for (i = 0; i < row_width; i++)
{
sp += 2;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 16;
row_info->rowbytes = row_width * 2;
}
row_info->channels = 1;
if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2;
while (sp < ep)
*dp++ = *sp++, *dp++ = *sp, sp += 3;
row_info->pixel_depth = 16;
}
if (flags & PNG_FLAG_STRIP_ALPHA)
row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
else
return; /* bad bit depth */
row_info->channels = 1;
/* Finally fix the color type if it records an alpha channel */
if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_GRAY;
}
/* RGBA, RGBX, XRGB cases */
else if (row_info->channels == 4)
{
if (row_info->bit_depth == 8)
{
if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
/* Note that the loop adds 3 to dp and 4 to sp each time. */
while (sp < ep)
*dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
row_info->pixel_depth = 24;
}
else if (row_info->bit_depth == 16)
{
if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6;
while (sp < ep)
{
/* Copy 6 bytes, skip 2 */
*dp++ = *sp++, *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp, sp += 3;
}
row_info->pixel_depth = 48;
}
else
return; /* bad bit depth */
row_info->channels = 3;
/* Finally fix the color type if it records an alpha channel */
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_RGB;
}
else
return; /* The filler channel has gone already */
/* Fix the rowbytes value. */
row_info->rowbytes = dp-row;
}
#endif
@@ -567,8 +605,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_bgr");
if (
(row_info->color_type & PNG_COLOR_MASK_COLOR))
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_uint_32 row_width = row_info->width;
if (row_info->bit_depth == 8)
@@ -585,6 +622,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
*(rp + 2) = save;
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_bytep rp;
@@ -598,6 +636,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
}
}
}
#ifdef PNG_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
@@ -615,6 +655,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
*(rp + 5) = save;
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_bytep rp;
@@ -631,47 +672,178 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
}
}
}
#endif
}
}
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
#endif /* READ_BGR || WRITE_BGR */
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
/* Added at libpng-1.5.10 */
void /* PRIVATE */
png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
{
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
{
/* Calculations moved outside switch in an attempt to stop different
* compiler warnings. 'padding' is in *bits* within the last byte, it is
* an 'int' because pixel_depth becomes an 'int' in the expression below,
* and this calculation is used because it avoids warnings that other
* forms produced on either GCC or MSVC.
*/
int padding = (-row_info->pixel_depth * row_info->width) & 7;
png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
switch (row_info->bit_depth)
{
case 1:
{
/* in this case, all bytes must be 0 so we don't need
* to unpack the pixels except for the rightmost one.
*/
for (; rp > png_ptr->row_buf; rp--)
{
if (*rp >> padding != 0)
png_ptr->num_palette_max = 1;
padding = 0;
}
break;
}
case 2:
{
for (; rp > png_ptr->row_buf; rp--)
{
int i = ((*rp >> padding) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 2) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 4) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 6) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
padding = 0;
}
break;
}
case 4:
{
for (; rp > png_ptr->row_buf; rp--)
{
int i = ((*rp >> padding) & 0x0f);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 4) & 0x0f);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
padding = 0;
}
break;
}
case 8:
{
for (; rp > png_ptr->row_buf; rp--)
{
if (*rp > png_ptr->num_palette_max)
png_ptr->num_palette_max = (int) *rp;
}
break;
}
default:
break;
}
}
}
#endif /* CHECK_FOR_INVALID_INDEX */
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
void PNGAPI
png_set_user_transform_info(png_structp png_ptr, png_voidp
png_set_user_transform_info(png_structrp png_ptr, png_voidp
user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
png_debug(1, "in png_set_user_transform_info");
if (png_ptr == NULL)
return;
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
(png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
{
png_app_error(png_ptr,
"info change after png_start_read_image or png_read_update_info");
return;
}
#endif
png_ptr->user_transform_ptr = user_transform_ptr;
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
#else
if (user_transform_ptr || user_transform_depth || user_transform_channels)
png_warning(png_ptr,
"This version of libpng does not support user transform info");
#endif
}
#endif
/* This function returns a pointer to the user_transform_ptr associated with
* the user transform functions. The application should free any memory
* associated with this pointer before png_write_destroy and png_read_destroy
* are called.
*/
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp PNGAPI
png_get_user_transform_ptr(png_structp png_ptr)
png_get_user_transform_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
return ((png_voidp)png_ptr->user_transform_ptr);
#else
return (NULL);
#endif
return png_ptr->user_transform_ptr;
}
#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
PNG_WRITE_USER_TRANSFORM_SUPPORTED */
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
png_uint_32 PNGAPI
png_get_current_row_number(png_const_structrp png_ptr)
{
/* See the comments in png.h - this is the sub-image row when reading an
* interlaced image.
*/
if (png_ptr != NULL)
return png_ptr->row_number;
return PNG_UINT_32_MAX; /* help the app not to fail silently */
}
png_byte PNGAPI
png_get_current_pass_number(png_const_structrp png_ptr)
{
if (png_ptr != NULL)
return png_ptr->pass;
return 8; /* invalid */
}
#endif /* USER_TRANSFORM_INFO */
#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
#endif /* READ || WRITE */

View File

@@ -1,8 +1,8 @@
/* pngwio.c - functions for data output
*
* Last changed in libpng 1.4.0 [January 3, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* Last changed in libpng 1.6.15 [November 20, 2014]
* Copyright (c) 1998-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,11 +18,10 @@
* them at run time with png_set_write_fn(...).
*/
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#ifdef PNG_WRITE_SUPPORTED
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
/* Write the data to whatever output you are using. The default routine
* writes to a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
@@ -31,10 +30,13 @@
*/
void /* PRIVATE */
png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
{
/* NOTE: write_data_fn must not change the buffer! */
if (png_ptr->write_data_fn != NULL )
(*(png_ptr->write_data_fn))(png_ptr, data, length);
(*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
length);
else
png_error(png_ptr, "Call to NULL write function");
}
@@ -45,70 +47,19 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
* write_data function and use it at run time with png_set_write_fn(), rather
* than changing the library.
*/
#ifndef USE_FAR_KEYWORD
void PNGAPI
void PNGCBAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_uint_32 check;
png_size_t check;
if (png_ptr == NULL)
return;
check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
if (check != length)
png_error(png_ptr, "Write Error");
}
#else
/* This is the model-independent version. Since the standard I/O library
* can't handle far buffers in the medium and small models, we have to copy
* the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
void PNGAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_uint_32 check;
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
png_FILE_p io_ptr;
if (png_ptr == NULL)
return;
/* Check if data really is near. If so, use usual code. */
near_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)near_data == data)
{
check = fwrite(near_data, 1, length, io_ptr);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err;
check = 0;
remaining = length;
do
{
written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
err = fwrite(buf, 1, written, io_ptr);
if (err != written)
break;
else
check += err;
data += written;
remaining -= written;
}
while (remaining != 0);
}
if (check != length)
png_error(png_ptr, "Write Error");
}
#endif
#endif
/* This function is called to output any data pending writing (normally
@@ -117,23 +68,25 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
*/
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void /* PRIVATE */
png_flush(png_structp png_ptr)
png_flush(png_structrp png_ptr)
{
if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr);
}
#ifdef PNG_STDIO_SUPPORTED
void PNGAPI
# ifdef PNG_STDIO_SUPPORTED
void PNGCBAPI
png_default_flush(png_structp png_ptr)
{
png_FILE_p io_ptr;
if (png_ptr == NULL)
return;
io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
fflush(io_ptr);
}
#endif
# endif
#endif
/* This function allows the application to supply new output functions for
@@ -166,8 +119,8 @@ png_default_flush(png_structp png_ptr)
* *FILE structure.
*/
void PNGAPI
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
if (png_ptr == NULL)
return;
@@ -185,57 +138,31 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED
if (output_flush_fn != NULL)
png_ptr->output_flush_fn = output_flush_fn;
else
png_ptr->output_flush_fn = png_default_flush;
#else
png_ptr->output_flush_fn = output_flush_fn;
#endif
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
# else
png_ptr->output_flush_fn = output_flush_fn;
# endif
#else
PNG_UNUSED(output_flush_fn)
#endif /* WRITE_FLUSH */
#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
png_ptr->read_data_fn = NULL;
png_warning(png_ptr,
"Attempted to set both read_data_fn and write_data_fn in");
png_warning(png_ptr,
"the same structure. Resetting read_data_fn to NULL");
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
#endif
}
#ifdef USE_FAR_KEYWORD
#ifdef _MSC_VER
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
{
void *near_ptr;
void FAR *far_ptr;
FP_OFF(near_ptr) = FP_OFF(ptr);
far_ptr = (void FAR *)near_ptr;
if (check != 0)
if (FP_SEG(ptr) != FP_SEG(far_ptr))
png_error(png_ptr, "segment lost in conversion");
return(near_ptr);
}
# else
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
{
void *near_ptr;
void FAR *far_ptr;
near_ptr = (void FAR *)ptr;
far_ptr = (void FAR *)near_ptr;
if (check != 0)
if (far_ptr != ptr)
png_error(png_ptr, "segment lost in conversion");
return(near_ptr);
}
# endif
# endif
#endif /* PNG_WRITE_SUPPORTED */
#endif /* WRITE */

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
* Last changed in libpng 1.4.1 [February 25, 2010]
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
* Last changed in libpng 1.6.17 [March 26, 2015]
* Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,84 +11,17 @@
* and license in png.h
*/
#define PNG_NO_PEDANTIC_WARNINGS
#include "png.h"
#ifdef PNG_WRITE_SUPPORTED
#include "pngpriv.h"
/* Transform the data according to the user's wishes. The order of
* transformations is significant.
*/
void /* PRIVATE */
png_do_write_transformations(png_structp png_ptr)
{
png_debug(1, "in png_do_write_transformations");
if (png_ptr == NULL)
return;
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
if (png_ptr->transformations & PNG_USER_TRANSFORM)
if (png_ptr->write_user_transform_fn != NULL)
(*(png_ptr->write_user_transform_fn)) /* User write transform
function */
(png_ptr, /* png_ptr */
&(png_ptr->row_info), /* row_info: */
/* png_uint_32 width; width of row */
/* png_uint_32 rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr->row_buf + 1); /* start of pixel data for row */
#endif
#ifdef PNG_WRITE_FILLER_SUPPORTED
if (png_ptr->transformations & PNG_FILLER)
png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->flags);
#endif
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if (png_ptr->transformations & PNG_PACKSWAP)
png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_PACK_SUPPORTED
if (png_ptr->transformations & PNG_PACK)
png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
(png_uint_32)png_ptr->bit_depth);
#endif
#ifdef PNG_WRITE_SWAP_SUPPORTED
if (png_ptr->transformations & PNG_SWAP_BYTES)
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
if (png_ptr->transformations & PNG_SHIFT)
png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
&(png_ptr->shift));
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_SWAP_ALPHA)
png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
if (png_ptr->transformations & PNG_INVERT_ALPHA)
png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_BGR_SUPPORTED
if (png_ptr->transformations & PNG_BGR)
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_SUPPORTED
if (png_ptr->transformations & PNG_INVERT_MONO)
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
}
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
* row_info bit depth should be 8 (one pixel per byte). The channels
* should be 1 (this only happens on grayscale and paletted images).
*/
void /* PRIVATE */
static void
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
png_debug(1, "in png_do_pack");
@@ -114,9 +47,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
if (*sp != 0)
v |= mask;
sp++;
if (mask > 1)
mask >>= 1;
else
{
mask = 0x80;
@@ -125,10 +61,13 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
v = 0;
}
}
if (mask != 0x80)
*dp = (png_byte)v;
break;
}
case 2:
{
png_bytep sp, dp;
@@ -140,12 +79,14 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
dp = row;
shift = 6;
v = 0;
for (i = 0; i < row_width; i++)
{
png_byte value;
value = (png_byte)(*sp & 0x03);
v |= (value << shift);
if (shift == 0)
{
shift = 6;
@@ -153,14 +94,19 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
dp++;
v = 0;
}
else
shift -= 2;
sp++;
}
if (shift != 6)
*dp = (png_byte)v;
break;
}
case 4:
{
png_bytep sp, dp;
@@ -172,6 +118,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
dp = row;
shift = 4;
v = 0;
for (i = 0; i < row_width; i++)
{
png_byte value;
@@ -186,20 +133,27 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
dp++;
v = 0;
}
else
shift -= 4;
sp++;
}
if (shift != 4)
*dp = (png_byte)v;
break;
}
default:
break;
}
row_info->bit_depth = (png_byte)bit_depth;
row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
row_info->width);
row_info->width);
}
}
#endif
@@ -212,36 +166,40 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*/
void /* PRIVATE */
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
static void
png_do_shift(png_row_infop row_info, png_bytep row,
png_const_color_8p bit_depth)
{
png_debug(1, "in png_do_shift");
if (
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{
int shift_start[4], shift_dec[4];
int channels = 0;
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->red;
shift_dec[channels] = bit_depth->red;
channels++;
shift_start[channels] = row_info->bit_depth - bit_depth->green;
shift_dec[channels] = bit_depth->green;
channels++;
shift_start[channels] = row_info->bit_depth - bit_depth->blue;
shift_dec[channels] = bit_depth->blue;
channels++;
}
else
{
shift_start[channels] = row_info->bit_depth - bit_depth->gray;
shift_dec[channels] = bit_depth->gray;
channels++;
}
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
shift_dec[channels] = bit_depth->alpha;
@@ -252,33 +210,40 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
if (row_info->bit_depth < 8)
{
png_bytep bp = row;
png_uint_32 i;
png_byte mask;
png_uint_32 row_bytes = row_info->rowbytes;
png_size_t i;
unsigned int mask;
png_size_t row_bytes = row_info->rowbytes;
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
mask = 0x55;
else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
mask = 0x11;
else
mask = 0xff;
for (i = 0; i < row_bytes; i++, bp++)
{
png_uint_16 v;
int j;
unsigned int v, out;
v = *bp;
*bp = 0;
out = 0;
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
{
if (j > 0)
*bp |= (png_byte)((v << j) & 0xff);
out |= v << j;
else
*bp |= (png_byte)((v >> (-j)) & mask);
out |= (v >> (-j)) & mask;
}
*bp = (png_byte)(out & 0xff);
}
}
else if (row_info->bit_depth == 8)
{
png_bytep bp = row;
@@ -288,21 +253,26 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
for (i = 0; i < istop; i++, bp++)
{
png_uint_16 v;
const unsigned int c = i%channels;
int j;
int c = (int)(i%channels);
unsigned int v, out;
v = *bp;
*bp = 0;
out = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
*bp |= (png_byte)((v << j) & 0xff);
out |= v << j;
else
*bp |= (png_byte)((v >> (-j)) & 0xff);
out |= v >> (-j);
}
*bp = (png_byte)(out & 0xff);
}
}
else
{
png_bytep bp;
@@ -311,20 +281,22 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
for (bp = row, i = 0; i < istop; i++)
{
int c = (int)(i%channels);
png_uint_16 value, v;
const unsigned int c = i%channels;
int j;
unsigned int value, v;
v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
v = png_get_uint_16(bp);
value = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
value |= v << j;
else
value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
value |= v >> (-j);
}
*bp++ = (png_byte)(value >> 8);
*bp++ = (png_byte)((value >> 8) & 0xff);
*bp++ = (png_byte)(value & 0xff);
}
}
@@ -333,7 +305,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
void /* PRIVATE */
static void
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
@@ -341,12 +313,13 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
/* This converts from ARGB to RGBA */
if (row_info->bit_depth == 8)
{
/* This converts from ARGB to RGBA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
for (i = 0, sp = dp = row; i < row_width; i++)
{
png_byte save = *(sp++);
@@ -356,9 +329,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save;
}
}
/* This converts from AARRGGBB to RRGGBBAA */
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This converts from AARRGGBB to RRGGBBAA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -378,12 +353,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
/* This converts from AG to GA */
if (row_info->bit_depth == 8)
{
/* This converts from AG to GA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -395,9 +372,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save;
}
}
/* This converts from AAGG to GGAA */
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This converts from AAGG to GGAA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -413,13 +392,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
#endif /* WRITE_16BIT */
}
}
}
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
void /* PRIVATE */
static void
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
@@ -427,12 +407,13 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
/* This inverts the alpha channel in RGBA */
if (row_info->bit_depth == 8)
{
/* This inverts the alpha channel in RGBA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
for (i = 0, sp = dp = row; i < row_width; i++)
{
/* Does nothing
@@ -444,9 +425,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
/* This inverts the alpha channel in RRGGBBAA */
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This inverts the alpha channel in RRGGBBAA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -466,12 +449,14 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
/* This inverts the alpha channel in GA */
if (row_info->bit_depth == 8)
{
/* This inverts the alpha channel in GA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -482,9 +467,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
/* This inverts the alpha channel in GGAA */
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This inverts the alpha channel in GGAA */
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
@@ -500,67 +487,88 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
#endif /* WRITE_16BIT */
}
}
}
#endif
#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Undoes intrapixel differencing */
/* Transform the data according to the user's wishes. The order of
* transformations is significant.
*/
void /* PRIVATE */
png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
{
png_debug(1, "in png_do_write_intrapixel");
png_debug(1, "in png_do_write_transformations");
if (
(row_info->color_type & PNG_COLOR_MASK_COLOR))
{
int bytes_per_pixel;
png_uint_32 row_width = row_info->width;
if (row_info->bit_depth == 8)
{
png_bytep rp;
png_uint_32 i;
if (png_ptr == NULL)
return;
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
bytes_per_pixel = 3;
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
bytes_per_pixel = 4;
else
return;
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
if (png_ptr->write_user_transform_fn != NULL)
(*(png_ptr->write_user_transform_fn)) /* User write transform
function */
(png_ptr, /* png_ptr */
row_info, /* row_info: */
/* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr->row_buf + 1); /* start of pixel data for row */
#endif
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
{
*(rp) = (png_byte)((*rp - *(rp+1))&0xff);
*(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
}
}
else if (row_info->bit_depth == 16)
{
png_bytep rp;
png_uint_32 i;
#ifdef PNG_WRITE_FILLER_SUPPORTED
if ((png_ptr->transformations & PNG_FILLER) != 0)
png_do_strip_channel(row_info, png_ptr->row_buf + 1,
!(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
#endif
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
bytes_per_pixel = 6;
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
bytes_per_pixel = 8;
else
return;
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
{
png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
*(rp ) = (png_byte)((red >> 8) & 0xff);
*(rp+1) = (png_byte)(red & 0xff);
*(rp+4) = (png_byte)((blue >> 8) & 0xff);
*(rp+5) = (png_byte)(blue & 0xff);
}
}
}
#ifdef PNG_WRITE_PACK_SUPPORTED
if ((png_ptr->transformations & PNG_PACK) != 0)
png_do_pack(row_info, png_ptr->row_buf + 1,
(png_uint_32)png_ptr->bit_depth);
#endif
#ifdef PNG_WRITE_SWAP_SUPPORTED
# ifdef PNG_16BIT_SUPPORTED
if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_do_swap(row_info, png_ptr->row_buf + 1);
# endif
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_do_shift(row_info, png_ptr->row_buf + 1,
&(png_ptr->shift));
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_BGR_SUPPORTED
if ((png_ptr->transformations & PNG_BGR) != 0)
png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_SUPPORTED
if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
#endif /* PNG_WRITE_SUPPORTED */
#endif /* WRITE_TRANSFORMS */
#endif /* WRITE */

Some files were not shown because too many files have changed in this diff Show More