272 Commits

Author SHA1 Message Date
DRC
3cea8ccd51 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
2025-12-09 18:24:36 -05:00
DRC
fc4b417a90 TJCompressor.loadSourceImage: Unset unused buffers
If loading a 2-to-8-bit image, unset srcBuf12 and srcBuf16.  If loading
a 9-to-12-bit image, unset srcBuf8 and srcBuf16.  If loading a
13-to-16-bit image, unset srcBuf8 and srcBuf12.  Otherwise,
TJCompressor.getSourceBuf() will return srcBuf8 or srcBuf12, in order,
if any previous invocation of TJCompressor.loadSourceImage() set them,
irrespective of the buffer that was set by the most recent invocation.

This probably helps with garbage collection as well, since it signals to
the GC that the unused buffers are really unused.
2025-12-09 18:21:21 -05:00
DRC
fc324109d5 JNI: Guard against int overflow w/ huge X, Y vals
This is not a security vulnerability, since applications that pass such
values to the Java API would fail regardless, and such a bug would never
make it into the wild.  By contrast, a security vulnerability arises
from applications that work correctly with most input data sets but
trigger a library failure, such as a buffer overrun, with one or more
specific input data sets.  As with most imaging APIs, the libjpeg-turbo
APIs rely upon the calling application to pass appropriately-sized
buffers and appropriate size/dimension arguments.  The failure to do so
is no more the fault of libjpeg-turbo than calling
'buf = malloc(1); buf[2] = 0;' is the fault of the C library.

Buffer size checking is a bonus feature of the Java API that isn't (and
can't be) provided by the C API, so this commit merely hardens the bonus
feature against API abuse, in keeping with the Java paradigm of throwing
an exception rather than crashing due to a caller-imposed buffer
overrun.
2025-12-03 14:52:03 -05:00
DRC
466c344878 TurboJPEG doc tweaks
- Clarify that YUV encoding performs downsampling as well as color
  conversion.

- Clarify that TJPARAM_LOSSLESS is ignored by tj3CompressFromYUV*8().

- Clarify that tj3CompressFromYUV*8() generates only YCbCr or grayscale
  JPEG images, i.e. that TJPARAM_COLORSPACE has no effect.
2025-10-23 10:42:23 -04:00
DRC
f74989d8c7 Clean up #include directives
This is subtle, but #include <header.h> searches directories specified
with -I, then system include directories.  #include "header.h" searches
the current source directory, then directories specified with -I, then
system include directories.

Using bracketed #include directives for jpeglib.h, jinclude.h, jerror.h,
cdjpeg.h, and turbojpeg.h only worked because the build system
explicitly passed -I{source_directory}/src/ to the compiler.  Referring
to 51cee03629, it's better for the source
code to have as few dependencies on our specific build system as
possible.

Since jpeglib.h, jinclude.h, jerror.h, and turbojpeg.h can be installed
in system include directories, it's also better for internal references
to those headers to resolve internally first, to avoid potential
conflicts between the system-installed version of libjpeg-turbo and the
version being built.  (Such conflicts would never have occurred with our
build system, but they might have occurred due to misintegration with a
downstream build system.)
2025-09-25 12:24:31 -04:00
DRC
c889b1da56 TJBench: Require additional argument with -copy
(oversight from e4c67aff50)
2025-06-12 10:08:21 -04:00
DRC
d7932a2709 TJ doc: Density params require YCbCr or grayscale
Since libjpeg-turbo does not support Exif, the only way it can embed
density information in a JPEG image is by using the JFIF marker, which
is only written if the JPEG colorspace is YCbCr or grayscale.
(Referring to the conversation under #793, we may need to further
restrict that to 8-bit-per-sample JPEG images, because the JFIF spec
requires 8-bit data precision.)
2024-10-30 12:21:50 -04:00
DRC
1b1356a565 TJComp: Explicitly specify data precision
This is just a code readability thing.  The logic effectively caused the
data precision to default to 8 if -precision was not specified, but that
was not obvious.

This commit also modifies tjcomptest so that it tests TJComp with no
-precision argument, to ensure that the data precision defaults to 8.
2024-09-23 15:24:48 -04:00
DRC
0d58f09997 TJTran: ICC profiles are now supported 2024-09-14 13:23:36 -04:00
DRC
6d02718d9a JNI: Guard against int. overflow w/ ICC profiles 2024-09-14 13:23:36 -04:00
DRC
9b01f5a057 TJ: Add func/method for computing xformed buf size 2024-09-14 13:23:32 -04:00
DRC
6f1fe2d113 turbojpeg-jni.c: Fix int. conv. warnings w/ VC++ 2024-09-09 10:54:16 -04:00
DRC
a272858212 TurboJPEG: ICC profile support 2024-09-06 19:55:41 -04:00
DRC
c519d7b679 Don't ignore JPEG buf size with TJPARAM_NOREALLOC
Since the introduction of TJFLAG_NOREALLOC in libjpeg-turbo 1.2.x, the
TurboJPEG C API documentation has (confusingly) stated that:

