From 38cb1ec2a77b7209a260f3cced1e6c6365616c8e Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 23 Aug 2013 04:45:43 +0000 Subject: [PATCH] Add CMYK support to the TurboJPEG Java API & clean up a few things in the C API git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@1020 632fc199-4ca6-4c93-a231-07263d6284db --- Makefile.am | 16 +- java/TJUnitTest.java | 95 +++++++-- java/doc/constant-values.html | 44 ++++- java/doc/index-all.html | 26 ++- java/doc/org/libjpegturbo/turbojpeg/TJ.html | 180 ++++++++++++++++++ .../libjpegturbo/turbojpeg/TJCompressor.html | 4 +- .../turbojpeg/TJCustomFilter.html | 4 +- .../turbojpeg/TJDecompressor.html | 18 ++ .../libjpegturbo/turbojpeg/TJTransformer.html | 2 +- java/org/libjpegturbo/turbojpeg/TJ.java | 80 +++++++- .../libjpegturbo/turbojpeg/TJCompressor.java | 4 +- .../turbojpeg/TJCustomFilter.java | 2 +- .../turbojpeg/TJDecompressor.java | 1 + java/org_libjpegturbo_turbojpeg_TJ.h | 20 +- tjbench.c | 4 +- tjunittest.c | 2 +- turbojpeg-jni.c | 8 +- turbojpeg.h | 60 +++--- 18 files changed, 497 insertions(+), 73 deletions(-) diff --git a/Makefile.am b/Makefile.am index bd77c33..6096049 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,14 +196,14 @@ MD5_JPEG_CROP = b4197f377e621c4e9b1d20471432610d test: testclean all if WITH_TURBOJPEG -#if WITH_JAVA -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -bi -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -noyuvpad -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -bi -# $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -bi -noyuvpad -#endif +if WITH_JAVA + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -bi + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -noyuvpad + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -bi + $(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -bi -noyuvpad +endif ./tjunittest ./tjunittest -alloc ./tjunittest -yuv diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java index b484000..56226e2 100644 --- a/java/TJUnitTest.java +++ b/java/TJUnitTest.java @@ -61,11 +61,11 @@ public class TJUnitTest { private static final String[] pixFormatStr = { "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale", - "RGBA", "BGRA", "ABGR", "ARGB" + "RGBA", "BGRA", "ABGR", "ARGB", "CMYK" }; private static final int[] alphaOffset = { - -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0 + -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1 }; private static final int[] _3byteFormats = { @@ -75,7 +75,7 @@ public class TJUnitTest { BufferedImage.TYPE_3BYTE_BGR }; private static final int[] _4byteFormats = { - TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB + TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB, TJ.PF_CMYK }; private static final int[] _4byteFormatsBI = { BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_INT_RGB, @@ -165,8 +165,8 @@ public class TJUnitTest { int ps = TJ.getPixelSize(pf); int index, row, col, halfway = 16; - Arrays.fill(buf, (byte)0); if (pf == TJ.PF_GRAY) { + Arrays.fill(buf, (byte)0); for (row = 0; row < h; row++) { for (col = 0; col < w; col++) { if ((flags & TJ.FLAG_BOTTOMUP) != 0) @@ -181,6 +181,27 @@ public class TJUnitTest { } return; } + if (pf == TJ.PF_CMYK) { + Arrays.fill(buf, (byte)255); + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + if ((flags & TJ.FLAG_BOTTOMUP) != 0) + index = (h - row - 1) * w + col; + else + index = row * w + col; + if (((row / 8) + (col / 8)) % 2 == 0) { + if (row >= halfway) buf[index * ps + 3] = 0; + } else { + buf[index * ps + 2] = 0; + if (row < halfway) + buf[index * ps + 1] = 0; + } + } + } + return; + } + + Arrays.fill(buf, (byte)0); for (row = 0; row < h; row++) { for (col = 0; col < w; col++) { if ((flags & TJ.FLAG_BOTTOMUP) != 0) @@ -299,6 +320,39 @@ public class TJUnitTest { int blockSize = 8 * sf.getNum() / sf.getDenom(); try { + + if (pf == TJ.PF_CMYK) { + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + if ((flags & TJ.FLAG_BOTTOMUP) != 0) + index = (h - row - 1) * w + col; + else + index = row * w + col; + byte c = buf[index * ps]; + byte m = buf[index * ps + 1]; + byte y = buf[index * ps + 2]; + byte k = buf[index * ps + 3]; + checkVal255(row, col, c, "C"); + if (((row / blockSize) + (col / blockSize)) % 2 == 0) { + checkVal255(row, col, m, "M"); + checkVal255(row, col, y, "Y"); + if (row < halfway) + checkVal255(row, col, k, "K"); + else + checkVal0(row, col, k, "K"); + } else { + checkVal0(row, col, y, "Y"); + checkVal255(row, col, k, "K"); + if (row < halfway) + checkVal0(row, col, m, "M"); + else + checkVal255(row, col, m, "M"); + } + } + } + return 1; + } + for (row = 0; row < halfway; row++) { for (col = 0; col < w; col++) { if ((flags & TJ.FLAG_BOTTOMUP) != 0) @@ -351,13 +405,25 @@ public class TJUnitTest { if (retval == 0) { for (row = 0; row < h; row++) { for (col = 0; col < w; col++) { - int r = buf[pitch * row + col * ps + roffset]; - int g = buf[pitch * row + col * ps + goffset]; - int b = buf[pitch * row + col * ps + boffset]; - if (r < 0) r += 256; - if (g < 0) g += 256; - if (b < 0) b += 256; - System.out.format("%3d/%3d/%3d ", r, g, b); + if (pf == TJ.PF_CMYK) { + int c = buf[pitch * row + col * ps]; + int m = buf[pitch * row + col * ps + 1]; + int y = buf[pitch * row + col * ps + 2]; + int k = buf[pitch * row + col * ps + 3]; + if (c < 0) c += 256; + if (m < 0) m += 256; + if (y < 0) y += 256; + if (k < 0) k += 256; + System.out.format("%3d/%3d/%3d/%3d ", c, m, y, k); + } else { + int r = buf[pitch * row + col * ps + roffset]; + int g = buf[pitch * row + col * ps + goffset]; + int b = buf[pitch * row + col * ps + boffset]; + if (r < 0) r += 256; + if (g < 0) g += 256; + if (b < 0) b += 256; + System.out.format("%3d/%3d/%3d ", r, g, b); + } } System.out.print("\n"); } @@ -788,6 +854,7 @@ public class TJUnitTest { tjd = new TJDecompressor(); for (int pf : formats) { + if (pf < 0) continue; for (int i = 0; i < 2; i++) { int flags = 0; if (subsamp == TJ.SAMP_422 || subsamp == TJ.SAMP_420 || @@ -880,7 +947,10 @@ public class TJUnitTest { testName = "javabitest"; } } - if (doyuv) yuv = YUVENCODE; + if (doyuv) { + yuv = YUVENCODE; + _4byteFormats[4] = -1; + } doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_444, testName); doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_444, @@ -904,6 +974,7 @@ public class TJUnitTest { doTest(39, 41, bi ? onlyGrayBI : onlyGray, TJ.SAMP_GRAY, testName); doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY, testName); + _4byteFormats[4] = -1; doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY, testName); if (!doyuv && !bi) diff --git a/java/doc/constant-values.html b/java/doc/constant-values.html index e1a5a98..01f950f 100644 --- a/java/doc/constant-values.html +++ b/java/doc/constant-values.html @@ -99,6 +99,36 @@ org.libjpegturbo.* org.libjpegturbo.turbojpeg.TJ + +public static final int +CS_CMYK +3 + + + +public static final int +CS_GRAY +2 + + + +public static final int +CS_RGB +0 + + + +public static final int +CS_YCbCr +1 + + + +public static final int +CS_YCCK +4 + + public static final int FLAG_ACCURATEDCT @@ -147,10 +177,16 @@ org.libjpegturbo.* 128 + +public static final int +NUMCS +5 + + public static final int NUMPF -11 +12 @@ -189,6 +225,12 @@ org.libjpegturbo.* 3 + +public static final int +PF_CMYK +11 + + public static final int PF_GRAY diff --git a/java/doc/index-all.html b/java/doc/index-all.html index 2630fb1..876410e 100644 --- a/java/doc/index-all.html +++ b/java/doc/index-all.html @@ -119,11 +119,26 @@ Method in class org.libjpegturbo.turbojpeg.TJCompressor
Compress the uncompressed source image stored in srcImage and return a buffer containing a JPEG image. +
CS_CMYK - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
CMYK colorspace. +
CS_GRAY - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
Grayscale colorspace. +
CS_RGB - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
RGB colorspace. +
CS_YCbCr - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
YCbCr colorspace. +
CS_YCCK - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
YCCK colorspace.
customFilter(ShortBuffer, Rectangle, Rectangle, int, int, TJTransform) - Method in interface org.libjpegturbo.turbojpeg.TJCustomFilter
A callback function that can be used to modify the DCT coefficients after they are losslessly transformed but before they are transcoded to a new - JPEG file. + JPEG image.

