mirror of
https://github.com/libjpeg-turbo/libjpeg-turbo.git
synced 2026-01-18 13:31:21 +01:00
rdppm.c: Fix CMYK upconversion/downconversion
If the data precision of the PBMPLUS file does not match the target data precision, then the grayscale or RGB samples are rescaled to the target data precision. Thus, we need to pass (1 << cinfo->data_precision) - 1 to rgb_to_cmyk() instead of maxval. This commit also modifies TJUnitTest so that it validates the correctness of upconversion and downconversion in the PPM reader. Fixes #841
This commit is contained in:
@@ -23,6 +23,11 @@ the JNI wrapper's buffer size checks that rendered those checks ineffective.
|
|||||||
invocation of `TJCompressor.loadSourceImage()` if the target data precision was
|
invocation of `TJCompressor.loadSourceImage()` if the target data precision was
|
||||||
changed before the most recent invocation.
|
changed before the most recent invocation.
|
||||||
|
|
||||||
|
5. Fixed an issue in the PPM reader that caused incorrect pixels to be
|
||||||
|
generated when using `tj3LoadImage*()` or `TJCompressor.loadSourceImage()` to
|
||||||
|
load a PBMPLUS (PPM/PGM) file into a CMYK buffer with a different data
|
||||||
|
precision than that of the file.
|
||||||
|
|
||||||
|
|
||||||
3.1.2
|
3.1.2
|
||||||
=====
|
=====
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C)2011-2018, 2022-2024 D. R. Commander. All Rights Reserved.
|
* Copyright (C)2011-2018, 2022-2025 D. R. Commander. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@@ -320,14 +320,14 @@ final class TJUnitTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getVal(Object buf, int index) {
|
static int getVal(Object buf, int index, int targetPrecision) {
|
||||||
int v;
|
int v;
|
||||||
if (precision <= 8)
|
if (targetPrecision <= 8)
|
||||||
v = (int)(((byte[])buf)[index]);
|
v = (int)(((byte[])buf)[index]);
|
||||||
else
|
else
|
||||||
v = (int)(((short[])buf)[index]);
|
v = (int)(((short[])buf)[index]);
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
v += maxSample + 1;
|
v += (1 << targetPrecision);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,10 +356,10 @@ final class TJUnitTest {
|
|||||||
index = (h - row - 1) * w + col;
|
index = (h - row - 1) * w + col;
|
||||||
else
|
else
|
||||||
index = row * w + col;
|
index = row * w + col;
|
||||||
int c = getVal(buf, index * ps);
|
int c = getVal(buf, index * ps, precision);
|
||||||
int m = getVal(buf, index * ps + 1);
|
int m = getVal(buf, index * ps + 1, precision);
|
||||||
int y = getVal(buf, index * ps + 2);
|
int y = getVal(buf, index * ps + 2, precision);
|
||||||
int k = getVal(buf, index * ps + 3);
|
int k = getVal(buf, index * ps + 3, precision);
|
||||||
checkValMax(row, col, c, "C");
|
checkValMax(row, col, c, "C");
|
||||||
if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
|
if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
|
||||||
checkValMax(row, col, m, "M");
|
checkValMax(row, col, m, "M");
|
||||||
@@ -387,10 +387,11 @@ final class TJUnitTest {
|
|||||||
index = pitch * (h - row - 1) + col * ps;
|
index = pitch * (h - row - 1) + col * ps;
|
||||||
else
|
else
|
||||||
index = pitch * row + col * ps;
|
index = pitch * row + col * ps;
|
||||||
int r = getVal(buf, index + roffset);
|
int r = getVal(buf, index + roffset, precision);
|
||||||
int g = getVal(buf, index + goffset);
|
int g = getVal(buf, index + goffset, precision);
|
||||||
int b = getVal(buf, index + boffset);
|
int b = getVal(buf, index + boffset, precision);
|
||||||
int a = aoffset >= 0 ? getVal(buf, index + aoffset) : maxSample;
|
int a = aoffset >= 0 ? getVal(buf, index + aoffset, precision) :
|
||||||
|
maxSample;
|
||||||
if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
|
if (((row / blockSize) + (col / blockSize)) % 2 == 0) {
|
||||||
if (row < halfway) {
|
if (row < halfway) {
|
||||||
checkValMax(row, col, r, "R");
|
checkValMax(row, col, r, "R");
|
||||||
@@ -434,15 +435,15 @@ final class TJUnitTest {
|
|||||||
for (row = 0; row < h; row++) {
|
for (row = 0; row < h; row++) {
|
||||||
for (col = 0; col < w; col++) {
|
for (col = 0; col < w; col++) {
|
||||||
if (pf == TJ.PF_CMYK) {
|
if (pf == TJ.PF_CMYK) {
|
||||||
int c = getVal(buf, pitch * row + col * ps);
|
int c = getVal(buf, pitch * row + col * ps, precision);
|
||||||
int m = getVal(buf, pitch * row + col * ps + 1);
|
int m = getVal(buf, pitch * row + col * ps + 1, precision);
|
||||||
int y = getVal(buf, pitch * row + col * ps + 2);
|
int y = getVal(buf, pitch * row + col * ps + 2, precision);
|
||||||
int k = getVal(buf, pitch * row + col * ps + 3);
|
int k = getVal(buf, pitch * row + col * ps + 3, precision);
|
||||||
System.out.format("%3d/%3d/%3d/%3d ", c, m, y, k);
|
System.out.format("%3d/%3d/%3d/%3d ", c, m, y, k);
|
||||||
} else {
|
} else {
|
||||||
int r = getVal(buf, pitch * row + col * ps + roffset);
|
int r = getVal(buf, pitch * row + col * ps + roffset, precision);
|
||||||
int g = getVal(buf, pitch * row + col * ps + goffset);
|
int g = getVal(buf, pitch * row + col * ps + goffset, precision);
|
||||||
int b = getVal(buf, pitch * row + col * ps + boffset);
|
int b = getVal(buf, pitch * row + col * ps + boffset, precision);
|
||||||
System.out.format("%3d/%3d/%3d ", r, g, b);
|
System.out.format("%3d/%3d/%3d ", r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1080,20 +1081,22 @@ final class TJUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void cmykToRGB(int c, int m, int y, int k, int[] r, int[] g,
|
static void cmykToRGB(int c, int m, int y, int k, int[] r, int[] g,
|
||||||
int[] b) {
|
int[] b, int targetMaxSample) {
|
||||||
r[0] = (int)((double)c * (double)k / (double)maxSample + 0.5);
|
r[0] = (int)((double)c * (double)k / (double)targetMaxSample + 0.5);
|
||||||
g[0] = (int)((double)m * (double)k / (double)maxSample + 0.5);
|
g[0] = (int)((double)m * (double)k / (double)targetMaxSample + 0.5);
|
||||||
b[0] = (int)((double)y * (double)k / (double)maxSample + 0.5);
|
b[0] = (int)((double)y * (double)k / (double)targetMaxSample + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean cmpBitmap(Object buf, int width, int pitch, int height,
|
static boolean cmpBitmap(Object buf, int width, int pitch, int height,
|
||||||
int pf, boolean bottomUp, boolean gray2rgb) {
|
int pf, boolean bottomUp, boolean gray2rgb,
|
||||||
|
int targetPrecision) {
|
||||||
int roffset = TJ.getRedOffset(pf);
|
int roffset = TJ.getRedOffset(pf);
|
||||||
int goffset = TJ.getGreenOffset(pf);
|
int goffset = TJ.getGreenOffset(pf);
|
||||||
int boffset = TJ.getBlueOffset(pf);
|
int boffset = TJ.getBlueOffset(pf);
|
||||||
int aoffset = TJ.getAlphaOffset(pf);
|
int aoffset = TJ.getAlphaOffset(pf);
|
||||||
int ps = TJ.getPixelSize(pf);
|
int ps = TJ.getPixelSize(pf);
|
||||||
int i, j;
|
int i, j;
|
||||||
|
int targetMaxSample = (1 << targetPrecision) - 1;
|
||||||
|
|
||||||
for (j = 0; j < height; j++) {
|
for (j = 0; j < height; j++) {
|
||||||
int row = bottomUp ? height - j - 1 : j;
|
int row = bottomUp ? height - j - 1 : j;
|
||||||
@@ -1104,16 +1107,28 @@ final class TJUnitTest {
|
|||||||
int b = (j * (maxSample + 1) / height +
|
int b = (j * (maxSample + 1) / height +
|
||||||
i * (maxSample + 1) / width) % (maxSample + 1);
|
i * (maxSample + 1) / width) % (maxSample + 1);
|
||||||
|
|
||||||
|
if (precision != targetPrecision) {
|
||||||
|
long halfMaxSample = maxSample / 2;
|
||||||
|
|
||||||
|
r = (int)((r * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
g = (int)((g * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
b = (int)((b * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
}
|
||||||
|
|
||||||
if (pf == TJ.PF_GRAY) {
|
if (pf == TJ.PF_GRAY) {
|
||||||
if (getVal(buf, row * pitch + i * ps) != b)
|
if (getVal(buf, row * pitch + i * ps, targetPrecision) != b)
|
||||||
return false;
|
return false;
|
||||||
} else if (pf == TJ.PF_CMYK) {
|
} else if (pf == TJ.PF_CMYK) {
|
||||||
int[] rf = new int[1], gf = new int[1], bf = new int[1];
|
int[] rf = new int[1], gf = new int[1], bf = new int[1];
|
||||||
|
|
||||||
cmykToRGB(getVal(buf, row * pitch + i * ps + 0),
|
cmykToRGB(getVal(buf, row * pitch + i * ps + 0, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 1),
|
getVal(buf, row * pitch + i * ps + 1, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 2),
|
getVal(buf, row * pitch + i * ps + 2, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 3), rf, gf, bf);
|
getVal(buf, row * pitch + i * ps + 3, targetPrecision),
|
||||||
|
rf, gf, bf, targetMaxSample);
|
||||||
if (gray2rgb) {
|
if (gray2rgb) {
|
||||||
if (rf[0] != b || gf[0] != b || bf[0] != b)
|
if (rf[0] != b || gf[0] != b || bf[0] != b)
|
||||||
return false;
|
return false;
|
||||||
@@ -1121,16 +1136,23 @@ final class TJUnitTest {
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (gray2rgb) {
|
if (gray2rgb) {
|
||||||
if (getVal(buf, row * pitch + i * ps + roffset) != b ||
|
if (getVal(buf, row * pitch + i * ps + roffset,
|
||||||
getVal(buf, row * pitch + i * ps + goffset) != b ||
|
targetPrecision) != b ||
|
||||||
getVal(buf, row * pitch + i * ps + boffset) != b)
|
getVal(buf, row * pitch + i * ps + goffset,
|
||||||
|
targetPrecision) != b ||
|
||||||
|
getVal(buf, row * pitch + i * ps + boffset,
|
||||||
|
targetPrecision) != b)
|
||||||
return false;
|
return false;
|
||||||
} else if (getVal(buf, row * pitch + i * ps + roffset) != r ||
|
} else if (getVal(buf, row * pitch + i * ps + roffset,
|
||||||
getVal(buf, row * pitch + i * ps + goffset) != g ||
|
targetPrecision) != r ||
|
||||||
getVal(buf, row * pitch + i * ps + boffset) != b)
|
getVal(buf, row * pitch + i * ps + goffset,
|
||||||
|
targetPrecision) != g ||
|
||||||
|
getVal(buf, row * pitch + i * ps + boffset,
|
||||||
|
targetPrecision) != b)
|
||||||
return false;
|
return false;
|
||||||
if (aoffset >= 0 &&
|
if (aoffset >= 0 &&
|
||||||
getVal(buf, row * pitch + i * ps + aoffset) != maxSample)
|
getVal(buf, row * pitch + i * ps + aoffset,
|
||||||
|
targetPrecision) != targetMaxSample)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1174,19 +1196,20 @@ final class TJUnitTest {
|
|||||||
"fc2803bca103ff75785ea0dca992aa", "d8c91fac522c16b029e514d331a22bc4",
|
"fc2803bca103ff75785ea0dca992aa", "d8c91fac522c16b029e514d331a22bc4",
|
||||||
"e50cff0b3562ed7e64dbfc093440e333", "64f3320b226ea37fb58080713b4df1b2"
|
"e50cff0b3562ed7e64dbfc093440e333", "64f3320b226ea37fb58080713b4df1b2"
|
||||||
};
|
};
|
||||||
|
int maxTargetPrecision = 16;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tjc = new TJCompressor();
|
tjc = new TJCompressor();
|
||||||
tjc.set(TJ.PARAM_BOTTOMUP, bottomUp ? 1 : 0);
|
tjc.set(TJ.PARAM_BOTTOMUP, bottomUp ? 1 : 0);
|
||||||
tjc.set(TJ.PARAM_PRECISION, precision);
|
|
||||||
tjd = new TJDecompressor();
|
tjd = new TJDecompressor();
|
||||||
tjd.set(TJ.PARAM_BOTTOMUP, bottomUp ? 1 : 0);
|
tjd.set(TJ.PARAM_BOTTOMUP, bottomUp ? 1 : 0);
|
||||||
tjd.set(TJ.PARAM_PRECISION, precision);
|
tjd.set(TJ.PARAM_PRECISION, precision);
|
||||||
|
|
||||||
if (precision == 8 && ext.equalsIgnoreCase("bmp"))
|
if (precision == 8 && ext.equalsIgnoreCase("bmp")) {
|
||||||
md5ref = (pf == TJ.PF_GRAY ? "51976530acf75f02beddf5d21149101d" :
|
md5ref = (pf == TJ.PF_GRAY ? "51976530acf75f02beddf5d21149101d" :
|
||||||
"6d659071b9bfcdee2def22cb58ddadca");
|
"6d659071b9bfcdee2def22cb58ddadca");
|
||||||
else
|
maxTargetPrecision = 8;
|
||||||
|
} else
|
||||||
md5ref = (pf == TJ.PF_GRAY ? grayPPMRefs[precision] :
|
md5ref = (pf == TJ.PF_GRAY ? grayPPMRefs[precision] :
|
||||||
colorPPMRefs[precision]);
|
colorPPMRefs[precision]);
|
||||||
|
|
||||||
@@ -1207,32 +1230,11 @@ final class TJUnitTest {
|
|||||||
throw new Exception(filename + " has an MD5 sum of " + md5sum +
|
throw new Exception(filename + " has an MD5 sum of " + md5sum +
|
||||||
". Should be " + md5ref);
|
". Should be " + md5ref);
|
||||||
|
|
||||||
tjc.loadSourceImage(filename, align, pf);
|
for (int targetPrecision = 2; targetPrecision <= maxTargetPrecision;
|
||||||
loadWidth = tjc.getWidth();
|
targetPrecision++) {
|
||||||
loadPitch = tjc.getPitch();
|
tjc.set(TJ.PARAM_PRECISION, targetPrecision);
|
||||||
loadHeight = tjc.getHeight();
|
pf = pixelFormat;
|
||||||
pf = tjc.getPixelFormat();
|
|
||||||
buf = tjc.getSourceBuf();
|
|
||||||
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
|
||||||
throw new Exception("Image dimensions of " + filename + " are bogus");
|
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, false))
|
|
||||||
throw new Exception("Pixel data in " + filename + " is bogus");
|
|
||||||
if (pf == TJ.PF_GRAY) {
|
|
||||||
pf = TJ.PF_XBGR;
|
|
||||||
tjc.loadSourceImage(filename, align, pf);
|
|
||||||
loadWidth = tjc.getWidth();
|
|
||||||
loadPitch = tjc.getPitch();
|
|
||||||
loadHeight = tjc.getHeight();
|
|
||||||
pf = tjc.getPixelFormat();
|
|
||||||
buf = tjc.getSourceBuf();
|
|
||||||
pitch = pad(width * TJ.getPixelSize(pf), align);
|
|
||||||
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
|
||||||
throw new Exception("Image dimensions of " + filename +
|
|
||||||
" are bogus");
|
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, true))
|
|
||||||
throw new Exception("Converting " + filename + " to RGB failed");
|
|
||||||
|
|
||||||
pf = TJ.PF_CMYK;
|
|
||||||
tjc.loadSourceImage(filename, align, pf);
|
tjc.loadSourceImage(filename, align, pf);
|
||||||
loadWidth = tjc.getWidth();
|
loadWidth = tjc.getWidth();
|
||||||
loadPitch = tjc.getPitch();
|
loadPitch = tjc.getPitch();
|
||||||
@@ -1243,22 +1245,62 @@ final class TJUnitTest {
|
|||||||
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
||||||
throw new Exception("Image dimensions of " + filename +
|
throw new Exception("Image dimensions of " + filename +
|
||||||
" are bogus");
|
" are bogus");
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, true))
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, false,
|
||||||
throw new Exception("Converting " + filename + " to CMYK failed");
|
ext.equalsIgnoreCase("bmp") ? 8 : targetPrecision))
|
||||||
|
throw new Exception("Pixel data in " + filename + " is bogus " +
|
||||||
|
"(target data precision = " + targetPrecision +
|
||||||
|
")");
|
||||||
|
|
||||||
|
if (pf == TJ.PF_GRAY) {
|
||||||
|
pf = TJ.PF_XBGR;
|
||||||
|
tjc.loadSourceImage(filename, align, pf);
|
||||||
|
loadWidth = tjc.getWidth();
|
||||||
|
loadPitch = tjc.getPitch();
|
||||||
|
loadHeight = tjc.getHeight();
|
||||||
|
pf = tjc.getPixelFormat();
|
||||||
|
buf = tjc.getSourceBuf();
|
||||||
|
pitch = pad(width * TJ.getPixelSize(pf), align);
|
||||||
|
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
||||||
|
throw new Exception("Image dimensions of " + filename +
|
||||||
|
" are bogus");
|
||||||
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, true,
|
||||||
|
ext.equalsIgnoreCase("bmp") ? 8 : targetPrecision))
|
||||||
|
throw new Exception("Converting " + filename + " to RGB failed " +
|
||||||
|
"(target data precision = " + targetPrecision +
|
||||||
|
")");
|
||||||
|
|
||||||
|
pf = TJ.PF_CMYK;
|
||||||
|
tjc.loadSourceImage(filename, align, pf);
|
||||||
|
loadWidth = tjc.getWidth();
|
||||||
|
loadPitch = tjc.getPitch();
|
||||||
|
loadHeight = tjc.getHeight();
|
||||||
|
pf = tjc.getPixelFormat();
|
||||||
|
buf = tjc.getSourceBuf();
|
||||||
|
pitch = pad(width * TJ.getPixelSize(pf), align);
|
||||||
|
if (width != loadWidth || pitch != loadPitch || height != loadHeight)
|
||||||
|
throw new Exception("Image dimensions of " + filename +
|
||||||
|
" are bogus");
|
||||||
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, true,
|
||||||
|
ext.equalsIgnoreCase("bmp") ? 8 : targetPrecision))
|
||||||
|
throw new Exception("Converting " + filename +
|
||||||
|
" to CMYK failed (target data precision = " +
|
||||||
|
targetPrecision + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that TJCompressor.loadSourceImage() returns the proper
|
||||||
|
"preferred" pixel format for the file type. */
|
||||||
|
pf = pixelFormat;
|
||||||
|
pixelFormat = TJ.PF_UNKNOWN;
|
||||||
|
tjc.loadSourceImage(filename, align, pixelFormat);
|
||||||
|
pixelFormat = tjc.getPixelFormat();
|
||||||
|
if ((pf == TJ.PF_GRAY && pixelFormat != TJ.PF_GRAY) ||
|
||||||
|
(pf != TJ.PF_GRAY && ext.equalsIgnoreCase("bmp") &&
|
||||||
|
pixelFormat != TJ.PF_BGR) ||
|
||||||
|
(pf != TJ.PF_GRAY && ext.equalsIgnoreCase("ppm") &&
|
||||||
|
pixelFormat != TJ.PF_RGB))
|
||||||
|
throw new Exception("TJCompressor.loadImage() returned unexpected " +
|
||||||
|
"pixel format: " + PIXFORMATSTR[pixelFormat]);
|
||||||
}
|
}
|
||||||
/* Verify that TJCompressor.loadSourceImage() returns the proper
|
|
||||||
"preferred" pixel format for the file type. */
|
|
||||||
pf = pixelFormat;
|
|
||||||
pixelFormat = TJ.PF_UNKNOWN;
|
|
||||||
tjc.loadSourceImage(filename, align, pixelFormat);
|
|
||||||
pixelFormat = tjc.getPixelFormat();
|
|
||||||
if ((pf == TJ.PF_GRAY && pixelFormat != TJ.PF_GRAY) ||
|
|
||||||
(pf != TJ.PF_GRAY && ext.equalsIgnoreCase("bmp") &&
|
|
||||||
pixelFormat != TJ.PF_BGR) ||
|
|
||||||
(pf != TJ.PF_GRAY && ext.equalsIgnoreCase("ppm") &&
|
|
||||||
pixelFormat != TJ.PF_RGB))
|
|
||||||
throw new Exception("TJCompressor.loadImage() returned unexpected " +
|
|
||||||
"pixel format: " + PIXFORMATSTR[pixelFormat]);
|
|
||||||
File file = new File(filename);
|
File file = new File(filename);
|
||||||
file.delete();
|
file.delete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
100
src/rdppm.c
100
src/rdppm.c
@@ -5,7 +5,7 @@
|
|||||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||||
* Modified 2009 by Bill Allombert, Guido Vollbeding.
|
* Modified 2009 by Bill Allombert, Guido Vollbeding.
|
||||||
* libjpeg-turbo Modifications:
|
* libjpeg-turbo Modifications:
|
||||||
* Copyright (C) 2015-2017, 2020-2024, D. R. Commander.
|
* Copyright (C) 2015-2017, 2020-2025, D. R. Commander.
|
||||||
* For conditions of distribution and use, see the accompanying README.ijg
|
* For conditions of distribution and use, see the accompanying README.ijg
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
@@ -217,7 +217,8 @@ get_text_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
} else {
|
} else {
|
||||||
for (col = cinfo->image_width; col > 0; col--) {
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
_JSAMPLE gray = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
_JSAMPLE gray = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
||||||
rgb_to_cmyk(maxval, gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, gray, gray, gray, ptr,
|
||||||
|
ptr + 1, ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,7 +296,8 @@ get_text_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
_JSAMPLE r = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
_JSAMPLE r = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
||||||
_JSAMPLE g = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
_JSAMPLE g = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
||||||
_JSAMPLE b = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
_JSAMPLE b = rescale[read_pbm_integer(cinfo, infile, maxval)];
|
||||||
rgb_to_cmyk(maxval, r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, r, g, b, ptr, ptr + 1,
|
||||||
|
ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,7 +388,8 @@ get_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
} else {
|
} else {
|
||||||
for (col = cinfo->image_width; col > 0; col--) {
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
_JSAMPLE gray = rescale[UCH(*bufferptr++)];
|
_JSAMPLE gray = rescale[UCH(*bufferptr++)];
|
||||||
rgb_to_cmyk(maxval, gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, gray, gray, gray, ptr,
|
||||||
|
ptr + 1, ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,7 +462,8 @@ get_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
_JSAMPLE r = rescale[UCH(*bufferptr++)];
|
_JSAMPLE r = rescale[UCH(*bufferptr++)];
|
||||||
_JSAMPLE g = rescale[UCH(*bufferptr++)];
|
_JSAMPLE g = rescale[UCH(*bufferptr++)];
|
||||||
_JSAMPLE b = rescale[UCH(*bufferptr++)];
|
_JSAMPLE b = rescale[UCH(*bufferptr++)];
|
||||||
rgb_to_cmyk(maxval, r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, r, g, b, ptr, ptr + 1,
|
||||||
|
ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,15 +564,29 @@ get_word_gray_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
ERREXIT(cinfo, JERR_INPUT_EOF);
|
ERREXIT(cinfo, JERR_INPUT_EOF);
|
||||||
ptr = source->pub._buffer[0];
|
ptr = source->pub._buffer[0];
|
||||||
bufferptr = source->iobuffer;
|
bufferptr = source->iobuffer;
|
||||||
for (col = cinfo->image_width; col > 0; col--) {
|
if (maxval == (1U << cinfo->data_precision) - 1U) {
|
||||||
register unsigned int gray;
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
gray = UCH(*bufferptr++) << 8;
|
register unsigned int gray;
|
||||||
gray |= UCH(*bufferptr++);
|
gray = UCH(*bufferptr++) << 8;
|
||||||
if (gray > maxval)
|
gray |= UCH(*bufferptr++);
|
||||||
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
if (gray > maxval)
|
||||||
rgb_to_cmyk(maxval, rescale[gray], rescale[gray], rescale[gray], ptr,
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
ptr + 1, ptr + 2, ptr + 3);
|
rgb_to_cmyk(maxval, gray, gray, gray, ptr, ptr + 1, ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
|
register unsigned int temp;
|
||||||
|
_JSAMPLE gray;
|
||||||
|
temp = UCH(*bufferptr++) << 8;
|
||||||
|
temp |= UCH(*bufferptr++);
|
||||||
|
if (temp > maxval)
|
||||||
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
|
gray = rescale[temp];
|
||||||
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, gray, gray, gray, ptr,
|
||||||
|
ptr + 1, ptr + 2, ptr + 3);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -634,23 +652,43 @@ get_word_rgb_cmyk_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
|
|||||||
ERREXIT(cinfo, JERR_INPUT_EOF);
|
ERREXIT(cinfo, JERR_INPUT_EOF);
|
||||||
ptr = source->pub._buffer[0];
|
ptr = source->pub._buffer[0];
|
||||||
bufferptr = source->iobuffer;
|
bufferptr = source->iobuffer;
|
||||||
for (col = cinfo->image_width; col > 0; col--) {
|
if (maxval == (1U << cinfo->data_precision) - 1U) {
|
||||||
register unsigned int r, g, b;
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
r = UCH(*bufferptr++) << 8;
|
register unsigned int r, g, b;
|
||||||
r |= UCH(*bufferptr++);
|
r = UCH(*bufferptr++) << 8;
|
||||||
if (r > maxval)
|
r |= UCH(*bufferptr++);
|
||||||
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
if (r > maxval)
|
||||||
g = UCH(*bufferptr++) << 8;
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
g |= UCH(*bufferptr++);
|
g = UCH(*bufferptr++) << 8;
|
||||||
if (g > maxval)
|
g |= UCH(*bufferptr++);
|
||||||
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
if (g > maxval)
|
||||||
b = UCH(*bufferptr++) << 8;
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
b |= UCH(*bufferptr++);
|
b = UCH(*bufferptr++) << 8;
|
||||||
if (b > maxval)
|
b |= UCH(*bufferptr++);
|
||||||
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
if (b > maxval)
|
||||||
rgb_to_cmyk(maxval, rescale[r], rescale[g], rescale[b], ptr, ptr + 1,
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
ptr + 2, ptr + 3);
|
rgb_to_cmyk(maxval, r, g, b, ptr, ptr + 1, ptr + 2, ptr + 3);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (col = cinfo->image_width; col > 0; col--) {
|
||||||
|
register unsigned int r, g, b;
|
||||||
|
r = UCH(*bufferptr++) << 8;
|
||||||
|
r |= UCH(*bufferptr++);
|
||||||
|
if (r > maxval)
|
||||||
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
|
g = UCH(*bufferptr++) << 8;
|
||||||
|
g |= UCH(*bufferptr++);
|
||||||
|
if (g > maxval)
|
||||||
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
|
b = UCH(*bufferptr++) << 8;
|
||||||
|
b |= UCH(*bufferptr++);
|
||||||
|
if (b > maxval)
|
||||||
|
ERREXIT(cinfo, JERR_PPM_OUTOFRANGE);
|
||||||
|
rgb_to_cmyk((1 << cinfo->data_precision) - 1, rescale[r], rescale[g],
|
||||||
|
rescale[b], ptr, ptr + 1, ptr + 2, ptr + 3);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
251
src/tjunittest.c
251
src/tjunittest.c
@@ -199,11 +199,11 @@ static void initBuf(void *buf, int w, int h, int pf, int bottomUp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int getVal(void *buf, int index)
|
static int getVal(void *buf, int index, int targetPrecision)
|
||||||
{
|
{
|
||||||
if (precision <= 8)
|
if (targetPrecision <= 8)
|
||||||
return ((unsigned char *)buf)[index];
|
return ((unsigned char *)buf)[index];
|
||||||
else if (precision <= 12)
|
else if (targetPrecision <= 12)
|
||||||
return ((short *)buf)[index];
|
return ((short *)buf)[index];
|
||||||
else
|
else
|
||||||
return ((unsigned short *)buf)[index];
|
return ((unsigned short *)buf)[index];
|
||||||
@@ -230,10 +230,10 @@ static int checkBuf(void *buf, int w, int h, int pf, int subsamp,
|
|||||||
|
|
||||||
if (bottomUp) index = (h - row - 1) * w + col;
|
if (bottomUp) index = (h - row - 1) * w + col;
|
||||||
else index = row * w + col;
|
else index = row * w + col;
|
||||||
c = getVal(buf, index * ps);
|
c = getVal(buf, index * ps, precision);
|
||||||
m = getVal(buf, index * ps + 1);
|
m = getVal(buf, index * ps + 1, precision);
|
||||||
y = getVal(buf, index * ps + 2);
|
y = getVal(buf, index * ps + 2, precision);
|
||||||
k = getVal(buf, index * ps + 3);
|
k = getVal(buf, index * ps + 3, precision);
|
||||||
if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
|
if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
|
||||||
CHECKVALMAX(c); CHECKVALMAX(m); CHECKVALMAX(y);
|
CHECKVALMAX(c); CHECKVALMAX(m); CHECKVALMAX(y);
|
||||||
if (row < halfway) CHECKVALMAX(k)
|
if (row < halfway) CHECKVALMAX(k)
|
||||||
@@ -254,10 +254,11 @@ static int checkBuf(void *buf, int w, int h, int pf, int subsamp,
|
|||||||
|
|
||||||
if (bottomUp) index = (h - row - 1) * w + col;
|
if (bottomUp) index = (h - row - 1) * w + col;
|
||||||
else index = row * w + col;
|
else index = row * w + col;
|
||||||
r = getVal(buf, index * ps + roffset);
|
r = getVal(buf, index * ps + roffset, precision);
|
||||||
g = getVal(buf, index * ps + goffset);
|
g = getVal(buf, index * ps + goffset, precision);
|
||||||
b = getVal(buf, index * ps + boffset);
|
b = getVal(buf, index * ps + boffset, precision);
|
||||||
a = aoffset >= 0 ? getVal(buf, index * ps + aoffset) : maxSample;
|
a = aoffset >= 0 ? getVal(buf, index * ps + aoffset, precision) :
|
||||||
|
maxSample;
|
||||||
if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
|
if (((row / blocksize) + (col / blocksize)) % 2 == 0) {
|
||||||
if (row < halfway) {
|
if (row < halfway) {
|
||||||
CHECKVALMAX(r); CHECKVALMAX(g); CHECKVALMAX(b);
|
CHECKVALMAX(r); CHECKVALMAX(g); CHECKVALMAX(b);
|
||||||
@@ -289,15 +290,16 @@ bailout:
|
|||||||
for (row = 0; row < h; row++) {
|
for (row = 0; row < h; row++) {
|
||||||
for (col = 0; col < w; col++) {
|
for (col = 0; col < w; col++) {
|
||||||
if (pf == TJPF_CMYK)
|
if (pf == TJPF_CMYK)
|
||||||
printf("%.3d/%.3d/%.3d/%.3d ", getVal(buf, (row * w + col) * ps),
|
printf("%.3d/%.3d/%.3d/%.3d ",
|
||||||
getVal(buf, (row * w + col) * ps + 1),
|
getVal(buf, (row * w + col) * ps, precision),
|
||||||
getVal(buf, (row * w + col) * ps + 2),
|
getVal(buf, (row * w + col) * ps + 1, precision),
|
||||||
getVal(buf, (row * w + col) * ps + 3));
|
getVal(buf, (row * w + col) * ps + 2, precision),
|
||||||
|
getVal(buf, (row * w + col) * ps + 3, precision));
|
||||||
else
|
else
|
||||||
printf("%.3d/%.3d/%.3d ",
|
printf("%.3d/%.3d/%.3d ",
|
||||||
getVal(buf, (row * w + col) * ps + roffset),
|
getVal(buf, (row * w + col) * ps + roffset, precision),
|
||||||
getVal(buf, (row * w + col) * ps + goffset),
|
getVal(buf, (row * w + col) * ps + goffset, precision),
|
||||||
getVal(buf, (row * w + col) * ps + boffset));
|
getVal(buf, (row * w + col) * ps + boffset, precision));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@@ -909,15 +911,16 @@ static void initBitmap(void *buf, int width, int pitch, int height, int pf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cmyk_to_rgb(int c, int m, int y, int k, int *r, int *g, int *b)
|
static void cmyk_to_rgb(int c, int m, int y, int k, int *r, int *g, int *b,
|
||||||
|
int targetMaxSample)
|
||||||
{
|
{
|
||||||
*r = (int)((double)c * (double)k / (double)maxSample + 0.5);
|
*r = (int)((double)c * (double)k / (double)targetMaxSample + 0.5);
|
||||||
*g = (int)((double)m * (double)k / (double)maxSample + 0.5);
|
*g = (int)((double)m * (double)k / (double)targetMaxSample + 0.5);
|
||||||
*b = (int)((double)y * (double)k / (double)maxSample + 0.5);
|
*b = (int)((double)y * (double)k / (double)targetMaxSample + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmpBitmap(void *buf, int width, int pitch, int height, int pf,
|
static int cmpBitmap(void *buf, int width, int pitch, int height, int pf,
|
||||||
int bottomUp, int gray2rgb)
|
int bottomUp, int gray2rgb, int targetPrecision)
|
||||||
{
|
{
|
||||||
int roffset = tjRedOffset[pf];
|
int roffset = tjRedOffset[pf];
|
||||||
int goffset = tjGreenOffset[pf];
|
int goffset = tjGreenOffset[pf];
|
||||||
@@ -925,6 +928,7 @@ static int cmpBitmap(void *buf, int width, int pitch, int height, int pf,
|
|||||||
int aoffset = tjAlphaOffset[pf];
|
int aoffset = tjAlphaOffset[pf];
|
||||||
int ps = tjPixelSize[pf];
|
int ps = tjPixelSize[pf];
|
||||||
int i, j;
|
int i, j;
|
||||||
|
int targetMaxSample = (1 << targetPrecision) - 1;
|
||||||
|
|
||||||
for (j = 0; j < height; j++) {
|
for (j = 0; j < height; j++) {
|
||||||
int row = bottomUp ? height - j - 1 : j;
|
int row = bottomUp ? height - j - 1 : j;
|
||||||
@@ -935,32 +939,51 @@ static int cmpBitmap(void *buf, int width, int pitch, int height, int pf,
|
|||||||
int b = (j * (maxSample + 1) / height +
|
int b = (j * (maxSample + 1) / height +
|
||||||
i * (maxSample + 1) / width) % (maxSample + 1);
|
i * (maxSample + 1) / width) % (maxSample + 1);
|
||||||
|
|
||||||
|
if (precision != targetPrecision) {
|
||||||
|
long halfMaxSample = maxSample / 2;
|
||||||
|
|
||||||
|
r = (int)((r * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
g = (int)((g * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
b = (int)((b * ((1 << targetPrecision) - 1) + halfMaxSample) /
|
||||||
|
maxSample);
|
||||||
|
}
|
||||||
|
|
||||||
if (pf == TJPF_GRAY) {
|
if (pf == TJPF_GRAY) {
|
||||||
if (getVal(buf, row * pitch + i * ps) != b)
|
if (getVal(buf, row * pitch + i * ps, targetPrecision) != b)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (pf == TJPF_CMYK) {
|
} else if (pf == TJPF_CMYK) {
|
||||||
int rf, gf, bf;
|
int rf, gf, bf;
|
||||||
|
|
||||||
cmyk_to_rgb(getVal(buf, row * pitch + i * ps + 0),
|
cmyk_to_rgb(getVal(buf, row * pitch + i * ps + 0, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 1),
|
getVal(buf, row * pitch + i * ps + 1, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 2),
|
getVal(buf, row * pitch + i * ps + 2, targetPrecision),
|
||||||
getVal(buf, row * pitch + i * ps + 3), &rf, &gf, &bf);
|
getVal(buf, row * pitch + i * ps + 3, targetPrecision),
|
||||||
|
&rf, &gf, &bf, targetMaxSample);
|
||||||
if (gray2rgb) {
|
if (gray2rgb) {
|
||||||
if (rf != b || gf != b || bf != b)
|
if (rf != b || gf != b || bf != b)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rf != r || gf != g || bf != b) return 0;
|
} else if (rf != r || gf != g || bf != b) return 0;
|
||||||
} else {
|
} else {
|
||||||
if (gray2rgb) {
|
if (gray2rgb) {
|
||||||
if (getVal(buf, row * pitch + i * ps + roffset) != b ||
|
if (getVal(buf, row * pitch + i * ps + roffset,
|
||||||
getVal(buf, row * pitch + i * ps + goffset) != b ||
|
targetPrecision) != b ||
|
||||||
getVal(buf, row * pitch + i * ps + boffset) != b)
|
getVal(buf, row * pitch + i * ps + goffset,
|
||||||
|
targetPrecision) != b ||
|
||||||
|
getVal(buf, row * pitch + i * ps + boffset,
|
||||||
|
targetPrecision) != b)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (getVal(buf, row * pitch + i * ps + roffset) != r ||
|
} else if (getVal(buf, row * pitch + i * ps + roffset,
|
||||||
getVal(buf, row * pitch + i * ps + goffset) != g ||
|
targetPrecision) != r ||
|
||||||
getVal(buf, row * pitch + i * ps + boffset) != b)
|
getVal(buf, row * pitch + i * ps + goffset,
|
||||||
|
targetPrecision) != g ||
|
||||||
|
getVal(buf, row * pitch + i * ps + boffset,
|
||||||
|
targetPrecision) != b)
|
||||||
return 0;
|
return 0;
|
||||||
if (aoffset >= 0 &&
|
if (aoffset >= 0 &&
|
||||||
getVal(buf, row * pitch + i * ps + aoffset) != maxSample)
|
getVal(buf, row * pitch + i * ps + aoffset,
|
||||||
|
targetPrecision) != targetMaxSample)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -998,16 +1021,18 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf,
|
|||||||
"00fc2803bca103ff75785ea0dca992aa", "d8c91fac522c16b029e514d331a22bc4",
|
"00fc2803bca103ff75785ea0dca992aa", "d8c91fac522c16b029e514d331a22bc4",
|
||||||
"e50cff0b3562ed7e64dbfc093440e333", "64f3320b226ea37fb58080713b4df1b2"
|
"e50cff0b3562ed7e64dbfc093440e333", "64f3320b226ea37fb58080713b4df1b2"
|
||||||
};
|
};
|
||||||
|
int targetPrecision, maxTargetPrecision = 16;
|
||||||
|
|
||||||
if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL)
|
if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL)
|
||||||
THROW_TJ(NULL);
|
THROW_TJ(NULL);
|
||||||
TRY_TJ(handle, tj3Set(handle, TJPARAM_BOTTOMUP, bottomUp));
|
TRY_TJ(handle, tj3Set(handle, TJPARAM_BOTTOMUP, bottomUp));
|
||||||
TRY_TJ(handle, tj3Set(handle, TJPARAM_PRECISION, precision));
|
TRY_TJ(handle, tj3Set(handle, TJPARAM_PRECISION, precision));
|
||||||
|
|
||||||
if (precision == 8 && !strcasecmp(ext, "bmp"))
|
if (precision == 8 && !strcasecmp(ext, "bmp")) {
|
||||||
md5ref = (pf == TJPF_GRAY ? "51976530acf75f02beddf5d21149101d" :
|
md5ref = (pf == TJPF_GRAY ? "51976530acf75f02beddf5d21149101d" :
|
||||||
"6d659071b9bfcdee2def22cb58ddadca");
|
"6d659071b9bfcdee2def22cb58ddadca");
|
||||||
else
|
maxTargetPrecision = 8;
|
||||||
|
} else
|
||||||
md5ref = (pf == TJPF_GRAY ? grayPPMRefs[precision] :
|
md5ref = (pf == TJPF_GRAY ? grayPPMRefs[precision] :
|
||||||
colorPPMRefs[precision]);
|
colorPPMRefs[precision]);
|
||||||
|
|
||||||
@@ -1027,6 +1052,7 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf,
|
|||||||
TRY_TJ(handle, tj3SaveImage16(handle, filename, (unsigned short *)buf,
|
TRY_TJ(handle, tj3SaveImage16(handle, filename, (unsigned short *)buf,
|
||||||
width, pitch, height, pf));
|
width, pitch, height, pf));
|
||||||
}
|
}
|
||||||
|
tj3Free(buf); buf = NULL;
|
||||||
md5sum = MD5File(filename, md5buf);
|
md5sum = MD5File(filename, md5buf);
|
||||||
if (!md5sum) {
|
if (!md5sum) {
|
||||||
printf("\n Could not determine MD5 sum of %s\n", filename);
|
printf("\n Could not determine MD5 sum of %s\n", filename);
|
||||||
@@ -1035,36 +1061,16 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf,
|
|||||||
if (strcasecmp(md5sum, md5ref))
|
if (strcasecmp(md5sum, md5ref))
|
||||||
THROW_MD5(filename, md5sum, md5ref);
|
THROW_MD5(filename, md5sum, md5ref);
|
||||||
|
|
||||||
tj3Free(buf); buf = NULL;
|
for (targetPrecision = 2; targetPrecision <= maxTargetPrecision;
|
||||||
if (precision <= 8) {
|
targetPrecision++) {
|
||||||
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align, &loadHeight,
|
TRY_TJ(handle, tj3Set(handle, TJPARAM_PRECISION, targetPrecision));
|
||||||
&pf)) == NULL)
|
pf = pixelFormat;
|
||||||
THROW_TJ(handle);
|
|
||||||
} else if (precision <= 12) {
|
if (targetPrecision <= 8) {
|
||||||
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align, &loadHeight,
|
|
||||||
&pf)) == NULL)
|
|
||||||
THROW_TJ(handle);
|
|
||||||
} else {
|
|
||||||
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align, &loadHeight,
|
|
||||||
&pf)) == NULL)
|
|
||||||
THROW_TJ(handle);
|
|
||||||
}
|
|
||||||
if (width != loadWidth || height != loadHeight) {
|
|
||||||
printf("\n Image dimensions of %s are bogus\n", filename);
|
|
||||||
retval = -1; goto bailout;
|
|
||||||
}
|
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 0)) {
|
|
||||||
printf("\n Pixel data in %s is bogus\n", filename);
|
|
||||||
retval = -1; goto bailout;
|
|
||||||
}
|
|
||||||
if (pf == TJPF_GRAY) {
|
|
||||||
tj3Free(buf); buf = NULL;
|
|
||||||
pf = TJPF_XBGR;
|
|
||||||
if (precision <= 8) {
|
|
||||||
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pf)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
} else if (precision <= 12) {
|
} else if (targetPrecision <= 12) {
|
||||||
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pf)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
@@ -1073,60 +1079,95 @@ static int doBmpTest(const char *ext, int width, int align, int height, int pf,
|
|||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pf)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
}
|
}
|
||||||
pitch = PAD(width * tjPixelSize[pf], align);
|
if (width != loadWidth || height != loadHeight) {
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 1)) {
|
printf("\n Image dimensions of %s are bogus\n", filename);
|
||||||
printf("\n Converting %s to RGB failed\n", filename);
|
|
||||||
retval = -1; goto bailout;
|
retval = -1; goto bailout;
|
||||||
}
|
}
|
||||||
|
pitch = PAD(width * tjPixelSize[pf], align);
|
||||||
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 0,
|
||||||
|
!strcasecmp(ext, "bmp") ? 8 : targetPrecision)) {
|
||||||
|
printf("\n Pixel data in %s is bogus\n", filename);
|
||||||
|
printf(" (target data precision = %d)\n", targetPrecision);
|
||||||
|
retval = -1; goto bailout;
|
||||||
|
}
|
||||||
|
tj3Free(buf); buf = NULL;
|
||||||
|
|
||||||
|
if (pf == TJPF_GRAY) {
|
||||||
|
pf = TJPF_XBGR;
|
||||||
|
if (targetPrecision <= 8) {
|
||||||
|
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
} else if (targetPrecision <= 12) {
|
||||||
|
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
} else {
|
||||||
|
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
}
|
||||||
|
pitch = PAD(width * tjPixelSize[pf], align);
|
||||||
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 1,
|
||||||
|
!strcasecmp(ext, "bmp") ? 8 : targetPrecision)) {
|
||||||
|
printf("\n Converting %s to RGB failed\n", filename);
|
||||||
|
printf(" (target data precision = %d)\n", targetPrecision);
|
||||||
|
retval = -1; goto bailout;
|
||||||
|
}
|
||||||
|
tj3Free(buf); buf = NULL;
|
||||||
|
|
||||||
|
pf = TJPF_CMYK;
|
||||||
|
if (targetPrecision <= 8) {
|
||||||
|
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
} else if (targetPrecision <= 12) {
|
||||||
|
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
} else {
|
||||||
|
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align,
|
||||||
|
&loadHeight, &pf)) == NULL)
|
||||||
|
THROW_TJ(handle);
|
||||||
|
}
|
||||||
|
pitch = PAD(width * tjPixelSize[pf], align);
|
||||||
|
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 1,
|
||||||
|
!strcasecmp(ext, "bmp") ? 8 : targetPrecision)) {
|
||||||
|
printf("\n Converting %s to CMYK failed\n", filename);
|
||||||
|
printf(" (target data precision = %d)\n", targetPrecision);
|
||||||
|
retval = -1; goto bailout;
|
||||||
|
}
|
||||||
|
tj3Free(buf); buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tj3Free(buf); buf = NULL;
|
/* Verify that tj3LoadImage*() returns the proper "preferred" pixel format
|
||||||
pf = TJPF_CMYK;
|
for the file type. */
|
||||||
if (precision <= 8) {
|
pf = pixelFormat;
|
||||||
|
pixelFormat = TJPF_UNKNOWN;
|
||||||
|
if (targetPrecision <= 8) {
|
||||||
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align,
|
||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pixelFormat)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
} else if (precision <= 12) {
|
} else if (targetPrecision <= 12) {
|
||||||
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align,
|
||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pixelFormat)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
} else {
|
} else {
|
||||||
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align,
|
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align,
|
||||||
&loadHeight, &pf)) == NULL)
|
&loadHeight, &pixelFormat)) == NULL)
|
||||||
THROW_TJ(handle);
|
THROW_TJ(handle);
|
||||||
}
|
}
|
||||||
pitch = PAD(width * tjPixelSize[pf], align);
|
tj3Free(buf); buf = NULL;
|
||||||
if (!cmpBitmap(buf, width, pitch, height, pf, bottomUp, 1)) {
|
if ((pf == TJPF_GRAY && pixelFormat != TJPF_GRAY) ||
|
||||||
printf("\n Converting %s to CMYK failed\n", filename);
|
(pf != TJPF_GRAY && !strcasecmp(ext, "bmp") &&
|
||||||
retval = -1; goto bailout;
|
pixelFormat != TJPF_BGR) ||
|
||||||
|
(pf != TJPF_GRAY && !strcasecmp(ext, "ppm") &&
|
||||||
|
pixelFormat != TJPF_RGB)) {
|
||||||
|
printf("\n tj3LoadImage8() returned unexpected pixel format: %s\n",
|
||||||
|
pixFormatStr[pixelFormat]);
|
||||||
|
retval = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Verify that tj3LoadImage*() returns the proper "preferred" pixel format
|
|
||||||
for the file type. */
|
|
||||||
tj3Free(buf); buf = NULL;
|
|
||||||
pf = pixelFormat;
|
|
||||||
pixelFormat = TJPF_UNKNOWN;
|
|
||||||
if (precision <= 8) {
|
|
||||||
if ((buf = tj3LoadImage8(handle, filename, &loadWidth, align, &loadHeight,
|
|
||||||
&pixelFormat)) == NULL)
|
|
||||||
THROW_TJ(handle);
|
|
||||||
} else if (precision <= 12) {
|
|
||||||
if ((buf = tj3LoadImage12(handle, filename, &loadWidth, align, &loadHeight,
|
|
||||||
&pixelFormat)) == NULL)
|
|
||||||
THROW_TJ(handle);
|
|
||||||
} else {
|
|
||||||
if ((buf = tj3LoadImage16(handle, filename, &loadWidth, align, &loadHeight,
|
|
||||||
&pixelFormat)) == NULL)
|
|
||||||
THROW_TJ(handle);
|
|
||||||
}
|
|
||||||
if ((pf == TJPF_GRAY && pixelFormat != TJPF_GRAY) ||
|
|
||||||
(pf != TJPF_GRAY && !strcasecmp(ext, "bmp") &&
|
|
||||||
pixelFormat != TJPF_BGR) ||
|
|
||||||
(pf != TJPF_GRAY && !strcasecmp(ext, "ppm") &&
|
|
||||||
pixelFormat != TJPF_RGB)) {
|
|
||||||
printf("\n tj3LoadImage8() returned unexpected pixel format: %s\n",
|
|
||||||
pixFormatStr[pixelFormat]);
|
|
||||||
retval = -1;
|
|
||||||
}
|
|
||||||
unlink(filename);
|
unlink(filename);
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
|
|||||||
Reference in New Issue
Block a user