- if the JPEG buffer pointer points to a pre-allocated buffer, then the
JPEG buffer size must be specified, and

- the JPEG buffer size should be specified if the JPEG buffer is
pre-allocated to an arbitrary size.

The documentation never explicitly stated that the JPEG buffer size
should be specified if the JPEG buffer is pre-allocated to a worst-case
size, but since focus does not imply exclusion, it also never explicitly
stated the reverse.  Furthermore, the documentation never stated that
this was contingent upon TJPARAM_NOREALLOC/TJFLAG_NOREALLOC.  However,
effectively the compression and lossless transformation functions
ignored the JPEG buffer size(s) passed to them, and assumed that the
JPEG buffer(s) had been allocated to a worst-case size, if
TJPARAM_NOREALLOC/TJFLAG_NOREALLOC was set.  This behavior was an
accidental and undocumented throwback to libjpeg-turbo 1.1.x, in which
the tjCompress() function provided no way to specify the JPEG buffer
size.  It was always a bad idea for applications to rely upon that
behavior (although our own TJBench application unfortunately did.)
However, if such applications exist in the wild, the new behavior would
constitute a breaking change, so it has been introduced only into
libjpeg-turbo 3.1.x and only into TurboJPEG 3 API functions.  The
previous behavior has been retained when calling functions from the
TurboJPEG 2.1.x API and prior versions.

Did I mention that APIs are hard?
2024-09-06 19:55:27 -04:00
DRC
5f05c75ac1 Merge branch 'main' into dev 2024-09-06 19:55:20 -04:00
DRC
b3f0abe377 TJ: Calc. xformed buf sizes based on dst. subsamp
With respect to tj3Transform(), this addresses an oversight from
bb1d540a80.

Note to self: A convenience function/method for computing the worst-case
transformed JPEG size for a particular transform would be nice.
2024-09-06 19:04:28 -04:00
DRC
6d9591703f Minor TurboJPEG doc tweaks
- When transforming, the worst-case JPEG buffer size depends on the
  subsampling level used in the destination image, since a grayscale
  transform might have been applied.

- Parentheses Police
2024-09-05 22:31:40 -04:00
DRC
8db41dad22 Merge branch 'main' into dev 2024-09-05 15:15:08 -04:00
DRC
758e8a8e9f Java: Use Java-style method nomenclature
:: is a C++ thing.
2024-09-05 14:57:15 -04:00
DRC
e4c67aff50 TJBench: More argument consistification
-copynone --> -copy none

Add '-copy all', even though it's the default.