@@ -344,6 +359,9 @@ Variable in class org.libjpegturbo.turbojpeg.jpegBufSize - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
  +
jpegColorspace - +Variable in class org.libjpegturbo.turbojpeg.TJDecompressor +
 
jpegHeight - Variable in class org.libjpegturbo.turbojpeg.TJDecompressor
  @@ -358,6 +376,9 @@ Variable in class org.libjpegturbo.turbojpeg.

N

+
NUMCS - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
The number of JPEG colorspaces
NUMOP - Static variable in class org.libjpegturbo.turbojpeg.TJTransform
The number of lossless transform operations @@ -442,6 +463,9 @@ Static variable in class org.libjpegturbo.turbojpeg.PF_BGRX - Static variable in class org.libjpegturbo.turbojpeg.TJ
BGRX pixel format. +
PF_CMYK - +Static variable in class org.libjpegturbo.turbojpeg.TJ +
CMYK pixel format.
PF_GRAY - Static variable in class org.libjpegturbo.turbojpeg.TJ
Grayscale pixel format. diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html index 2f27246..b832cf8 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html @@ -115,6 +115,46 @@ TurboJPEG utility class (cannot be instantiated) static int +CS_CMYK + +
+          CMYK colorspace. + + + +static int +CS_GRAY + +
+          Grayscale colorspace. + + + +static int +CS_RGB + +
+          RGB colorspace. + + + +static int +CS_YCbCr + +
+          YCbCr colorspace. + + + +static int +CS_YCCK + +
+          YCCK colorspace. + + + +static int FLAG_ACCURATEDCT
@@ -187,6 +227,14 @@ TurboJPEG utility class (cannot be instantiated) static int +NUMCS + +
+          The number of JPEG colorspaces + + + +static int NUMPF
@@ -243,6 +291,14 @@ TurboJPEG utility class (cannot be instantiated) static int +PF_CMYK + +
+          CMYK pixel format. + + + +static int PF_GRAY
@@ -746,6 +802,130 @@ public static final int PF_ARGB

+

+PF_CMYK

+
+public static final int PF_CMYK
+
+
CMYK pixel format. Unlike RGB, which is a display colorspace, + CMYK (Cyan/Magenta/Yellow/Key) is a print colorspace in which the + value of each color component corresponds to the amount of cyan, magenta, + yellow, or black ink that is applied to a white background. In order to + convert between CMYK and RGB, it is necessary to use a color management + system (CMS.) A CMS will attempt to map colors within the printer's gamut + to perceptually similar colors in the display's gamut and vice versa, but + the mapping is typically not 1:1 or reversible, nor can it be defined with + a simple formula. Thus, such a conversion is out of scope for a codec + library. However, the TurboJPEG API allows for compressing CMYK pixels + into a YCCK JPEG image (see CS_YCCK) and decompressing YCCK JPEG + images into CMYK pixels. +

+

+
See Also:
Constant Field Values
+
+
+ +

+NUMCS

+
+public static final int NUMCS
+
+
The number of JPEG colorspaces +

+

+
See Also:
Constant Field Values
+
+
+ +

+CS_RGB

+
+public static final int CS_RGB
+
+
RGB colorspace. When compressing the JPEG image, the R, G, and B + components in the source image are reordered into image planes, but no + colorspace conversion or subsampling is performed. RGB JPEG images can be + decompressed to any of the extended RGB pixel formats or grayscale, but + they cannot be decompressed to YUV images. +