-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb, -gray, -cmyk -->
-pixelformat {rgb|bgr|rgbx|bgrx|xbgr|xrgb|gray|cmyk}
(This is mainly so -gray won't interfere with -grayscale.)

Fix an ArrayIndexOutOfBoundsException that occurred when passing -dct
to the Java version without specifying the DCT algorithm (oversight from
24fbf64d31a0758c63bcc27cf5d92fc5611717d0.)
2024-09-04 12:41:15 -04:00
DRC
d43ed7a1ff Merge branch 'main' into dev 2024-09-04 08:38:13 -04:00
DRC
5550c80fdc Doc: "compress operation"="compression operation"
(consistification)
2024-09-03 17:20:10 -04:00
DRC
37851a32c0 TurboJPEG: Add restart markers when transforming 2024-09-03 09:26:33 -04:00
DRC
debf57bc1d TJBench: Improve usage screen readability 2024-09-01 14:05:37 -04:00
DRC
fad6100704 Replace TJExample with IJG workalike programs 2024-09-01 14:05:15 -04:00
DRC
6d9f1f816c Merge branch 'main' into dev 2024-09-01 14:04:20 -04:00
DRC
797c6ccd98 Doc: Further clarify MCU definition 2024-09-01 11:25:29 -04:00
DRC
3e303e7235 TJBench: Allow British spellings in arguments 2024-08-31 18:42:19 -04:00
DRC
645673810f Merge branch 'main' into dev 2024-08-31 17:41:03 -04:00
DRC
8d76e4e550 Doc: "EXIF" = "Exif" 2024-08-31 15:33:55 -04:00
DRC
9983840eb6 TJ/xform: Check crop region against dest. image
Lossless cropping is performed after other lossless transform
operations, so the cropping region must be specified relative to the
destination image dimensions and level of chrominance subsampling, not
the source image dimensions and level of chrominance subsampling.

More specifically, if the lossless transform operation swaps the X and Y
axes, or if the image is converted to grayscale, then that changes the
cropping region requirements.
2024-08-31 15:04:30 -04:00
DRC
8456d2b98c Doc: "MCU block" = "iMCU" or "MCU"
The JPEG-1 spec never uses the term "MCU block".  That term is rarely
used in other literature to describe the equivalent of an MCU in an
interleaved JPEG image, but the libjpeg documentation uses "iMCU" to
describe the same thing.  "iMCU" is a better term, since the equivalent
of an interleaved MCU can contain multiple DCT blocks (or samples in
lossless mode) that are only grouped together if the image is
interleaved.

In the case of restart markers, "MCU block" was used in the libjpeg
documentation instead of "MCU", but "MCU" is more accurate and less
confusing.  (The restart interval is literally in MCUs, where one MCU
is one data unit in a non-interleaved JPEG image and multiple data units
in a multi-component interleaved JPEG image.)

In the case of 9b704f96b2, the issue was
actually with progressive JPEG images exactly two DCT blocks wide, not
two MCU blocks wide.

This commit also defines "MCU" and "MCU row" in the description of the
various restart marker options/parameters.  Although an MCU row is
technically always a row of samples in lossless mode, "sample row" was
confusing, since it is used in other places to describe a row of samples
for a single component (whereas an MCU row in a typical lossless JPEG
image consists of a row of interleaved samples for all components.)
2024-08-30 14:16:09 -04:00
DRC
2858783db5 JNI: Set srcX, srcY = 0 in loadSourceImage()
(oversight from 79b8d65f0f)
2024-08-28 18:58:27 -04:00
DRC
4ceaf8b700 TJBench: Allow 'X' in crop spec
(for consistency with djpeg and jpegtran)
2024-08-28 18:58:27 -04:00
DRC
fd9b21b69b Merge branch 'main' into dev 2024-08-28 18:58:21 -04:00
DRC
5cf7960678 Undocument TJ*PARAM_RESTARTBLOCKS for lossless
TJ*PARAM_RESTARTBLOCKS technically works with lossless compression, but
it is not useful, since the value must be equal to the number of samples
in a row.  (In other words, it is no different than
TJ*PARAM_RESTARTINROWS, except that it requires the user to do more
math.)
2024-08-28 18:36:37 -04:00
DRC
d62079717c TJBench: Don't override subsamp until args parsed
Otherwise, passing -subsamp after -lossless might cause the worst-case
JPEG buffer size to be too small.
2024-08-28 18:21:55 -04:00
DRC
6a9565ce6e Merge branch 'main' into dev 2024-08-26 16:45:41 -04:00
DRC
548f732432 TJBench: Usage screen tweak
Indicate that -maxmemory and -maxpixels take an integer argument.
2024-08-26 10:14:11 -04:00
DRC
de4bbac55e TJCompressor.compress(): Fix lossls buf size calc 2024-08-23 12:48:34 -04:00
DRC
acbb493759 JNI: Fix Windows CI build failure
(introduced by previous commit)

jint and int are technically the same thing, but certain compilers are a
bit pedantic.
2024-08-22 18:32:30 -04:00
DRC
79b8d65f0f Java: Add official packed-pixel image I/O methods 2024-08-22 18:19:09 -04:00
DRC
8088dfc08c TJUnitTest.java: Use boolean ret vals for check*() 2024-08-22 18:16:15 -04:00
DRC
b577504f1d JNI: Remove deprecated constants
(oversight from 0737844235)
2024-08-22 17:14:45 -04:00
DRC
a98bc9a54f Merge branch 'main' into dev 2024-08-22 17:14:37 -04:00
DRC
d44fc54f94 Java: Unset srcBuf12/16 with BufferedImage/YUV src
Due to an oversight in the multi-precision feature,
TJCompressor.srcBuf12 and TJCompressor.srcBuf16 were not set to null
in TJCompressor.setSourceImage(YUVImage) or
TJCompressor.setSourceImage(BufferedImage, ...).  Thus, if an
application set a 12-bit or 16-bit packed-pixel buffer as the source
image then set a BufferedImage with integer pixels as the source image,
TJCompress.compress() would compress from the 12-bit or 16-bit
packed-pixel buffer instead of the BufferedImage.  The odds of an
application actually doing that are very slim, however.
2024-08-21 16:44:46 -04:00
DRC
ecf7c8b168 Merge branch 'main' into dev 2024-08-21 13:09:53 -04:00
DRC
24fbf64d31 TJBench: Consistify args with djpeg
-fastdct --> -dct fast
-fastupsample --> -nosmooth
2024-08-21 13:07:46 -04:00
DRC
d6ce7df352 TJBench: Consistify args with cjpeg/djpeg/jpegtran
-hflip --> -flip horizontal
-limitscans --> -maxscans N
-rot90 --> -rotate 90
-rot180 --> -rotate 180
-rot270 --> -rotate 270
-stoponwarning --> -strict
-vflip --> -flip vertical
2024-08-21 13:07:46 -04:00
DRC
ab203704dd TJBench: Allow abbreviated command-line options
... using the same matching algorithm as cjpeg/djpeg/jpegtran and, where
possible, the same abbreviations:

-a for -arithmetic
-b for -bmp
-cr for -crop
-g for -grayscale
-l for -lossless
-max for -maxmemory
-o for -optimize
-pre for -precision
-p for -progressive
-r for -restart
-s for -scale
-t for -transpose
-transv for -transverse
2024-08-21 13:07:46 -04:00