+

+
See Also:
Constant Field Values
+
+
+ +

+CS_YCbCr

+
+public static final int CS_YCbCr
+
+
YCbCr colorspace. YCbCr is not an absolute colorspace but rather a + mathematical transformation of RGB designed solely for storage and + transmission. YCbCr images must be converted to RGB before they can + actually be displayed. In the YCbCr colorspace, the Y (luminance) + component represents the black & white portion of the original image, and + the Cb and Cr (chrominance) components represent the color portion of the + original image. Originally, the analog equivalent of this transformation + allowed the same signal to drive both black & white and color televisions, + but JPEG images use YCbCr primarily because it allows the color data to be + optionally subsampled for the purposes of reducing bandwidth or disk + space. YCbCr is the most common JPEG colorspace, and YCbCr JPEG images + can be compressed from and decompressed to any of the extended RGB pixel + formats or grayscale, or they can be decompressed to YUV planar images. +

+

+
See Also:
Constant Field Values
+
+
+ +

+CS_GRAY

+
+public static final int CS_GRAY
+
+
Grayscale colorspace. The JPEG image retains only the luminance data (Y + component), and any color data from the source image is discarded. + Grayscale JPEG images can be compressed from and decompressed to any of + the extended RGB pixel formats or grayscale, or they can be decompressed + to YUV planar images. +

+

+
See Also:
Constant Field Values
+
+
+ +

+CS_CMYK

+
+public static final int CS_CMYK
+
+
CMYK colorspace. When compressing the JPEG image, the C, M, Y, and K + components in the source image are reordered into image planes, but no + colorspace conversion or subsampling is performed. CMYK JPEG images can + only be decompressed to CMYK pixels. +

+

+
See Also:
Constant Field Values
+
+
+ +

+CS_YCCK

+
+public static final int CS_YCCK
+
+
YCCK colorspace. YCCK (AKA "YCbCrK") is not an absolute colorspace but + rather a mathematical transformation of CMYK designed solely for storage + and transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + reversibly transformed into YCCK, and as with YCbCr, the chrominance + components in the YCCK pixels can be subsampled without incurring major + perceptual loss. YCCK JPEG images can only be compressed from and + decompressed to CMYK pixels. +

+

+
See Also:
Constant Field Values
+
+
+

FLAG_BOTTOMUP

diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
index 40511c0..30d5ff3 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
@@ -420,8 +420,8 @@ public void setSourceImage(byte[] srcImage,
 
Associate an uncompressed source image with this compressor instance.

-
Parameters:
srcImage - image buffer containing RGB or grayscale pixels to be - compressed
x - x offset (in pixels) of the region from which the JPEG image +
Parameters:
srcImage - image buffer containing RGB, grayscale, or CMYK pixels to + be compressed
x - x offset (in pixels) of the region from which the JPEG image should be compressed, relative to the start of srcImage.
y - y offset (in pixels) of the region from which the JPEG image should be compressed, relative to the start of srcImage.
width - width (in pixels) of the region in the source image from which the JPEG image should be compressed.
pitch - bytes per line of the source image. Normally, this should be diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html index 4cb2615..d4f6bff 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html @@ -122,7 +122,7 @@ Custom filter callback interface
          A callback function that can be used to modify the DCT coefficients after they are losslessly transformed but before they are transcoded to a new - JPEG file. + JPEG image.   @@ -151,7 +151,7 @@ void customFilter(java.nio.ShortBuffer coeffBuffer,
A callback function that can be used to modify the DCT coefficients after they are losslessly transformed but before they are transcoded to a new - JPEG file. This allows for custom filters or other transformations to be + JPEG image. This allows for custom filters or other transformations to be applied in the frequency domain.

diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html index 6d46ebd..12a5e83 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html @@ -136,6 +136,14 @@ TurboJPEG decompressor protected  int jpegBufSize +
+            + + + +protected  int +jpegColorspace +
            @@ -504,6 +512,16 @@ protected int jpegSubsamp
+
+ +

+jpegColorspace

+
+protected int jpegColorspace
+
+
+
+
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html index b1cc0eb..823fe0f 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html @@ -120,7 +120,7 @@ TurboJPEG lossless transformer Fields inherited from class org.libjpegturbo.turbojpeg.TJDecompressor -handle, jpegBuf, jpegBufSize, jpegHeight, jpegSubsamp, jpegWidth +handle, jpegBuf, jpegBufSize, jpegColorspace, jpegHeight, jpegSubsamp, jpegWidth   diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java index 833ae97..b3ca4b8 100644 --- a/java/org/libjpegturbo/turbojpeg/TJ.java +++ b/java/org/libjpegturbo/turbojpeg/TJ.java @@ -121,7 +121,7 @@ public final class TJ { /** * The number of pixel formats */ - public static final int NUMPF = 11; + public static final int NUMPF = 12; /** * RGB pixel format. The red, green, and blue components in the image are * stored in 3-byte pixels in the order R, G, B from lowest to highest byte @@ -191,6 +191,21 @@ public final class TJ { * interpreted as an opaque alpha channel. */ public static final int PF_ARGB = 10; + /** + * CMYK pixel format. Unlike RGB, which is a display colorspace, + * CMYK (Cyan/Magenta/Yellow/Key) is a print colorspace in which the + * value of each color component corresponds to the amount of cyan, magenta, + * yellow, or black ink that is applied to a white background. In order to + * convert between CMYK and RGB, it is necessary to use a color management + * system (CMS.) A CMS will attempt to map colors within the printer's gamut + * to perceptually similar colors in the display's gamut and vice versa, but + * the mapping is typically not 1:1 or reversible, nor can it be defined with + * a simple formula. Thus, such a conversion is out of scope for a codec + * library. However, the TurboJPEG API allows for compressing CMYK pixels + * into a YCCK JPEG image (see {@link #CS_YCCK}) and decompressing YCCK JPEG + * images into CMYK pixels. + */ + public static final int PF_CMYK = 11; /** @@ -207,7 +222,7 @@ public final class TJ { } private static final int[] pixelSize = { - 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4 + 3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4 }; @@ -229,7 +244,7 @@ public final class TJ { } private static final int[] redOffset = { - 0, 2, 0, 2, 3, 1, 0, 0, 2, 3, 1 + 0, 2, 0, 2, 3, 1, 0, 0, 2, 3, 1, -1 }; @@ -251,7 +266,7 @@ public final class TJ { } private static final int[] greenOffset = { - 1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2 + 1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2, -1 }; @@ -273,10 +288,65 @@ public final class TJ { } private static final int[] blueOffset = { - 2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3 + 2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3, -1 }; + /** + * The number of JPEG colorspaces + */ + public static final int NUMCS = 5; + /** + * RGB colorspace. When compressing the JPEG image, the R, G, and B + * components in the source image are reordered into image planes, but no + * colorspace conversion or subsampling is performed. RGB JPEG images can be + * decompressed to any of the extended RGB pixel formats or grayscale, but + * they cannot be decompressed to YUV images. + */ + public static final int CS_RGB = 0; + /** + * YCbCr colorspace. YCbCr is not an absolute colorspace but rather a + * mathematical transformation of RGB designed solely for storage and + * transmission. YCbCr images must be converted to RGB before they can + * actually be displayed. In the YCbCr colorspace, the Y (luminance) + * component represents the black & white portion of the original image, and + * the Cb and Cr (chrominance) components represent the color portion of the + * original image. Originally, the analog equivalent of this transformation + * allowed the same signal to drive both black & white and color televisions, + * but JPEG images use YCbCr primarily because it allows the color data to be + * optionally subsampled for the purposes of reducing bandwidth or disk + * space. YCbCr is the most common JPEG colorspace, and YCbCr JPEG images + * can be compressed from and decompressed to any of the extended RGB pixel + * formats or grayscale, or they can be decompressed to YUV planar images. + */ + public static final int CS_YCbCr = 1; + /** + * Grayscale colorspace. The JPEG image retains only the luminance data (Y + * component), and any color data from the source image is discarded. + * Grayscale JPEG images can be compressed from and decompressed to any of + * the extended RGB pixel formats or grayscale, or they can be decompressed + * to YUV planar images. + */ + public static final int CS_GRAY = 2; + /** + * CMYK colorspace. When compressing the JPEG image, the C, M, Y, and K + * components in the source image are reordered into image planes, but no + * colorspace conversion or subsampling is performed. CMYK JPEG images can + * only be decompressed to CMYK pixels. + */ + public static final int CS_CMYK = 3; + /** + * YCCK colorspace. YCCK (AKA "YCbCrK") is not an absolute colorspace but + * rather a mathematical transformation of CMYK designed solely for storage + * and transmission. It is to CMYK as YCbCr is to RGB. CMYK pixels can be + * reversibly transformed into YCCK, and as with YCbCr, the chrominance + * components in the YCCK pixels can be subsampled without incurring major + * perceptual loss. YCCK JPEG images can only be compressed from and + * decompressed to CMYK pixels. + */ + public static final int CS_YCCK = 4; + + /** * The uncompressed source/destination image is stored in bottom-up (Windows, * OpenGL) order, not top-down (X11) order. diff --git a/java/org/libjpegturbo/turbojpeg/TJCompressor.java b/java/org/libjpegturbo/turbojpeg/TJCompressor.java index 18fa192..114c4a7 100644 --- a/java/org/libjpegturbo/turbojpeg/TJCompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJCompressor.java @@ -95,8 +95,8 @@ public class TJCompressor { /** * Associate an uncompressed source image with this compressor instance. * - * @param srcImage image buffer containing RGB or grayscale pixels to be - * compressed + * @param srcImage image buffer containing RGB, grayscale, or CMYK pixels to + * be compressed * * @param x x offset (in pixels) of the region from which the JPEG image * should be compressed, relative to the start of srcImage. diff --git a/java/org/libjpegturbo/turbojpeg/TJCustomFilter.java b/java/org/libjpegturbo/turbojpeg/TJCustomFilter.java index 6e46fa1..d862d66 100644 --- a/java/org/libjpegturbo/turbojpeg/TJCustomFilter.java +++ b/java/org/libjpegturbo/turbojpeg/TJCustomFilter.java @@ -39,7 +39,7 @@ public interface TJCustomFilter { /** * A callback function that can be used to modify the DCT coefficients after * they are losslessly transformed but before they are transcoded to a new - * JPEG file. This allows for custom filters or other transformations to be + * JPEG image. This allows for custom filters or other transformations to be * applied in the frequency domain. * * @param coeffBuffer a buffer containing transformed DCT coefficients. diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java index eb8d31c..42c3691 100644 --- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java @@ -687,5 +687,6 @@ public class TJDecompressor { protected int jpegWidth = 0; protected int jpegHeight = 0; protected int jpegSubsamp = -1; + protected int jpegColorspace = -1; private ByteOrder byteOrder = null; }; diff --git a/java/org_libjpegturbo_turbojpeg_TJ.h b/java/org_libjpegturbo_turbojpeg_TJ.h index cec69e4..d590831 100644 --- a/java/org_libjpegturbo_turbojpeg_TJ.h +++ b/java/org_libjpegturbo_turbojpeg_TJ.h @@ -8,7 +8,7 @@ extern "C" { #endif #undef org_libjpegturbo_turbojpeg_TJ_NUMSAMP -#define org_libjpegturbo_turbojpeg_TJ_NUMSAMP 5L +#define org_libjpegturbo_turbojpeg_TJ_NUMSAMP 6L #undef org_libjpegturbo_turbojpeg_TJ_SAMP_444 #define org_libjpegturbo_turbojpeg_TJ_SAMP_444 0L #undef org_libjpegturbo_turbojpeg_TJ_SAMP_422 @@ -19,8 +19,10 @@ extern "C" { #define org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY 3L #undef org_libjpegturbo_turbojpeg_TJ_SAMP_440 #define org_libjpegturbo_turbojpeg_TJ_SAMP_440 4L +#undef org_libjpegturbo_turbojpeg_TJ_SAMP_411 +#define org_libjpegturbo_turbojpeg_TJ_SAMP_411 5L #undef org_libjpegturbo_turbojpeg_TJ_NUMPF -#define org_libjpegturbo_turbojpeg_TJ_NUMPF 11L +#define org_libjpegturbo_turbojpeg_TJ_NUMPF 12L #undef org_libjpegturbo_turbojpeg_TJ_PF_RGB #define org_libjpegturbo_turbojpeg_TJ_PF_RGB 0L #undef org_libjpegturbo_turbojpeg_TJ_PF_BGR @@ -43,6 +45,20 @@ extern "C" { #define org_libjpegturbo_turbojpeg_TJ_PF_ABGR 9L #undef org_libjpegturbo_turbojpeg_TJ_PF_ARGB #define org_libjpegturbo_turbojpeg_TJ_PF_ARGB 10L +#undef org_libjpegturbo_turbojpeg_TJ_PF_CMYK +#define org_libjpegturbo_turbojpeg_TJ_PF_CMYK 11L +#undef org_libjpegturbo_turbojpeg_TJ_NUMCS +#define org_libjpegturbo_turbojpeg_TJ_NUMCS 5L +#undef org_libjpegturbo_turbojpeg_TJ_CS_RGB +#define org_libjpegturbo_turbojpeg_TJ_CS_RGB 0L +#undef org_libjpegturbo_turbojpeg_TJ_CS_YCbCr +#define org_libjpegturbo_turbojpeg_TJ_CS_YCbCr 1L +#undef org_libjpegturbo_turbojpeg_TJ_CS_GRAY +#define org_libjpegturbo_turbojpeg_TJ_CS_GRAY 2L +#undef org_libjpegturbo_turbojpeg_TJ_CS_CMYK +#define org_libjpegturbo_turbojpeg_TJ_CS_CMYK 3L +#undef org_libjpegturbo_turbojpeg_TJ_CS_YCCK +#define org_libjpegturbo_turbojpeg_TJ_CS_YCCK 4L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP #define org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP 2L #undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX diff --git a/tjbench.c b/tjbench.c index 615f2f7..b2ef8d6 100644 --- a/tjbench.c +++ b/tjbench.c @@ -69,13 +69,13 @@ double benchtime=5.0; char *formatName(int subsamp, int cs, char *buf) { - if(cs==TJCS_YCbCr) return subNameLong[subsamp]; + if(cs==TJCS_YCbCr) return (char *)subNameLong[subsamp]; else if(cs==TJCS_YCCK) { snprintf(buf, 80, "%s %s", csName[cs], subNameLong[subsamp]); return buf; } - else return csName[cs]; + else return (char *)csName[cs]; } diff --git a/tjunittest.c b/tjunittest.c index 16ecd09..b738c6c 100644 --- a/tjunittest.c +++ b/tjunittest.c @@ -467,7 +467,7 @@ void _decompTest(tjhandle handle, unsigned char *jpegBuf, if(yuv==YUVENCODE) return; if(yuv==YUVDECODE) - printf("JPEG -> YUV %s ... ", subNameLong[subsamp]); + printf("JPEG -> YUV %s ", subNameLong[subsamp]); else printf("JPEG -> %s %s ", pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-Up":"Top-Down "); diff --git a/turbojpeg-jni.c b/turbojpeg-jni.c index 174558e..09c557b 100644 --- a/turbojpeg-jni.c +++ b/turbojpeg-jni.c @@ -382,7 +382,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress { tjhandle handle=0; unsigned char *jpegBuf=NULL; - int width=0, height=0, jpegSubsamp=-1; + int width=0, height=0, jpegSubsamp=-1, jpegColorspace=-1; gethandle(); @@ -391,8 +391,8 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); - if(tjDecompressHeader2(handle, jpegBuf, (unsigned long)jpegSize, - &width, &height, &jpegSubsamp)==-1) + if(tjDecompressHeader3(handle, jpegBuf, (unsigned long)jpegSize, + &width, &height, &jpegSubsamp, &jpegColorspace)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); _throw(tjGetErrorStr()); @@ -401,6 +401,8 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); (*env)->SetIntField(env, obj, _fid, jpegSubsamp); + bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegColorspace", "I")); + (*env)->SetIntField(env, obj, _fid, jpegColorspace); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); (*env)->SetIntField(env, obj, _fid, width); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); diff --git a/turbojpeg.h b/turbojpeg.h index d098143..065150c 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -225,10 +225,39 @@ enum TJPF }; +/** + * Red offset (in bytes) for a given pixel format. This specifies the number + * of bytes that the red component is offset from the start of the pixel. For + * instance, if a pixel of format TJ_BGRX is stored in char pixel[], + * then the red component will be pixel[tjRedOffset[TJ_BGRX]]. + */ +static const int tjRedOffset[TJ_NUMPF] = {0, 2, 0, 2, 3, 1, 0, 0, 2, 3, 1, -1}; +/** + * Green offset (in bytes) for a given pixel format. This specifies the number + * of bytes that the green component is offset from the start of the pixel. + * For instance, if a pixel of format TJ_BGRX is stored in + * char pixel[], then the green component will be + * pixel[tjGreenOffset[TJ_BGRX]]. + */ +static const int tjGreenOffset[TJ_NUMPF] = {1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2, -1}; +/** + * Blue offset (in bytes) for a given pixel format. This specifies the number + * of bytes that the Blue component is offset from the start of the pixel. For + * instance, if a pixel of format TJ_BGRX is stored in char pixel[], + * then the blue component will be pixel[tjBlueOffset[TJ_BGRX]]. + */ +static const int tjBlueOffset[TJ_NUMPF] = {2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3, -1}; + +/** + * Pixel size (in bytes) for a given pixel format. + */ +static const int tjPixelSize[TJ_NUMPF] = {3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4}; + + /** * The number of JPEG colorspaces */ -#define TJ_NUMCS 12 +#define TJ_NUMCS 5 /** * JPEG colorspaces @@ -287,35 +316,6 @@ enum TJCS }; -/** - * Red offset (in bytes) for a given pixel format. This specifies the number - * of bytes that the red component is offset from the start of the pixel. For - * instance, if a pixel of format TJ_BGRX is stored in char pixel[], - * then the red component will be pixel[tjRedOffset[TJ_BGRX]]. - */ -static const int tjRedOffset[TJ_NUMPF] = {0, 2, 0, 2, 3, 1, 0, 0, 2, 3, 1, -1}; -/** - * Green offset (in bytes) for a given pixel format. This specifies the number - * of bytes that the green component is offset from the start of the pixel. - * For instance, if a pixel of format TJ_BGRX is stored in - * char pixel[], then the green component will be - * pixel[tjGreenOffset[TJ_BGRX]]. - */ -static const int tjGreenOffset[TJ_NUMPF] = {1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2, -1}; -/** - * Blue offset (in bytes) for a given pixel format. This specifies the number - * of bytes that the Blue component is offset from the start of the pixel. For - * instance, if a pixel of format TJ_BGRX is stored in char pixel[], - * then the blue component will be pixel[tjBlueOffset[TJ_BGRX]]. - */ -static const int tjBlueOffset[TJ_NUMPF] = {2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3, -1}; - -/** - * Pixel size (in bytes) for a given pixel format. - */ -static const int tjPixelSize[TJ_NUMPF] = {3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4}; - - /** * The uncompressed source/destination image is stored in bottom-up (Windows, * OpenGL) order, not top-down (X11) order. -- 2.40.0