mirror of
https://github.com/libjpeg-turbo/libjpeg-turbo
synced 2025-03-28 21:13:18 +00:00
Replace TJExample with IJG workalike programs
This commit is contained in:
parent
6d9f1f816c
commit
fad6100704
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -2,4 +2,5 @@
|
||||
/.gitattributes export-ignore
|
||||
/.github export-ignore
|
||||
*.ppm binary
|
||||
*.pgm binary
|
||||
/ChangeLog.md conflict-marker-size=8
|
||||
|
@ -736,8 +736,14 @@ if(WITH_TURBOJPEG)
|
||||
target_link_libraries(tjbench m)
|
||||
endif()
|
||||
|
||||
add_executable(tjexample src/tjexample.c)
|
||||
target_link_libraries(tjexample turbojpeg)
|
||||
add_executable(tjcomp src/tjcomp.c)
|
||||
target_link_libraries(tjcomp turbojpeg)
|
||||
|
||||
add_executable(tjdecomp src/tjdecomp.c)
|
||||
target_link_libraries(tjdecomp turbojpeg)
|
||||
|
||||
add_executable(tjtran src/tjtran.c)
|
||||
target_link_libraries(tjtran turbojpeg)
|
||||
|
||||
add_custom_target(tjdoc COMMAND doxygen -s ../doc/doxygen.config
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src)
|
||||
@ -1881,20 +1887,20 @@ add_custom_target(croptest
|
||||
|
||||
if(WITH_TURBOJPEG)
|
||||
configure_file(test/tjbenchtest.in test/tjbenchtest @ONLY)
|
||||
configure_file(test/tjexampletest.in test/tjexampletest @ONLY)
|
||||
configure_file(test/tjcomptest.in test/tjcomptest @ONLY)
|
||||
configure_file(test/tjdecomptest.in test/tjdecomptest @ONLY)
|
||||
configure_file(test/tjtrantest.in test/tjtrantest @ONLY)
|
||||
if(WIN32)
|
||||
set(BASH bash)
|
||||
endif()
|
||||
add_custom_target(tjtest COMMAND ${CMAKE_COMMAND} -DWITH_JAVA=${WITH_JAVA}
|
||||
-DPRECISION=8 -P ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjexampletest)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest)
|
||||
add_custom_target(tjtest12 COMMAND ${CMAKE_COMMAND} -DWITH_JAVA=${WITH_JAVA}
|
||||
-DPRECISION=12 -P ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjexampletest)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest)
|
||||
add_custom_target(tjtest16 COMMAND ${CMAKE_COMMAND} -DWITH_JAVA=${WITH_JAVA}
|
||||
-DPRECISION=2 -P ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DWITH_JAVA=${WITH_JAVA}
|
||||
@ -1922,8 +1928,14 @@ if(WITH_TURBOJPEG)
|
||||
COMMAND ${CMAKE_COMMAND} -DWITH_JAVA=${WITH_JAVA}
|
||||
-DPRECISION=16 -P ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/cmakescripts/tjbenchtest.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjexampletest)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjbenchtest)
|
||||
add_custom_target(tjexampletest COMMAND ${CMAKE_COMMAND}
|
||||
-DWITH_JAVA=${WITH_JAVA}
|
||||
-P ${CMAKE_SOURCE_DIR}/cmakescripts/tjexampletest.cmake
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/cmakescripts/tjexampletest.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjcomptest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjdecomptest
|
||||
${CMAKE_CURRENT_BINARY_DIR}/test/tjtrantest)
|
||||
endif()
|
||||
|
||||
|
||||
@ -1991,7 +2003,9 @@ install(TARGETS rdjpgcom wrjpgcom
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.ijg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/README.md
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/example.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tjexample.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tjcomp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tjdecomp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/tjtran.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/doc/libjpeg.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/doc/structure.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/doc/usage.txt
|
||||
@ -1999,7 +2013,9 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.ijg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
COMPONENT doc)
|
||||
if(WITH_JAVA)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/java/TJExample.java
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/java/TJComp.java
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/java/TJDeomp.java
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/java/TJTran.java
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT doc)
|
||||
endif()
|
||||
|
||||
|
@ -61,6 +61,10 @@ djpeg, and jpegtran.)
|
||||
work similarly to the `tj3LoadImage*()` and `tj3SaveImage*()` functions in the
|
||||
C API.
|
||||
|
||||
8. TJExample has been replaced with three programs (TJComp, TJDecomp, and
|
||||
TJTran) that demonstrate how to approximate the functionality of cjpeg, djpeg,
|
||||
and jpegtran using the TurboJPEG C and Java APIs.
|
||||
|
||||
|
||||
3.0.4
|
||||
=====
|
||||
|
@ -69,8 +69,10 @@ JPEG images:
|
||||
generating planar YUV images and performing multiple simultaneous lossless
|
||||
transforms on an image. The Java interface for libjpeg-turbo is written on
|
||||
top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
|
||||
users of libjpeg-turbo. Refer to [tjexample.c](src/tjexample.c) and
|
||||
[TJExample.java](java/TJExample.java) for examples of its usage and to
|
||||
users of libjpeg-turbo. Refer to [tjcomp.c](src/tjcomp.c),
|
||||
[tjdecomp.c](src/tjdecomp.c), [tjtran.c](src/tjtran.c),
|
||||
[TJComp.java](java/TJComp.java), [TJDecomp.java](java/TJDecomp.java), and
|
||||
[TJTran.java](java/TJTran.java) for examples of its usage and to
|
||||
<https://libjpeg-turbo.org/Documentation/Documentation> for API
|
||||
documentation.
|
||||
|
||||
|
@ -40,7 +40,9 @@ file(GLOB FILES
|
||||
*_LOSSL*S_*.jpg
|
||||
croptest.log
|
||||
tjbenchtest*.log
|
||||
tjexampletest*.log)
|
||||
tjcomptest*.log
|
||||
tjdecomptest*.log
|
||||
tjtrantest*.log)
|
||||
|
||||
if(NOT FILES STREQUAL "")
|
||||
message(STATUS "Removing test files")
|
||||
|
@ -45,9 +45,6 @@ if(PRECISION EQUAL 8)
|
||||
endif()
|
||||
run_test(tjbenchtest "-precision;${PRECISION};-lossless")
|
||||
run_test(tjbenchtest "-precision;${PRECISION};-lossless;-alloc")
|
||||
if(PRECISION EQUAL 8)
|
||||
run_test(tjexampletest "")
|
||||
endif()
|
||||
if(WITH_JAVA)
|
||||
if(PRECISION EQUAL 8 OR PRECISION EQUAL 12)
|
||||
run_test(tjbenchtest "-java;-precision;${PRECISION}")
|
||||
@ -71,7 +68,4 @@ if(WITH_JAVA)
|
||||
run_test(tjbenchtest "-java;-precision;${PRECISION};-arithmetic;-yuv")
|
||||
endif()
|
||||
run_test(tjbenchtest "-java;-precision;${PRECISION};-lossless")
|
||||
if(PRECISION EQUAL 8)
|
||||
run_test(tjexampletest "-java")
|
||||
endif()
|
||||
endif()
|
||||
|
26
cmakescripts/tjexampletest.cmake
Normal file
26
cmakescripts/tjexampletest.cmake
Normal file
@ -0,0 +1,26 @@
|
||||
if(NOT DEFINED WITH_JAVA)
|
||||
message(FATAL_ERROR "WITH_JAVA must be specified")
|
||||
endif()
|
||||
|
||||
macro(check_error program)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "${program} failed.")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(run_test PROG ARGS)
|
||||
string(REPLACE ";" " " SPACED_ARGS "${ARGS}")
|
||||
message(STATUS "${PROG} ${SPACED_ARGS}")
|
||||
execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test/${PROG} ${ARGS}
|
||||
RESULT_VARIABLE RESULT)
|
||||
check_error("${PROG} ${SPACED_ARGS}")
|
||||
endmacro()
|
||||
|
||||
run_test(tjcomptest "")
|
||||
run_test(tjdecomptest "")
|
||||
run_test(tjtrantest "")
|
||||
if(WITH_JAVA)
|
||||
run_test(tjcomptest "-java")
|
||||
run_test(tjdecomptest "-java")
|
||||
run_test(tjtrantest "-java")
|
||||
endif()
|
@ -25,7 +25,9 @@ set(JAVA_SOURCES org/libjpegturbo/turbojpeg/TJ.java
|
||||
org/libjpegturbo/turbojpeg/TJTransformer.java
|
||||
org/libjpegturbo/turbojpeg/YUVImage.java
|
||||
TJUnitTest.java
|
||||
TJExample.java
|
||||
TJComp.java
|
||||
TJDecomp.java
|
||||
TJTran.java
|
||||
TJBench.java)
|
||||
|
||||
set(TURBOJPEG_DLL_NAME "turbojpeg")
|
||||
@ -50,7 +52,7 @@ if(MSYS)
|
||||
set(CMAKE_HOST_SYSTEM_NAME "MSYS")
|
||||
endif()
|
||||
add_jar(turbojpeg-java ${JAVA_SOURCES} OUTPUT_NAME turbojpeg
|
||||
ENTRY_POINT TJExample)
|
||||
ENTRY_POINT TJBench)
|
||||
if(MSYS)
|
||||
set(CMAKE_HOST_SYSTEM_NAME ${CMAKE_HOST_SYSTEM_NAME_BAK})
|
||||
endif()
|
||||
|
@ -1,2 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: TJExample
|
||||
Main-Class: TJBench
|
||||
|
@ -10,9 +10,9 @@ directly into both open source and proprietary projects without restriction. A
|
||||
Java archive (JAR) file containing these classes is also shipped with the
|
||||
"official" distribution packages of libjpeg-turbo.
|
||||
|
||||
TJExample.java, which should also be located in the same directory as this
|
||||
README file, demonstrates how to use the TurboJPEG Java API to compress and
|
||||
decompress JPEG images in memory.
|
||||
TJComp.java, TJDecomp.java, and TJTran.java, which should be located in the
|
||||
same directory as this README file, demonstrate how to use the TurboJPEG Java
|
||||
API to compress, decompress, and transform JPEG images in memory.
|
||||
|
||||
|
||||
Performance Pitfalls
|
||||
|
299
java/TJComp.java
Normal file
299
java/TJComp.java
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017-2018, 2022-2024 D. R. Commander.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG Java API to approximate
|
||||
* the functionality of the IJG's cjpeg program. cjpeg features that are not
|
||||
* covered:
|
||||
*
|
||||
* - GIF and Targa input file formats [legacy feature]
|
||||
* - Separate quality settings for luminance and chrominance
|
||||
* - The floating-point DCT method [legacy feature]
|
||||
* - Embedding an ICC color management profile
|
||||
* - Input image smoothing
|
||||
* - Progress reporting
|
||||
* - Debug output
|
||||
* - Forcing baseline-compatible quantization tables
|
||||
* - Specifying arbitrary quantization tables
|
||||
* - Specifying arbitrary sampling factors
|
||||
* - Scan scripts
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.libjpegturbo.turbojpeg.*;
|
||||
|
||||
|
||||
@SuppressWarnings("checkstyle:JavadocType")
|
||||
final class TJComp {
|
||||
|
||||
private TJComp() {}
|
||||
|
||||
static final String CLASS_NAME =
|
||||
new TJComp().getClass().getName();
|
||||
|
||||
static final int DEFAULT_SUBSAMP = TJ.SAMP_420;
|
||||
static final int DEFAULT_QUALITY = 75;
|
||||
|
||||
|
||||
static final String[] SUBSAMP_NAME = {
|
||||
"444", "422", "420", "GRAY", "440", "411", "441"
|
||||
};
|
||||
|
||||
|
||||
static void usage() {
|
||||
System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
|
||||
" [options] <Input image> <JPEG image>\n");
|
||||
|
||||
System.out.println("The input image can be in Windows BMP or PBMPLUS (PPM/PGM) format.\n");
|
||||
|
||||
System.out.println("GENERAL OPTIONS (CAN BE ABBREVIATED)");
|
||||
System.out.println("------------------------------------");
|
||||
System.out.println("-lossless PSV[,Pt]");
|
||||
System.out.println(" Create a lossless JPEG image (implies -subsamp 444) using predictor");
|
||||
System.out.println(" selection value PSV (1-7) and optional point transform Pt (0 through");
|
||||
System.out.println(" {data precision} - 1)");
|
||||
System.out.println("-maxmemory N");
|
||||
System.out.println(" Memory limit (in megabytes) for intermediate buffers used with progressive");
|
||||
System.out.println(" JPEG compression, lossless JPEG compression, and Huffman table optimization");
|
||||
System.out.println(" [default = no limit]");
|
||||
System.out.println("-precision N");
|
||||
System.out.println(" Create a JPEG image with N-bit data precision [N = 2..16; default = 8; if N");
|
||||
System.out.println(" is not 8 or 12, then -lossless must also be specified] (-precision 12");
|
||||
System.out.println(" implies -optimize unless -arithmetic is also specified)");
|
||||
System.out.println("-restart N");
|
||||
System.out.println(" Add a restart marker every N MCU rows [default = 0 (no restart markers)].");
|
||||
System.out.println(" Append 'B' to specify the restart marker interval in MCUs (lossy only.)\n");
|
||||
|
||||
System.out.println("LOSSY JPEG OPTIONS (CAN BE ABBREVIATED)");
|
||||
System.out.println("---------------------------------------");
|
||||
System.out.println("-arithmetic");
|
||||
System.out.println(" Use arithmetic entropy coding instead of Huffman entropy coding (can be");
|
||||
System.out.println(" combined with -progressive)");
|
||||
System.out.println("-dct fast");
|
||||
System.out.println(" Use less accurate DCT algorithm [legacy feature]");
|
||||
System.out.println("-dct int");
|
||||
System.out.println(" Use more accurate DCT algorithm [default]");
|
||||
System.out.println("-grayscale");
|
||||
System.out.println(" Create a grayscale JPEG image from a full-color input image");
|
||||
System.out.println("-optimize");
|
||||
System.out.println(" Use Huffman table optimization");
|
||||
System.out.println("-progressive");
|
||||
System.out.println(" Create a progressive JPEG image instead of a single-scan JPEG image (can be");
|
||||
System.out.println(" combined with -arithmetic; implies -optimize unless -arithmetic is also");
|
||||
System.out.println(" specified)");
|
||||
System.out.println("-quality {1..100}");
|
||||
System.out.format(" Create a JPEG image with the specified quality level [default = %d]\n",
|
||||
DEFAULT_QUALITY);
|
||||
System.out.println("-rgb");
|
||||
System.out.println(" Create a JPEG image that uses the RGB colorspace instead of the YCbCr");
|
||||
System.out.println(" colorspace");
|
||||
System.out.println("-subsamp {444|422|440|420|411|441}");
|
||||
System.out.println(" Create a JPEG image that uses the specified chrominance subsampling level");
|
||||
System.out.format(" [default = %s]\n\n", SUBSAMP_NAME[DEFAULT_SUBSAMP]);
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
static boolean matchArg(String arg, String string, int minChars) {
|
||||
if (arg.length() > string.length() || arg.length() < minChars)
|
||||
return false;
|
||||
|
||||
int cmpChars = Math.max(arg.length(), minChars);
|
||||
string = string.substring(0, cmpChars);
|
||||
|
||||
return arg.equalsIgnoreCase(string);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] argv) {
|
||||
int exitStatus = 0;
|
||||
TJCompressor tjc = null;
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
int i;
|
||||
int arithmetic = -1, colorspace = -1, fastDCT = -1, losslessPSV = -1,
|
||||
losslessPt = -1, maxMemory = -1, optimize = -1,
|
||||
pixelFormat = TJ.PF_UNKNOWN, precision = -1, progressive = -1,
|
||||
quality = DEFAULT_QUALITY, restartIntervalBlocks = -1,
|
||||
restartIntervalRows = -1, subsamp = DEFAULT_SUBSAMP;
|
||||
byte[] jpegBuf;
|
||||
|
||||
for (i = 0; i < argv.length; i++) {
|
||||
if (matchArg(argv[i], "-arithmetic", 2))
|
||||
arithmetic = 1;
|
||||
else if (matchArg(argv[i], "-dct", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "fast", 1))
|
||||
fastDCT = 1;
|
||||
else if (!matchArg(argv[i], "int", 1))
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-grayscale", 2) ||
|
||||
matchArg(argv[i], "-greyscale", 2))
|
||||
colorspace = TJ.CS_GRAY;
|
||||
else if (matchArg(argv[i], "-lossless", 2) && i < argv.length - 1) {
|
||||
Scanner scanner = new Scanner(argv[++i]).useDelimiter(",");
|
||||
|
||||
try {
|
||||
if (scanner.hasNextInt())
|
||||
losslessPSV = scanner.nextInt();
|
||||
if (scanner.hasNextInt())
|
||||
losslessPt = scanner.nextInt();
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (losslessPSV < 1 || losslessPSV > 7)
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-maxmemory", 2) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 0)
|
||||
usage();
|
||||
maxMemory = temp;
|
||||
} else if (matchArg(argv[i], "-optimize", 2) ||
|
||||
matchArg(argv[i], "-optimise", 2))
|
||||
optimize = 1;
|
||||
else if (matchArg(argv[i], "-precision", 4) && i < argv.length - 1) {
|
||||
int temp = 0;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 2 || temp > 16)
|
||||
usage();
|
||||
precision = temp;
|
||||
} else if (matchArg(argv[i], "-progressive", 2))
|
||||
progressive = 1;
|
||||
else if (matchArg(argv[i], "-quality", 2) && i < argv.length - 1) {
|
||||
int temp = 0;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 1 || temp > 100)
|
||||
usage();
|
||||
quality = temp;
|
||||
} else if (matchArg(argv[i], "-rgb", 3))
|
||||
colorspace = TJ.CS_RGB;
|
||||
else if (matchArg(argv[i], "-restart", 2) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
String arg = argv[++i];
|
||||
Scanner scanner = new Scanner(arg).useDelimiter("b|B");
|
||||
|
||||
try {
|
||||
temp = scanner.nextInt();
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (temp < 0 || temp > 65535 || scanner.hasNext())
|
||||
usage();
|
||||
if (arg.endsWith("B") || arg.endsWith("b"))
|
||||
restartIntervalBlocks = temp;
|
||||
else
|
||||
restartIntervalRows = temp;
|
||||
} else if (matchArg(argv[i], "-subsamp", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "444", 3))
|
||||
subsamp = TJ.SAMP_444;
|
||||
else if (matchArg(argv[i], "422", 3))
|
||||
subsamp = TJ.SAMP_422;
|
||||
else if (matchArg(argv[i], "440", 3))
|
||||
subsamp = TJ.SAMP_440;
|
||||
else if (matchArg(argv[i], "420", 3))
|
||||
subsamp = TJ.SAMP_420;
|
||||
else if (matchArg(argv[i], "411", 3))
|
||||
subsamp = TJ.SAMP_411;
|
||||
else if (matchArg(argv[i], "441", 3))
|
||||
subsamp = TJ.SAMP_441;
|
||||
else
|
||||
usage();
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (i != argv.length - 2)
|
||||
usage();
|
||||
if (losslessPSV == -1 && precision != -1 && precision != 8 &&
|
||||
precision != 12)
|
||||
usage();
|
||||
|
||||
tjc = new TJCompressor();
|
||||
|
||||
tjc.set(TJ.PARAM_QUALITY, quality);
|
||||
tjc.set(TJ.PARAM_SUBSAMP, subsamp);
|
||||
if (precision >= 0)
|
||||
tjc.set(TJ.PARAM_PRECISION, precision);
|
||||
if (fastDCT >= 0)
|
||||
tjc.set(TJ.PARAM_FASTDCT, fastDCT);
|
||||
if (optimize >= 0)
|
||||
tjc.set(TJ.PARAM_OPTIMIZE, optimize);
|
||||
if (progressive >= 0)
|
||||
tjc.set(TJ.PARAM_PROGRESSIVE, progressive);
|
||||
if (arithmetic >= 0)
|
||||
tjc.set(TJ.PARAM_ARITHMETIC, arithmetic);
|
||||
if (losslessPSV >= 1 && losslessPSV <= 7) {
|
||||
tjc.set(TJ.PARAM_LOSSLESS, 1);
|
||||
tjc.set(TJ.PARAM_LOSSLESSPSV, losslessPSV);
|
||||
if (losslessPt >= 0)
|
||||
tjc.set(TJ.PARAM_LOSSLESSPT, losslessPt);
|
||||
}
|
||||
if (restartIntervalBlocks >= 0)
|
||||
tjc.set(TJ.PARAM_RESTARTBLOCKS, restartIntervalBlocks);
|
||||
if (restartIntervalRows >= 0)
|
||||
tjc.set(TJ.PARAM_RESTARTROWS, restartIntervalRows);
|
||||
if (maxMemory >= 0)
|
||||
tjc.set(TJ.PARAM_MAXMEMORY, maxMemory);
|
||||
|
||||
tjc.loadSourceImage(argv[i], 1, pixelFormat);
|
||||
pixelFormat = tjc.getPixelFormat();
|
||||
|
||||
if (pixelFormat == TJ.PF_GRAY && colorspace < 0)
|
||||
colorspace = TJ.CS_GRAY;
|
||||
if (colorspace >= 0)
|
||||
tjc.set(TJ.PARAM_COLORSPACE, colorspace);
|
||||
|
||||
jpegBuf = tjc.compress();
|
||||
|
||||
File outFile = new File(argv[++i]);
|
||||
fos = new FileOutputStream(outFile);
|
||||
fos.write(jpegBuf, 0, tjc.getCompressedSize());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
exitStatus = -1;
|
||||
}
|
||||
|
||||
try {
|
||||
if (fos != null) fos.close();
|
||||
if (tjc != null) tjc.close();
|
||||
} catch (Exception e) {}
|
||||
System.exit(exitStatus);
|
||||
}
|
||||
};
|
340
java/TJDecomp.java
Normal file
340
java/TJDecomp.java
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017-2018, 2022-2024 D. R. Commander.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG C API to approximate the
|
||||
* functionality of the IJG's djpeg program. djpeg features that are not
|
||||
* covered:
|
||||
*
|
||||
* - OS/2 BMP, GIF, and Targa output file formats [legacy feature]
|
||||
* - Color quantization and dithering [legacy feature]
|
||||
* - The floating-point IDCT method [legacy feature]
|
||||
* - Extracting an ICC color management profile
|
||||
* - Progress reporting
|
||||
* - Skipping rows (i.e. exclusive rather than inclusive partial decompression)
|
||||
* - Debug output
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.libjpegturbo.turbojpeg.*;
|
||||
|
||||
|
||||
@SuppressWarnings("checkstyle:JavadocType")
|
||||
final class TJDecomp {
|
||||
|
||||
private TJDecomp() {}
|
||||
|
||||
static final String CLASS_NAME =
|
||||
new TJDecomp().getClass().getName();
|
||||
|
||||
|
||||
private static boolean isCropped(java.awt.Rectangle cr) {
|
||||
return (cr.x != 0 || cr.y != 0 || cr.width != 0 || cr.height != 0);
|
||||
}
|
||||
|
||||
|
||||
private static String tjErrorMsg;
|
||||
private static int tjErrorCode = -1;
|
||||
|
||||
static void handleTJException(TJException e, int stopOnWarning)
|
||||
throws TJException {
|
||||
String errorMsg = e.getMessage();
|
||||
int errorCode = e.getErrorCode();
|
||||
|
||||
if (stopOnWarning != 1 && errorCode == TJ.ERR_WARNING) {
|
||||
if (tjErrorMsg == null || !tjErrorMsg.equals(errorMsg) ||
|
||||
tjErrorCode != errorCode) {
|
||||
tjErrorMsg = errorMsg;
|
||||
tjErrorCode = errorCode;
|
||||
System.out.println("WARNING: " + errorMsg);
|
||||
}
|
||||
} else
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
static void usage() {
|
||||
int i;
|
||||
TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
|
||||
int numScalingFactors = scalingFactors.length;
|
||||
|
||||
System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
|
||||
" [options] <JPEG image> <Output image>\n");
|
||||
|
||||
System.out.println("The output image will be in Windows BMP or PBMPLUS (PPM/PGM) format, depending");
|
||||
System.out.println("on the file extension.\n");
|
||||
|
||||
System.out.println("GENERAL OPTIONS (CAN BE ABBREVBIATED)");
|
||||
System.out.println("-------------------------------------");
|
||||
System.out.println("-strict");
|
||||
System.out.println(" Treat all warnings as fatal; abort immediately if incomplete or corrupt");
|
||||
System.out.println(" data is encountered in the JPEG image, rather than trying to salvage the");
|
||||
System.out.println(" rest of the image\n");
|
||||
|
||||
System.out.println("LOSSY JPEG OPTIONS (CAN BE ABBREVIATED)");
|
||||
System.out.println("---------------------------------------");
|
||||
System.out.println("-crop WxH+X+Y");
|
||||
System.out.println(" Decompress only the specified region of the JPEG image. (W, H, X, and Y");
|
||||
System.out.println(" are the width, height, left boundary, and upper boundary of the region, all");
|
||||
System.out.println(" specified relative to the scaled image dimensions.) If necessary, X will");
|
||||
System.out.println(" be shifted left to the nearest iMCU boundary, and W will be increased");
|
||||
System.out.println(" accordingly.");
|
||||
System.out.println("-dct fast");
|
||||
System.out.println(" Use less accurate IDCT algorithm [legacy feature]");
|
||||
System.out.println("-dct int");
|
||||
System.out.println(" Use more accurate IDCT algorithm [default]");
|
||||
System.out.println("-grayscale");
|
||||
System.out.println(" Decompress a full-color JPEG image into a grayscale output image");
|
||||
System.out.println("-maxmemory N");
|
||||
System.out.println(" Memory limit (in megabytes) for intermediate buffers used with progressive");
|
||||
System.out.println(" JPEG decompression [default = no limit]");
|
||||
System.out.println("-maxscans N");
|
||||
System.out.println(" Refuse to decompress progressive JPEG images that have more than N scans");
|
||||
System.out.println("-nosmooth");
|
||||
System.out.println(" Use the fastest chrominance upsampling algorithm available");
|
||||
System.out.println("-rgb");
|
||||
System.out.println(" Decompress a grayscale JPEG image into a full-color output image");
|
||||
System.out.println("-scale M/N");
|
||||
System.out.println(" Scale the width/height of the JPEG image by a factor of M/N when");
|
||||
System.out.print(" decompressing it (M/N = ");
|
||||
for (i = 0; i < numScalingFactors; i++) {
|
||||
System.out.format("%d/%d", scalingFactors[i].getNum(),
|
||||
scalingFactors[i].getDenom());
|
||||
if (numScalingFactors == 2 && i != numScalingFactors - 1)
|
||||
System.out.print(" or ");
|
||||
else if (numScalingFactors > 2) {
|
||||
if (i != numScalingFactors - 1)
|
||||
System.out.print(", ");
|
||||
if (i == numScalingFactors - 2)
|
||||
System.out.print("or ");
|
||||
}
|
||||
if (i % 8 == 0 && i != 0) System.out.print("\n ");
|
||||
}
|
||||
System.out.println(")\n");
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
static boolean matchArg(String arg, String string, int minChars) {
|
||||
if (arg.length() > string.length() || arg.length() < minChars)
|
||||
return false;
|
||||
|
||||
int cmpChars = Math.max(arg.length(), minChars);
|
||||
string = string.substring(0, cmpChars);
|
||||
|
||||
return arg.equalsIgnoreCase(string);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] argv) {
|
||||
int exitStatus = 0;
|
||||
TJDecompressor tjd = null;
|
||||
FileInputStream fis = null;
|
||||
|
||||
try {
|
||||
|
||||
int i;
|
||||
int colorspace, fastDCT = -1, fastUpsample = -1, maxMemory = -1,
|
||||
maxScans = -1, pixelFormat = TJ.PF_UNKNOWN, precision,
|
||||
stopOnWarning = -1, subsamp;
|
||||
java.awt.Rectangle croppingRegion = TJ.UNCROPPED;
|
||||
TJScalingFactor scalingFactor = TJ.UNSCALED;
|
||||
int width, height;
|
||||
byte[] jpegBuf;
|
||||
Object dstBuf = null;
|
||||
|
||||
for (i = 0; i < argv.length; i++) {
|
||||
if (matchArg(argv[i], "-crop", 2) && i < argv.length - 1) {
|
||||
int tempWidth = -1, tempHeight = -1, tempX = -1, tempY = -1;
|
||||
Scanner scanner = new Scanner(argv[++i]).useDelimiter("x|X|\\+");
|
||||
|
||||
try {
|
||||
tempWidth = scanner.nextInt();
|
||||
tempHeight = scanner.nextInt();
|
||||
tempX = scanner.nextInt();
|
||||
tempY = scanner.nextInt();
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (tempWidth < 1 || tempHeight < 1 || tempX < 0 || tempY < 0)
|
||||
usage();
|
||||
croppingRegion.width = tempWidth;
|
||||
croppingRegion.height = tempHeight;
|
||||
croppingRegion.x = tempX;
|
||||
croppingRegion.y = tempY;
|
||||
} else if (matchArg(argv[i], "-dct", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "fast", 1))
|
||||
fastDCT = 1;
|
||||
else if (!matchArg(argv[i], "int", 1))
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-grayscale", 2) ||
|
||||
matchArg(argv[i], "-greyscale", 2))
|
||||
pixelFormat = TJ.PF_GRAY;
|
||||
else if (matchArg(argv[i], "-maxscans", 5) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 0)
|
||||
usage();
|
||||
maxScans = temp;
|
||||
} else if (matchArg(argv[i], "-maxmemory", 2) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 0)
|
||||
usage();
|
||||
maxMemory = temp;
|
||||
} else if (matchArg(argv[i], "-nosmooth", 2))
|
||||
fastUpsample = 1;
|
||||
else if (matchArg(argv[i], "-rgb", 2))
|
||||
pixelFormat = TJ.PF_RGB;
|
||||
else if (matchArg(argv[i], "-strict", 3))
|
||||
stopOnWarning = 1;
|
||||
else if (matchArg(argv[i], "-scale", 2) && i < argv.length - 1) {
|
||||
int tempNum = 0, tempDenom = 0;
|
||||
boolean match = false, scanned = true;
|
||||
Scanner scanner = new Scanner(argv[++i]).useDelimiter("/");
|
||||
|
||||
try {
|
||||
tempNum = scanner.nextInt();
|
||||
tempDenom = scanner.nextInt();
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (tempNum < 1 || tempDenom < 1)
|
||||
usage();
|
||||
|
||||
TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
|
||||
for (int j = 0; j < scalingFactors.length; j++) {
|
||||
if ((double)tempNum / (double)tempDenom ==
|
||||
(double)scalingFactors[j].getNum() /
|
||||
(double)scalingFactors[j].getDenom()) {
|
||||
scalingFactor = scalingFactors[j];
|
||||
match = true; break;
|
||||
}
|
||||
}
|
||||
if (!match) usage();
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (i != argv.length - 2)
|
||||
usage();
|
||||
|
||||
tjd = new TJDecompressor();
|
||||
|
||||
if (stopOnWarning >= 0)
|
||||
tjd.set(TJ.PARAM_STOPONWARNING, stopOnWarning);
|
||||
if (fastUpsample >= 0)
|
||||
tjd.set(TJ.PARAM_FASTUPSAMPLE, fastUpsample);
|
||||
if (fastDCT >= 0)
|
||||
tjd.set(TJ.PARAM_FASTDCT, fastDCT);
|
||||
if (maxScans >= 0)
|
||||
tjd.set(TJ.PARAM_SCANLIMIT, maxScans);
|
||||
if (maxMemory >= 0)
|
||||
tjd.set(TJ.PARAM_MAXMEMORY, maxMemory);
|
||||
|
||||
File jpegFile = new File(argv[i++]);
|
||||
fis = new FileInputStream(jpegFile);
|
||||
int jpegSize = fis.available();
|
||||
if (jpegSize < 1)
|
||||
throw new Exception("Input file contains no data");
|
||||
jpegBuf = new byte[jpegSize];
|
||||
fis.read(jpegBuf);
|
||||
fis.close(); fis = null;
|
||||
|
||||
try {
|
||||
tjd.setSourceImage(jpegBuf, jpegSize);
|
||||
} catch (TJException e) { handleTJException(e, stopOnWarning); }
|
||||
subsamp = tjd.get(TJ.PARAM_SUBSAMP);
|
||||
width = tjd.get(TJ.PARAM_JPEGWIDTH);
|
||||
height = tjd.get(TJ.PARAM_JPEGHEIGHT);
|
||||
precision = tjd.get(TJ.PARAM_PRECISION);
|
||||
colorspace = tjd.get(TJ.PARAM_COLORSPACE);
|
||||
|
||||
if (pixelFormat == TJ.PF_UNKNOWN) {
|
||||
if (colorspace == TJ.CS_GRAY)
|
||||
pixelFormat = TJ.PF_GRAY;
|
||||
else if (colorspace == TJ.CS_CMYK || colorspace == TJ.CS_YCCK)
|
||||
pixelFormat = TJ.PF_CMYK;
|
||||
else
|
||||
pixelFormat = TJ.PF_RGB;
|
||||
}
|
||||
|
||||
if (tjd.get(TJ.PARAM_LOSSLESS) == 0) {
|
||||
tjd.setScalingFactor(scalingFactor);
|
||||
width = scalingFactor.getScaled(width);
|
||||
height = scalingFactor.getScaled(height);
|
||||
|
||||
if (isCropped(croppingRegion)) {
|
||||
int adjustment;
|
||||
|
||||
if (subsamp == TJ.SAMP_UNKNOWN)
|
||||
throw new Exception("Could not determine subsampling level of JPEG image");
|
||||
adjustment = croppingRegion.x %
|
||||
scalingFactor.getScaled(TJ.getMCUWidth(subsamp));
|
||||
croppingRegion.x -= adjustment;
|
||||
croppingRegion.width += adjustment;
|
||||
tjd.setCroppingRegion(croppingRegion);
|
||||
width = croppingRegion.width;
|
||||
height = croppingRegion.height;
|
||||
}
|
||||
}
|
||||
|
||||
if (precision <= 8)
|
||||
dstBuf = new byte[width * height * TJ.getPixelSize(pixelFormat)];
|
||||
else
|
||||
dstBuf = new short[width * height * TJ.getPixelSize(pixelFormat)];
|
||||
|
||||
try {
|
||||
if (precision <= 8)
|
||||
tjd.decompress8((byte[])dstBuf, 0, 0, 0, pixelFormat);
|
||||
else if (precision <= 12)
|
||||
tjd.decompress12((short[])dstBuf, 0, 0, 0, pixelFormat);
|
||||
else
|
||||
tjd.decompress16((short[])dstBuf, 0, 0, 0, pixelFormat);
|
||||
} catch (TJException e) { handleTJException(e, stopOnWarning); }
|
||||
|
||||
tjd.saveImage(argv[i], dstBuf, 0, 0, width, 0, height, pixelFormat);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
exitStatus = -1;
|
||||
}
|
||||
|
||||
try {
|
||||
if (fis != null) fis.close();
|
||||
if (tjd != null) tjd.close();
|
||||
} catch (Exception e) {}
|
||||
System.exit(exitStatus);
|
||||
}
|
||||
};
|
@ -1,402 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017-2018, 2022-2024 D. R. Commander.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to compress, decompress, and transform JPEG
|
||||
* images using the TurboJPEG Java API
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.nio.*;
|
||||
import javax.imageio.*;
|
||||
import javax.swing.*;
|
||||
import org.libjpegturbo.turbojpeg.*;
|
||||
|
||||
|
||||
@SuppressWarnings("checkstyle:JavadocType")
|
||||
class TJExample implements TJCustomFilter {
|
||||
|
||||
static final String CLASS_NAME =
|
||||
new TJExample().getClass().getName();
|
||||
|
||||
static final int DEFAULT_SUBSAMP = TJ.SAMP_444;
|
||||
static final int DEFAULT_QUALITY = 95;
|
||||
|
||||
|
||||
static final String[] SUBSAMP_NAME = {
|
||||
"4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1", "4:4:1"
|
||||
};
|
||||
|
||||
static final String[] COLORSPACE_NAME = {
|
||||
"RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
|
||||
};
|
||||
|
||||
|
||||
/* DCT filter example. This produces a negative of the image. */
|
||||
|
||||
@SuppressWarnings("checkstyle:JavadocMethod")
|
||||
public void customFilter(ShortBuffer coeffBuffer, Rectangle bufferRegion,
|
||||
Rectangle planeRegion, int componentIndex,
|
||||
int transformIndex, TJTransform transform)
|
||||
throws TJException {
|
||||
for (int i = 0; i < bufferRegion.width * bufferRegion.height; i++) {
|
||||
coeffBuffer.put(i, (short)(-coeffBuffer.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void usage() throws Exception {
|
||||
System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
|
||||
" <Input image> <Output image> [options]\n");
|
||||
|
||||
System.out.println("Input and output images can be in any image format that the Java Image I/O");
|
||||
System.out.println("extensions understand. If either filename ends in a .jpg extension, then");
|
||||
System.out.println("the TurboJPEG API will be used to compress or decompress the image.\n");
|
||||
|
||||
System.out.println("Compression Options (used if the output image is a JPEG image)");
|
||||
System.out.println("--------------------------------------------------------------\n");
|
||||
|
||||
System.out.println("-subsamp <444|422|420|gray> = Apply this level of chrominance subsampling when");
|
||||
System.out.println(" compressing the output image. The default is to use the same level of");
|
||||
System.out.println(" subsampling as in the input image, if the input image is also a JPEG");
|
||||
System.out.println(" image, or to use grayscale if the input image is a grayscale non-JPEG");
|
||||
System.out.println(" image, or to use " +
|
||||
SUBSAMP_NAME[DEFAULT_SUBSAMP] +
|
||||
" subsampling otherwise.\n");
|
||||
|
||||
System.out.println("-q <1-100> = Compress the output image with this JPEG quality level");
|
||||
System.out.println(" (default = " + DEFAULT_QUALITY + ").\n");
|
||||
|
||||
System.out.println("Decompression Options (used if the input image is a JPEG image)");
|
||||
System.out.println("---------------------------------------------------------------\n");
|
||||
|
||||
System.out.println("-scale M/N = Scale the input image by a factor of M/N when decompressing it.");
|
||||
System.out.print("(M/N = ");
|
||||
for (int i = 0; i < SCALING_FACTORS.length; i++) {
|
||||
System.out.print(SCALING_FACTORS[i].getNum() + "/" +
|
||||
SCALING_FACTORS[i].getDenom());
|
||||
if (SCALING_FACTORS.length == 2 && i != SCALING_FACTORS.length - 1)
|
||||
System.out.print(" or ");
|
||||
else if (SCALING_FACTORS.length > 2) {
|
||||
if (i != SCALING_FACTORS.length - 1)
|
||||
System.out.print(", ");
|
||||
if (i == SCALING_FACTORS.length - 2)
|
||||
System.out.print("or ");
|
||||
}
|
||||
}
|
||||
System.out.println(")\n");
|
||||
|
||||
System.out.println("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =");
|
||||
System.out.println(" Perform one of these lossless transform operations on the input image");
|
||||
System.out.println(" prior to decompressing it (these options are mutually exclusive.)\n");
|
||||
|
||||
System.out.println("-grayscale = Perform lossless grayscale conversion on the input image prior");
|
||||
System.out.println(" to decompressing it (can be combined with the other transform operations");
|
||||
System.out.println(" above.)\n");
|
||||
|
||||
System.out.println("-crop WxH+X+Y = Perform lossless cropping on the input image prior to");
|
||||
System.out.println(" decompressing it. X and Y specify the upper left corner of the cropping");
|
||||
System.out.println(" region, and W and H specify the width and height of the cropping region.");
|
||||
System.out.println(" X and Y must be evenly divible by the iMCU size (8x8 if the input image");
|
||||
System.out.println(" was compressed using no subsampling or grayscale, 16x8 if it was");
|
||||
System.out.println(" compressed using 4:2:2 subsampling, or 16x16 if it was compressed using");
|
||||
System.out.println(" 4:2:0 subsampling.)\n");
|
||||
|
||||
System.out.println("General Options");
|
||||
System.out.println("---------------\n");
|
||||
|
||||
System.out.println("-display = Display output image (Output filename need not be specified in this");
|
||||
System.out.println(" case.)\n");
|
||||
|
||||
System.out.println("-fastupsample = Use the fastest chrominance upsampling algorithm available\n");
|
||||
|
||||
System.out.println("-fastdct = Use the fastest DCT/IDCT algorithm available\n");
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] argv) {
|
||||
|
||||
try {
|
||||
|
||||
TJScalingFactor scalingFactor = TJ.UNSCALED;
|
||||
int outSubsamp = -1, outQual = -1;
|
||||
TJTransform xform = new TJTransform();
|
||||
boolean display = false, fastUpsample = false, fastDCT = false;
|
||||
int width, height;
|
||||
String inFormat = "jpg", outFormat = "jpg";
|
||||
BufferedImage img = null;
|
||||
byte[] imgBuf = null;
|
||||
|
||||
if (argv.length < 2)
|
||||
usage();
|
||||
|
||||
if (argv[1].substring(0, 2).equalsIgnoreCase("-d"))
|
||||
display = true;
|
||||
|
||||
/* Parse arguments. */
|
||||
for (int i = 2; i < argv.length; i++) {
|
||||
if (argv[i].length() < 2)
|
||||
continue;
|
||||
else if (argv[i].length() > 2 &&
|
||||
argv[i].substring(0, 3).equalsIgnoreCase("-sc") &&
|
||||
i < argv.length - 1) {
|
||||
int match = 0;
|
||||
String[] scaleArg = argv[++i].split("/");
|
||||
if (scaleArg.length == 2) {
|
||||
TJScalingFactor tempsf =
|
||||
new TJScalingFactor(Integer.parseInt(scaleArg[0]),
|
||||
Integer.parseInt(scaleArg[1]));
|
||||
for (int j = 0; j < SCALING_FACTORS.length; j++) {
|
||||
if (tempsf.equals(SCALING_FACTORS[j])) {
|
||||
scalingFactor = SCALING_FACTORS[j];
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match != 1)
|
||||
usage();
|
||||
} else if (argv[i].length() > 2 &&
|
||||
argv[i].substring(0, 3).equalsIgnoreCase("-su") &&
|
||||
i < argv.length - 1) {
|
||||
i++;
|
||||
if (argv[i].substring(0, 1).equalsIgnoreCase("g"))
|
||||
outSubsamp = TJ.SAMP_GRAY;
|
||||
else if (argv[i].equals("444"))
|
||||
outSubsamp = TJ.SAMP_444;
|
||||
else if (argv[i].equals("422"))
|
||||
outSubsamp = TJ.SAMP_422;
|
||||
else if (argv[i].equals("420"))
|
||||
outSubsamp = TJ.SAMP_420;
|
||||
else
|
||||
usage();
|
||||
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-q") &&
|
||||
i < argv.length - 1) {
|
||||
outQual = Integer.parseInt(argv[++i]);
|
||||
if (outQual < 1 || outQual > 100)
|
||||
usage();
|
||||
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-g"))
|
||||
xform.options |= TJTransform.OPT_GRAY;
|
||||
else if (argv[i].equalsIgnoreCase("-hflip"))
|
||||
xform.op = TJTransform.OP_HFLIP;
|
||||
else if (argv[i].equalsIgnoreCase("-vflip"))
|
||||
xform.op = TJTransform.OP_VFLIP;
|
||||
else if (argv[i].equalsIgnoreCase("-transpose"))
|
||||
xform.op = TJTransform.OP_TRANSPOSE;
|
||||
else if (argv[i].equalsIgnoreCase("-transverse"))
|
||||
xform.op = TJTransform.OP_TRANSVERSE;
|
||||
else if (argv[i].equalsIgnoreCase("-rot90"))
|
||||
xform.op = TJTransform.OP_ROT90;
|
||||
else if (argv[i].equalsIgnoreCase("-rot180"))
|
||||
xform.op = TJTransform.OP_ROT180;
|
||||
else if (argv[i].equalsIgnoreCase("-rot270"))
|
||||
xform.op = TJTransform.OP_ROT270;
|
||||
else if (argv[i].equalsIgnoreCase("-custom"))
|
||||
xform.cf = new TJExample();
|
||||
else if (argv[i].length() > 2 &&
|
||||
argv[i].substring(0, 2).equalsIgnoreCase("-c") &&
|
||||
i < argv.length - 1) {
|
||||
String[] cropArg = argv[++i].split("[x\\+]");
|
||||
if (cropArg.length != 4)
|
||||
usage();
|
||||
xform.width = Integer.parseInt(cropArg[0]);
|
||||
xform.height = Integer.parseInt(cropArg[1]);
|
||||
xform.x = Integer.parseInt(cropArg[2]);
|
||||
xform.y = Integer.parseInt(cropArg[3]);
|
||||
if (xform.x < 0 || xform.y < 0 || xform.width < 1 ||
|
||||
xform.height < 1)
|
||||
usage();
|
||||
xform.options |= TJTransform.OPT_CROP;
|
||||
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-d"))
|
||||
display = true;
|
||||
else if (argv[i].equalsIgnoreCase("-fastupsample")) {
|
||||
System.out.println("Using fast upsampling code");
|
||||
fastUpsample = true;
|
||||
} else if (argv[i].equalsIgnoreCase("-fastdct")) {
|
||||
System.out.println("Using fastest DCT/IDCT algorithm");
|
||||
fastDCT = true;
|
||||
} else usage();
|
||||
}
|
||||
|
||||
/* Determine input and output image formats based on file extensions. */
|
||||
String[] inFileTokens = argv[0].split("\\.");
|
||||
if (inFileTokens.length > 1)
|
||||
inFormat = inFileTokens[inFileTokens.length - 1];
|
||||
String[] outFileTokens;
|
||||
if (display)
|
||||
outFormat = "bmp";
|
||||
else {
|
||||
outFileTokens = argv[1].split("\\.");
|
||||
if (outFileTokens.length > 1)
|
||||
outFormat = outFileTokens[outFileTokens.length - 1];
|
||||
}
|
||||
|
||||
if (inFormat.equalsIgnoreCase("jpg")) {
|
||||
/* Input image is a JPEG image. Decompress and/or transform it. */
|
||||
boolean doTransform = (xform.op != TJTransform.OP_NONE ||
|
||||
xform.options != 0 || xform.cf != null);
|
||||
|
||||
/* Read the JPEG file into memory. */
|
||||
File jpegFile = new File(argv[0]);
|
||||
FileInputStream fis = new FileInputStream(jpegFile);
|
||||
int jpegSize = fis.available();
|
||||
if (jpegSize < 1) {
|
||||
System.out.println("Input file contains no data");
|
||||
System.exit(1);
|
||||
}
|
||||
byte[] jpegBuf = new byte[jpegSize];
|
||||
fis.read(jpegBuf);
|
||||
fis.close();
|
||||
|
||||
TJDecompressor tjd;
|
||||
if (doTransform) {
|
||||
/* Transform it. */
|
||||
TJTransformer tjt = new TJTransformer(jpegBuf);
|
||||
TJTransform[] xforms = new TJTransform[1];
|
||||
xforms[0] = xform;
|
||||
xforms[0].options |= TJTransform.OPT_TRIM;
|
||||
TJDecompressor[] tjds = tjt.transform(xforms);
|
||||
tjd = tjds[0];
|
||||
tjt.close();
|
||||
} else
|
||||
tjd = new TJDecompressor(jpegBuf);
|
||||
tjd.set(TJ.PARAM_FASTUPSAMPLE, fastUpsample ? 1 : 0);
|
||||
tjd.set(TJ.PARAM_FASTDCT, fastDCT ? 1 : 0);
|
||||
|
||||
width = tjd.getWidth();
|
||||
height = tjd.getHeight();
|
||||
int inSubsamp = tjd.get(TJ.PARAM_SUBSAMP);
|
||||
int inColorspace = tjd.get(TJ.PARAM_COLORSPACE);
|
||||
|
||||
if (tjd.get(TJ.PARAM_LOSSLESS) == 1)
|
||||
scalingFactor = TJ.UNSCALED;
|
||||
|
||||
System.out.println((doTransform ? "Transformed" : "Input") +
|
||||
" Image (jpg): " + width + " x " + height +
|
||||
" pixels, " + SUBSAMP_NAME[inSubsamp] +
|
||||
" subsampling, " + COLORSPACE_NAME[inColorspace]);
|
||||
|
||||
if (outFormat.equalsIgnoreCase("jpg") && doTransform &&
|
||||
scalingFactor.isOne() && outSubsamp < 0 && outQual < 0) {
|
||||
/* Input image has been transformed, and no re-compression options
|
||||
have been selected. Write the transformed image to disk and
|
||||
exit. */
|
||||
File outFile = new File(argv[1]);
|
||||
FileOutputStream fos = new FileOutputStream(outFile);
|
||||
fos.write(tjd.getJPEGBuf(), 0, tjd.getJPEGSize());
|
||||
fos.close();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/* Scaling and/or a non-JPEG output image format and/or compression
|
||||
options have been selected, so we need to decompress the
|
||||
input/transformed image. */
|
||||
tjd.setScalingFactor(scalingFactor);
|
||||
width = scalingFactor.getScaled(width);
|
||||
height = scalingFactor.getScaled(height);
|
||||
if (outSubsamp < 0)
|
||||
outSubsamp = inSubsamp;
|
||||
|
||||
if (!outFormat.equalsIgnoreCase("jpg"))
|
||||
img = tjd.decompress8(BufferedImage.TYPE_INT_RGB);
|
||||
else
|
||||
imgBuf = tjd.decompress8(0, TJ.PF_BGRX);
|
||||
tjd.close();
|
||||
} else {
|
||||
/* Input image is not a JPEG image. Load it into memory. */
|
||||
img = ImageIO.read(new File(argv[0]));
|
||||
if (img == null)
|
||||
throw new Exception("Input image type not supported.");
|
||||
width = img.getWidth();
|
||||
height = img.getHeight();
|
||||
if (outSubsamp < 0) {
|
||||
if (img.getType() == BufferedImage.TYPE_BYTE_GRAY)
|
||||
outSubsamp = TJ.SAMP_GRAY;
|
||||
else
|
||||
outSubsamp = DEFAULT_SUBSAMP;
|
||||
}
|
||||
System.out.println("Input Image: " + width + " x " + height +
|
||||
" pixels");
|
||||
}
|
||||
System.gc();
|
||||
if (!display)
|
||||
System.out.print("Output Image (" + outFormat + "): " + width +
|
||||
" x " + height + " pixels");
|
||||
|
||||
if (display) {
|
||||
/* Display the uncompressed image */
|
||||
ImageIcon icon = new ImageIcon(img);
|
||||
JLabel label = new JLabel(icon, JLabel.CENTER);
|
||||
JOptionPane.showMessageDialog(null, label, "Output Image",
|
||||
JOptionPane.PLAIN_MESSAGE);
|
||||
} else if (outFormat.equalsIgnoreCase("jpg")) {
|
||||
/* Output image format is JPEG. Compress the uncompressed image. */
|
||||
if (outQual < 0)
|
||||
outQual = DEFAULT_QUALITY;
|
||||
System.out.println(", " + SUBSAMP_NAME[outSubsamp] +
|
||||
" subsampling, quality = " + outQual);
|
||||
|
||||
TJCompressor tjc = new TJCompressor();
|
||||
tjc.set(TJ.PARAM_SUBSAMP, outSubsamp);
|
||||
tjc.set(TJ.PARAM_QUALITY, outQual);
|
||||
tjc.set(TJ.PARAM_FASTDCT, fastDCT ? 1 : 0);
|
||||
if (img != null)
|
||||
tjc.setSourceImage(img, 0, 0, 0, 0);
|
||||
else
|
||||
tjc.setSourceImage(imgBuf, 0, 0, width, 0, height, TJ.PF_BGRX);
|
||||
byte[] jpegBuf = tjc.compress();
|
||||
int jpegSize = tjc.getCompressedSize();
|
||||
tjc.close();
|
||||
|
||||
/* Write the JPEG image to disk. */
|
||||
File outFile = new File(argv[1]);
|
||||
FileOutputStream fos = new FileOutputStream(outFile);
|
||||
fos.write(jpegBuf, 0, jpegSize);
|
||||
fos.close();
|
||||
} else {
|
||||
/* Output image format is not JPEG. Save the uncompressed image
|
||||
directly to disk. */
|
||||
System.out.print("\n");
|
||||
File outFile = new File(argv[1]);
|
||||
ImageIO.write(img, outFormat, outFile);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static final TJScalingFactor[] SCALING_FACTORS =
|
||||
TJ.getScalingFactors();
|
||||
};
|
315
java/TJTran.java
Normal file
315
java/TJTran.java
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017-2018, 2022-2024 D. R. Commander.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG C API to approximate the
|
||||
* functionality of the IJG's jpegtran program. jpegtran features that are not
|
||||
* covered:
|
||||
*
|
||||
* - Adding restart markers to the output image
|
||||
* - Scan scripts
|
||||
* - Expanding the input image when cropping
|
||||
* - Wiping a region of the input image
|
||||
* - Dropping another JPEG image into the input image
|
||||
* - Copying only comment markers or ICC profile markers
|
||||
* - Embedding an ICC color management profile
|
||||
* - Progress reporting
|
||||
* - Treating warnings as non-fatal [limitation of the TurboJPEG Java API]
|
||||
* - Debug output
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.libjpegturbo.turbojpeg.*;
|
||||
|
||||
|
||||
@SuppressWarnings("checkstyle:JavadocType")
|
||||
final class TJTran {
|
||||
|
||||
private TJTran() {}
|
||||
|
||||
static final String CLASS_NAME =
|
||||
new TJTran().getClass().getName();
|
||||
|
||||
|
||||
private static boolean isCropped(java.awt.Rectangle cr) {
|
||||
return (cr.x != 0 || cr.y != 0 || cr.width != 0 || cr.height != 0);
|
||||
}
|
||||
|
||||
|
||||
static void usage() {
|
||||
int i;
|
||||
TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
|
||||
int numScalingFactors = scalingFactors.length;
|
||||
|
||||
System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
|
||||
" [options] <JPEG input image> <JPEG output image>\n");
|
||||
|
||||
System.out.println("This program reads the DCT coefficients from the lossy JPEG input image,");
|
||||
System.out.println("optionally transforms them, and writes them to a lossy JPEG output image.\n");
|
||||
|
||||
System.out.println("OPTIONS (CAN BE ABBREVBIATED)");
|
||||
System.out.println("-----------------------------");
|
||||
System.out.println("-arithmetic");
|
||||
System.out.println(" Use arithmetic entropy coding in the output image instead of Huffman");
|
||||
System.out.println(" entropy coding (can be combined with -progressive)");
|
||||
System.out.println("-copy all");
|
||||
System.out.println(" Copy all extra markers (including comments, JFIF thumbnails, Exif data, and");
|
||||
System.out.println(" ICC profile data) from the input image to the output image [default]");
|
||||
System.out.println("-copy none");
|
||||
System.out.println(" Copy no extra markers from the input image to the output image");
|
||||
System.out.println("-crop WxH+X+Y");
|
||||
System.out.println(" Include only the specified region of the input image. (W, H, X, and Y are");
|
||||
System.out.println(" the width, height, left boundary, and upper boundary of the region, all");
|
||||
System.out.println(" specified relative to the transformed image dimensions.) If necessary, X");
|
||||
System.out.println(" and Y will be shifted up and left to the nearest iMCU boundary, and W and H");
|
||||
System.out.println(" will be increased accordingly.");
|
||||
System.out.println("-flip {horizontal|vertical}, -rotate {90|180|270}, -transpose, -transverse");
|
||||
System.out.println(" Perform the specified lossless transform operation (these options are");
|
||||
System.out.println(" mutually exclusive)");
|
||||
System.out.println("-grayscale");
|
||||
System.out.println(" Create a grayscale output image from a full-color input image");
|
||||
System.out.println("-maxmemory N");
|
||||
System.out.println(" Memory limit (in megabytes) for intermediate buffers used with progressive");
|
||||
System.out.println(" JPEG compression, Huffman table optimization, and lossless transformation");
|
||||
System.out.println(" [default = no limit]");
|
||||
System.out.println("-maxscans N");
|
||||
System.out.println(" Refuse to transform progressive JPEG images that have more than N scans");
|
||||
System.out.println("-optimize");
|
||||
System.out.println(" Use Huffman table optimization in the output image");
|
||||
System.out.println("-perfect");
|
||||
System.out.println(" Abort if the requested transform operation is imperfect (non-reversible.)");
|
||||
System.out.println(" '-flip horizontal', '-rotate 180', '-rotate 270', and '-transverse' are");
|
||||
System.out.println(" imperfect if the image width is not evenly divisible by the iMCU width.");
|
||||
System.out.println(" '-flip vertical', '-rotate 90', '-rotate 180', and '-transverse' are");
|
||||
System.out.println(" imperfect if the image height is not evenly divisible by the iMCU height.");
|
||||
System.out.println("-progressive");
|
||||
System.out.println(" Create a progressive output image instead of a single-scan output image");
|
||||
System.out.println(" (can be combined with -arithmetic; implies -optimize unless -arithmetic is");
|
||||
System.out.println(" also specified)");
|
||||
System.out.println("-trim");
|
||||
System.out.println(" If necessary, trim the partial iMCUs at the right or bottom edge of the");
|
||||
System.out.println(" image to make the requested transform perfect\n");
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
static boolean matchArg(String arg, String string, int minChars) {
|
||||
if (arg.length() > string.length() || arg.length() < minChars)
|
||||
return false;
|
||||
|
||||
int cmpChars = Math.max(arg.length(), minChars);
|
||||
string = string.substring(0, cmpChars);
|
||||
|
||||
return arg.equalsIgnoreCase(string);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] argv) {
|
||||
int exitStatus = 0;
|
||||
TJTransformer tjt = null;
|
||||
FileInputStream fis = null;
|
||||
FileOutputStream fos = null;
|
||||
|
||||
try {
|
||||
|
||||
int i;
|
||||
int arithmetic = 0, maxMemory = -1, maxScans = -1, optimize = -1,
|
||||
progressive = 0, subsamp;
|
||||
TJTransform[] xform = new TJTransform[1];
|
||||
xform[0] = new TJTransform();
|
||||
byte[] srcBuf;
|
||||
int width, height;
|
||||
byte[][] dstBuf;
|
||||
|
||||
for (i = 0; i < argv.length; i++) {
|
||||
if (matchArg(argv[i], "-arithmetic", 2))
|
||||
arithmetic = 1;
|
||||
else if (matchArg(argv[i], "-crop", 3) && i < argv.length - 1) {
|
||||
int tempWidth = -1, tempHeight = -1, tempX = -1, tempY = -1;
|
||||
Scanner scanner = new Scanner(argv[++i]).useDelimiter("x|X|\\+");
|
||||
|
||||
try {
|
||||
tempWidth = scanner.nextInt();
|
||||
tempHeight = scanner.nextInt();
|
||||
tempX = scanner.nextInt();
|
||||
tempY = scanner.nextInt();
|
||||
} catch (Exception e) {}
|
||||
|
||||
if (tempWidth < 1 || tempHeight < 1 || tempX < 0 || tempY < 0)
|
||||
usage();
|
||||
xform[0].options |= TJTransform.OPT_CROP;
|
||||
xform[0].width = tempWidth;
|
||||
xform[0].height = tempHeight;
|
||||
xform[0].x = tempX;
|
||||
xform[0].y = tempY;
|
||||
} else if (matchArg(argv[i], "-copy", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "none", 1))
|
||||
xform[0].options |= TJTransform.OPT_COPYNONE;
|
||||
else if (!matchArg(argv[i], "all", 1))
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-flip", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "horizontal", 1))
|
||||
xform[0].op = TJTransform.OP_HFLIP;
|
||||
else if (matchArg(argv[i], "vertical", 1))
|
||||
xform[0].op = TJTransform.OP_VFLIP;
|
||||
else
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-grayscale", 2) ||
|
||||
matchArg(argv[i], "-greyscale", 2))
|
||||
xform[0].options |= TJTransform.OPT_GRAY;
|
||||
else if (matchArg(argv[i], "-maxscans", 5) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 0)
|
||||
usage();
|
||||
maxScans = temp;
|
||||
} else if (matchArg(argv[i], "-maxmemory", 2) && i < argv.length - 1) {
|
||||
int temp = -1;
|
||||
|
||||
try {
|
||||
temp = Integer.parseInt(argv[++i]);
|
||||
} catch (NumberFormatException e) {}
|
||||
if (temp < 0)
|
||||
usage();
|
||||
maxMemory = temp;
|
||||
} else if (matchArg(argv[i], "-optimize", 2) ||
|
||||
matchArg(argv[i], "-optimise", 2))
|
||||
optimize = 1;
|
||||
else if (matchArg(argv[i], "-perfect", 3))
|
||||
xform[0].options |= TJTransform.OPT_PERFECT;
|
||||
else if (matchArg(argv[i], "-progressive", 2))
|
||||
progressive = 1;
|
||||
else if (matchArg(argv[i], "-rotate", 2) && i < argv.length - 1) {
|
||||
i++;
|
||||
if (matchArg(argv[i], "90", 2))
|
||||
xform[0].op = TJTransform.OP_ROT90;
|
||||
else if (matchArg(argv[i], "180", 3))
|
||||
xform[0].op = TJTransform.OP_ROT180;
|
||||
else if (matchArg(argv[i], "270", 3))
|
||||
xform[0].op = TJTransform.OP_ROT270;
|
||||
else
|
||||
usage();
|
||||
} else if (matchArg(argv[i], "-transverse", 7))
|
||||
xform[0].op = TJTransform.OP_TRANSVERSE;
|
||||
else if (matchArg(argv[i], "-trim", 4))
|
||||
xform[0].options |= TJTransform.OPT_TRIM;
|
||||
else if (matchArg(argv[i], "-transpose", 2))
|
||||
xform[0].op = TJTransform.OP_TRANSPOSE;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (i != argv.length - 2)
|
||||
usage();
|
||||
|
||||
tjt = new TJTransformer();
|
||||
|
||||
if (optimize >= 0)
|
||||
tjt.set(TJ.PARAM_OPTIMIZE, optimize);
|
||||
if (maxScans >= 0)
|
||||
tjt.set(TJ.PARAM_SCANLIMIT, maxScans);
|
||||
if (maxMemory >= 0)
|
||||
tjt.set(TJ.PARAM_MAXMEMORY, maxMemory);
|
||||
|
||||
File inFile = new File(argv[i++]);
|
||||
fis = new FileInputStream(inFile);
|
||||
int srcSize = fis.available();
|
||||
if (srcSize < 1)
|
||||
throw new Exception("Input file contains no data");
|
||||
srcBuf = new byte[srcSize];
|
||||
fis.read(srcBuf);
|
||||
fis.close(); fis = null;
|
||||
|
||||
tjt.setSourceImage(srcBuf, srcSize);
|
||||
subsamp = tjt.get(TJ.PARAM_SUBSAMP);
|
||||
if (xform[0].op == TJTransform.OP_TRANSPOSE ||
|
||||
xform[0].op == TJTransform.OP_TRANSVERSE ||
|
||||
xform[0].op == TJTransform.OP_ROT90 ||
|
||||
xform[0].op == TJTransform.OP_ROT270) {
|
||||
width = tjt.get(TJ.PARAM_JPEGHEIGHT);
|
||||
height = tjt.get(TJ.PARAM_JPEGWIDTH);
|
||||
} else {
|
||||
width = tjt.get(TJ.PARAM_JPEGWIDTH);
|
||||
height = tjt.get(TJ.PARAM_JPEGHEIGHT);
|
||||
}
|
||||
if ((xform[0].options & TJTransform.OPT_GRAY) != 0)
|
||||
subsamp = TJ.SAMP_GRAY;
|
||||
|
||||
if (progressive >= 0)
|
||||
tjt.set(TJ.PARAM_PROGRESSIVE, progressive);
|
||||
if (arithmetic >= 0)
|
||||
tjt.set(TJ.PARAM_ARITHMETIC, arithmetic);
|
||||
|
||||
if (isCropped(xform[0])) {
|
||||
int xAdjust, yAdjust;
|
||||
|
||||
if (subsamp == TJ.SAMP_UNKNOWN)
|
||||
throw new Exception("Could not determine subsampling level of input image");
|
||||
if (xform[0].op == TJTransform.OP_TRANSPOSE ||
|
||||
xform[0].op == TJTransform.OP_TRANSVERSE ||
|
||||
xform[0].op == TJTransform.OP_ROT90 ||
|
||||
xform[0].op == TJTransform.OP_ROT270) {
|
||||
xAdjust = xform[0].x % TJ.getMCUHeight(subsamp);
|
||||
yAdjust = xform[0].y % TJ.getMCUWidth(subsamp);
|
||||
} else {
|
||||
xAdjust = xform[0].x % TJ.getMCUWidth(subsamp);
|
||||
yAdjust = xform[0].y % TJ.getMCUHeight(subsamp);
|
||||
}
|
||||
xform[0].x -= xAdjust;
|
||||
xform[0].width += xAdjust;
|
||||
xform[0].y -= yAdjust;
|
||||
xform[0].height += yAdjust;
|
||||
}
|
||||
|
||||
dstBuf = new byte[1][TJ.bufSize(width, height, subsamp)];
|
||||
|
||||
tjt.transform(dstBuf, xform);
|
||||
|
||||
File outFile = new File(argv[i]);
|
||||
fos = new FileOutputStream(outFile);
|
||||
fos.write(dstBuf[0], 0, tjt.getTransformedSizes()[0]);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
exitStatus = -1;
|
||||
}
|
||||
|
||||
try {
|
||||
if (fis != null) fis.close();
|
||||
if (tjt != null) tjt.close();
|
||||
if (fos != null) fos.close();
|
||||
} catch (Exception e) {}
|
||||
System.exit(exitStatus);
|
||||
}
|
||||
};
|
@ -95,8 +95,12 @@ Section "@CMAKE_PROJECT_NAME@ SDK for @INST_PLATFORM@ (required)"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\doc\structure.txt"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\doc\usage.txt"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\doc\wizard.txt"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\src\tjexample.c"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\java\TJExample.java"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\src\tjcomp.c"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\src\tjdecomp.c"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\src\tjtran.c"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\java\TJComp.java"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\java\TJDecomp.java"
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\java\TJTran.java"
|
||||
!ifdef GCC
|
||||
SetOutPath $INSTDIR\man\man1
|
||||
File "@CMAKE_CURRENT_SOURCE_DIR@\doc\cjpeg.1"
|
||||
@ -173,8 +177,12 @@ Section "Uninstall"
|
||||
Delete $INSTDIR\doc\structure.txt
|
||||
Delete $INSTDIR\doc\usage.txt
|
||||
Delete $INSTDIR\doc\wizard.txt
|
||||
Delete $INSTDIR\doc\tjexample.c
|
||||
Delete $INSTDIR\doc\TJExample.java
|
||||
Delete $INSTDIR\doc\tjcomp.c
|
||||
Delete $INSTDIR\doc\tjdecomp.c
|
||||
Delete $INSTDIR\doc\tjtran.c
|
||||
Delete $INSTDIR\doc\TJComp.java
|
||||
Delete $INSTDIR\doc\TJDecomp.java
|
||||
Delete $INSTDIR\doc\TJTran.java
|
||||
!ifdef GCC
|
||||
Delete $INSTDIR\man\man1\cjpeg.1
|
||||
Delete $INSTDIR\man\man1\djpeg.1
|
||||
|
@ -19,9 +19,10 @@
|
||||
*/
|
||||
|
||||
/* First-time users of libjpeg-turbo might be better served by looking at
|
||||
* tjexample.c, which uses the more straightforward TurboJPEG API. Note that
|
||||
* this example, like cjpeg and djpeg, interleaves disk I/O with JPEG
|
||||
* compression/decompression, so it is not suitable for benchmarking purposes.
|
||||
* tjcomp.c, tjdecomp.c, and tjtran.c, which use the more straightforward
|
||||
* TurboJPEG API and are more full-featured. Note that this example, like
|
||||
* cjpeg and djpeg, interleaves disk I/O with JPEG compression/decompression,
|
||||
* so it is not suitable for benchmarking purposes.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -1 +1,3 @@
|
||||
add_executable(md5cmp md5cmp.c md5.c md5hl.c)
|
||||
|
||||
add_executable(md5sum md5sum.c md5.c md5hl.c)
|
||||
|
60
src/md5/md5sum.c
Normal file
60
src/md5/md5sum.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C)2013, 2016, 2024 D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "./md5.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *md5sum = NULL, buf[65];
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "USAGE: %s <file>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
md5sum = MD5File(argv[i], buf);
|
||||
if (!md5sum) {
|
||||
fprintf(stderr, "Could not obtain MD5 sum for %s:\n%s\n", argv[i],
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s %s\n", md5sum, argv[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
321
src/tjcomp.c
Normal file
321
src/tjcomp.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017, 2019, 2021-2024
|
||||
* D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG C API to approximate the
|
||||
* functionality of the IJG's cjpeg program. cjpeg features that are not
|
||||
* covered:
|
||||
*
|
||||
* - GIF and Targa input file formats [legacy feature]
|
||||
* - Separate quality settings for luminance and chrominance
|
||||
* - The floating-point DCT method [legacy feature]
|
||||
* - Embedding an ICC color management profile
|
||||
* - Input image smoothing
|
||||
* - Progress reporting
|
||||
* - Debug output
|
||||
* - Forcing baseline-compatible quantization tables
|
||||
* - Specifying arbitrary quantization tables
|
||||
* - Specifying arbitrary sampling factors
|
||||
* - Scan scripts
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1600
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <turbojpeg.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define MATCH_ARG(arg, string, minChars) \
|
||||
!strncasecmp(arg, string, max(strlen(arg), minChars))
|
||||
|
||||
#define THROW(action, message) { \
|
||||
printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
|
||||
retval = -1; goto bailout; \
|
||||
}
|
||||
|
||||
#define THROW_TJ(action) THROW(action, tj3GetErrorStr(tjInstance))
|
||||
|
||||
#define THROW_UNIX(action) THROW(action, strerror(errno))
|
||||
|
||||
#define DEFAULT_SUBSAMP TJSAMP_420
|
||||
#define DEFAULT_QUALITY 75
|
||||
|
||||
|
||||
static const char *subsampName[TJ_NUMSAMP] = {
|
||||
"444", "422", "420", "GRAY", "440", "411", "441"
|
||||
};
|
||||
|
||||
|
||||
static void usage(char *programName)
|
||||
{
|
||||
printf("\nUSAGE: %s [options] <Input image> <JPEG image>\n\n", programName);
|
||||
|
||||
printf("The input image can be in Windows BMP or PBMPLUS (PPM/PGM) format.\n\n");
|
||||
|
||||
printf("GENERAL OPTIONS (CAN BE ABBREVIATED)\n");
|
||||
printf("------------------------------------\n");
|
||||
printf("-lossless PSV[,Pt]\n");
|
||||
printf(" Create a lossless JPEG image (implies -subsamp 444) using predictor\n");
|
||||
printf(" selection value PSV (1-7) and optional point transform Pt (0 through\n");
|
||||
printf(" {data precision} - 1)\n");
|
||||
printf("-maxmemory N\n");
|
||||
printf(" Memory limit (in megabytes) for intermediate buffers used with progressive\n");
|
||||
printf(" JPEG compression, lossless JPEG compression, and Huffman table optimization\n");
|
||||
printf(" [default = no limit]\n");
|
||||
printf("-precision N\n");
|
||||
printf(" Create a JPEG image with N-bit data precision [N = 2..16; default = 8; if N\n");
|
||||
printf(" is not 8 or 12, then -lossless must also be specified] (-precision 12\n");
|
||||
printf(" implies -optimize unless -arithmetic is also specified)\n");
|
||||
printf("-restart N\n");
|
||||
printf(" Add a restart marker every N MCU rows [default = 0 (no restart markers)].\n");
|
||||
printf(" Append 'B' to specify the restart marker interval in MCUs (lossy only.)\n\n");
|
||||
|
||||
printf("LOSSY JPEG OPTIONS (CAN BE ABBREVIATED)\n");
|
||||
printf("---------------------------------------\n");
|
||||
printf("-arithmetic\n");
|
||||
printf(" Use arithmetic entropy coding instead of Huffman entropy coding (can be\n");
|
||||
printf(" combined with -progressive)\n");
|
||||
printf("-dct fast\n");
|
||||
printf(" Use less accurate DCT algorithm [legacy feature]\n");
|
||||
printf("-dct int\n");
|
||||
printf(" Use more accurate DCT algorithm [default]\n");
|
||||
printf("-grayscale\n");
|
||||
printf(" Create a grayscale JPEG image from a full-color input image\n");
|
||||
printf("-optimize\n");
|
||||
printf(" Use Huffman table optimization\n");
|
||||
printf("-progressive\n");
|
||||
printf(" Create a progressive JPEG image instead of a single-scan JPEG image (can be\n");
|
||||
printf(" combined with -arithmetic; implies -optimize unless -arithmetic is also\n");
|
||||
printf(" specified)\n");
|
||||
printf("-quality {1..100}\n");
|
||||
printf(" Create a JPEG image with the specified quality level [default = %d]\n",
|
||||
DEFAULT_QUALITY);
|
||||
printf("-rgb\n");
|
||||
printf(" Create a JPEG image that uses the RGB colorspace instead of the YCbCr\n");
|
||||
printf(" colorspace\n");
|
||||
printf("-subsamp {444|422|440|420|411|441}\n");
|
||||
printf(" Create a JPEG image that uses the specified chrominance subsampling level\n");
|
||||
printf(" [default = %s]\n\n", subsampName[DEFAULT_SUBSAMP]);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, retval = 0;
|
||||
int arithmetic = -1, colorspace = -1, fastDCT = -1, losslessPSV = -1,
|
||||
losslessPt = -1, maxMemory = -1, optimize = -1, pixelFormat = TJPF_UNKNOWN,
|
||||
precision = -1, progressive = -1, quality = DEFAULT_QUALITY,
|
||||
restartIntervalBlocks = -1, restartIntervalRows = -1,
|
||||
subsamp = DEFAULT_SUBSAMP;
|
||||
tjhandle tjInstance = NULL;
|
||||
void *srcBuf = NULL;
|
||||
int width, height;
|
||||
unsigned char *jpegBuf = NULL;
|
||||
size_t jpegSize = 0;
|
||||
FILE *jpegFile = NULL;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (MATCH_ARG(argv[i], "-arithmetic", 2))
|
||||
arithmetic = 1;
|
||||
else if (MATCH_ARG(argv[i], "-dct", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "fast", 1))
|
||||
fastDCT = 1;
|
||||
else if (!MATCH_ARG(argv[i], "int", 1))
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-grayscale", 2) ||
|
||||
MATCH_ARG(argv[i], "-greyscale", 2))
|
||||
colorspace = TJCS_GRAY;
|
||||
else if (MATCH_ARG(argv[i], "-lossless", 2) && i < argc - 1) {
|
||||
if (sscanf(argv[++i], "%d,%d", &losslessPSV, &losslessPt) < 1 ||
|
||||
losslessPSV < 1 || losslessPSV > 7)
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-maxmemory", 2) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 0) usage(argv[0]);
|
||||
maxMemory = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-optimize", 2) ||
|
||||
MATCH_ARG(argv[i], "-optimise", 2))
|
||||
optimize = 1;
|
||||
else if (MATCH_ARG(argv[i], "-precision", 4) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 2 || tempi > 16)
|
||||
usage(argv[0]);
|
||||
precision = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-progressive", 2))
|
||||
progressive = 1;
|
||||
else if (MATCH_ARG(argv[i], "-quality", 2) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 1 || tempi > 100)
|
||||
usage(argv[0]);
|
||||
quality = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-rgb", 3))
|
||||
colorspace = TJCS_RGB;
|
||||
else if (MATCH_ARG(argv[i], "-restart", 2) && i < argc - 1) {
|
||||
int tempi = -1, nscan; char tempc = 0;
|
||||
|
||||
if ((nscan = sscanf(argv[++i], "%d%c", &tempi, &tempc)) < 1 ||
|
||||
tempi < 0 || tempi > 65535 ||
|
||||
(nscan == 2 && tempc != 'B' && tempc != 'b'))
|
||||
usage(argv[0]);
|
||||
|
||||
if (tempc == 'B' || tempc == 'b')
|
||||
restartIntervalBlocks = tempi;
|
||||
else
|
||||
restartIntervalRows = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-subsamp", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "444", 3))
|
||||
subsamp = TJSAMP_444;
|
||||
else if (MATCH_ARG(argv[i], "422", 3))
|
||||
subsamp = TJSAMP_422;
|
||||
else if (MATCH_ARG(argv[i], "440", 3))
|
||||
subsamp = TJSAMP_440;
|
||||
else if (MATCH_ARG(argv[i], "420", 3))
|
||||
subsamp = TJSAMP_420;
|
||||
else if (MATCH_ARG(argv[i], "411", 3))
|
||||
subsamp = TJSAMP_411;
|
||||
else if (MATCH_ARG(argv[i], "441", 3))
|
||||
subsamp = TJSAMP_441;
|
||||
else
|
||||
usage(argv[0]);
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (i != argc - 2)
|
||||
usage(argv[0]);
|
||||
if (losslessPSV == -1 && precision != -1 && precision != 8 &&
|
||||
precision != 12)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((tjInstance = tj3Init(TJINIT_COMPRESS)) == NULL)
|
||||
THROW_TJ("creating TurboJPEG instance");
|
||||
|
||||
if (tj3Set(tjInstance, TJPARAM_QUALITY, quality) < 0)
|
||||
THROW_TJ("setting TJPARAM_QUALITY");
|
||||
if (tj3Set(tjInstance, TJPARAM_SUBSAMP, subsamp) < 0)
|
||||
THROW_TJ("setting TJPARAM_SUBSAMP");
|
||||
if (precision >= 0 && tj3Set(tjInstance, TJPARAM_PRECISION, precision) < 0)
|
||||
THROW_TJ("setting TJPARAM_PRECISION");
|
||||
if (fastDCT >= 0 && tj3Set(tjInstance, TJPARAM_FASTDCT, fastDCT) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTDCT");
|
||||
if (optimize >= 0 && tj3Set(tjInstance, TJPARAM_OPTIMIZE, optimize) < 0)
|
||||
THROW_TJ("setting TJPARAM_OPTIMIZE");
|
||||
if (progressive >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_PROGRESSIVE, progressive) < 0)
|
||||
THROW_TJ("setting TJPARAM_PROGRESSIVE");
|
||||
if (arithmetic >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_ARITHMETIC, arithmetic) < 0)
|
||||
THROW_TJ("setting TJPARAM_ARITHMETIC");
|
||||
if (losslessPSV >= 1 && losslessPSV <= 7) {
|
||||
if (tj3Set(tjInstance, TJPARAM_LOSSLESS, 1) < 0)
|
||||
THROW_TJ("setting TJPARAM_LOSSLESS");
|
||||
if (tj3Set(tjInstance, TJPARAM_LOSSLESSPSV, losslessPSV) < 0)
|
||||
THROW_TJ("setting TJPARAM_LOSSLESSPSV");
|
||||
if (losslessPt >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_LOSSLESSPT, losslessPt) < 0)
|
||||
THROW_TJ("setting TJPARAM_LOSSLESSPT");
|
||||
}
|
||||
if (restartIntervalBlocks >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_RESTARTBLOCKS, restartIntervalBlocks) < 0)
|
||||
THROW_TJ("setting TJPARAM_RESTARTBLOCKS");
|
||||
if (restartIntervalRows >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_RESTARTROWS, restartIntervalRows) < 0)
|
||||
THROW_TJ("setting TJPARAM_RESTARTROWS");
|
||||
if (maxMemory >= 0 && tj3Set(tjInstance, TJPARAM_MAXMEMORY, maxMemory) < 0)
|
||||
THROW_TJ("setting TJPARAM_MAXMEMORY");
|
||||
|
||||
if (precision <= 8) {
|
||||
if ((srcBuf = tj3LoadImage8(tjInstance, argv[i], &width, 1, &height,
|
||||
&pixelFormat)) == NULL)
|
||||
THROW_TJ("loading input image");
|
||||
} else if (precision <= 12) {
|
||||
if ((srcBuf = tj3LoadImage12(tjInstance, argv[i], &width, 1, &height,
|
||||
&pixelFormat)) == NULL)
|
||||
THROW_TJ("loading input image");
|
||||
} else {
|
||||
if ((srcBuf = tj3LoadImage16(tjInstance, argv[i], &width, 1, &height,
|
||||
&pixelFormat)) == NULL)
|
||||
THROW_TJ("loading input image");
|
||||
}
|
||||
|
||||
if (pixelFormat == TJPF_GRAY && colorspace < 0)
|
||||
colorspace = TJCS_GRAY;
|
||||
if (colorspace >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_COLORSPACE, colorspace) < 0)
|
||||
THROW_TJ("setting TJPARAM_COLORSPACE");
|
||||
|
||||
if (precision <= 8) {
|
||||
if (tj3Compress8(tjInstance, srcBuf, width, 0, height, pixelFormat,
|
||||
&jpegBuf, &jpegSize) < 0)
|
||||
THROW_TJ("compressing image");
|
||||
} else if (precision <= 12) {
|
||||
if (tj3Compress12(tjInstance, srcBuf, width, 0, height, pixelFormat,
|
||||
&jpegBuf, &jpegSize) < 0)
|
||||
THROW_TJ("compressing image");
|
||||
} else {
|
||||
if (tj3Compress16(tjInstance, srcBuf, width, 0, height, pixelFormat,
|
||||
&jpegBuf, &jpegSize) < 0)
|
||||
THROW_TJ("compressing image");
|
||||
}
|
||||
|
||||
if ((jpegFile = fopen(argv[++i], "wb")) == NULL)
|
||||
THROW_UNIX("opening output file");
|
||||
if (fwrite(jpegBuf, jpegSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("writing output file");
|
||||
|
||||
bailout:
|
||||
tj3Destroy(tjInstance);
|
||||
tj3Free(srcBuf);
|
||||
tj3Free(jpegBuf);
|
||||
if (jpegFile) fclose(jpegFile);
|
||||
return retval;
|
||||
}
|
351
src/tjdecomp.c
Normal file
351
src/tjdecomp.c
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017, 2019, 2021-2024
|
||||
* D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG C API to approximate the
|
||||
* functionality of the IJG's djpeg program. djpeg features that are not
|
||||
* covered:
|
||||
*
|
||||
* - OS/2 BMP, GIF, and Targa output file formats [legacy feature]
|
||||
* - Color quantization and dithering [legacy feature]
|
||||
* - The floating-point IDCT method [legacy feature]
|
||||
* - Extracting an ICC color management profile
|
||||
* - Progress reporting
|
||||
* - Skipping rows (i.e. exclusive rather than inclusive partial decompression)
|
||||
* - Debug output
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1600
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <turbojpeg.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define MATCH_ARG(arg, string, minChars) \
|
||||
!strncasecmp(arg, string, max(strlen(arg), minChars))
|
||||
|
||||
#define IS_CROPPED(cr) (cr.x != 0 || cr.y != 0 || cr.w != 0 || cr.h != 0)
|
||||
|
||||
#define THROW(action, message) { \
|
||||
printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
|
||||
retval = -1; goto bailout; \
|
||||
}
|
||||
|
||||
#define THROW_TJ(action) { \
|
||||
int errorCode = tj3GetErrorCode(tjInstance); \
|
||||
printf("%s in line %d while %s:\n%s\n", \
|
||||
errorCode == TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, action, \
|
||||
tj3GetErrorStr(tjInstance)); \
|
||||
if (errorCode == TJERR_FATAL || stopOnWarning == 1) { \
|
||||
retval = -1; goto bailout; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define THROW_UNIX(action) THROW(action, strerror(errno))
|
||||
|
||||
#define DEFAULT_SUBSAMP TJSAMP_444
|
||||
#define DEFAULT_QUALITY 95
|
||||
|
||||
|
||||
static tjscalingfactor *scalingFactors = NULL;
|
||||
static int numScalingFactors = 0;
|
||||
|
||||
|
||||
static void usage(char *programName)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\nUSAGE: %s [options] <JPEG image> <Output image>\n\n", programName);
|
||||
|
||||
printf("The output image will be in Windows BMP or PBMPLUS (PPM/PGM) format, depending\n");
|
||||
printf("on the file extension.\n\n");
|
||||
|
||||
printf("GENERAL OPTIONS (CAN BE ABBREVBIATED)\n");
|
||||
printf("-------------------------------------\n");
|
||||
printf("-strict\n");
|
||||
printf(" Treat all warnings as fatal; abort immediately if incomplete or corrupt\n");
|
||||
printf(" data is encountered in the JPEG image, rather than trying to salvage the\n");
|
||||
printf(" rest of the image\n\n");
|
||||
|
||||
printf("LOSSY JPEG OPTIONS (CAN BE ABBREVIATED)\n");
|
||||
printf("---------------------------------------\n");
|
||||
printf("-crop WxH+X+Y\n");
|
||||
printf(" Decompress only the specified region of the JPEG image. (W, H, X, and Y\n");
|
||||
printf(" are the width, height, left boundary, and upper boundary of the region, all\n");
|
||||
printf(" specified relative to the scaled image dimensions.) If necessary, X will\n");
|
||||
printf(" be shifted left to the nearest iMCU boundary, and W will be increased\n");
|
||||
printf(" accordingly.\n");
|
||||
printf("-dct fast\n");
|
||||
printf(" Use less accurate IDCT algorithm [legacy feature]\n");
|
||||
printf("-dct int\n");
|
||||
printf(" Use more accurate IDCT algorithm [default]\n");
|
||||
printf("-grayscale\n");
|
||||
printf(" Decompress a full-color JPEG image into a grayscale output image\n");
|
||||
printf("-maxmemory N\n");
|
||||
printf(" Memory limit (in megabytes) for intermediate buffers used with progressive\n");
|
||||
printf(" JPEG decompression [default = no limit]\n");
|
||||
printf("-maxscans N\n");
|
||||
printf(" Refuse to decompress progressive JPEG images that have more than N scans\n");
|
||||
printf("-nosmooth\n");
|
||||
printf(" Use the fastest chrominance upsampling algorithm available\n");
|
||||
printf("-rgb\n");
|
||||
printf(" Decompress a grayscale JPEG image into a full-color output image\n");
|
||||
printf("-scale M/N\n");
|
||||
printf(" Scale the width/height of the JPEG image by a factor of M/N when\n");
|
||||
printf(" decompressing it (M/N = ");
|
||||
for (i = 0; i < numScalingFactors; i++) {
|
||||
printf("%d/%d", scalingFactors[i].num, scalingFactors[i].denom);
|
||||
if (numScalingFactors == 2 && i != numScalingFactors - 1)
|
||||
printf(" or ");
|
||||
else if (numScalingFactors > 2) {
|
||||
if (i != numScalingFactors - 1)
|
||||
printf(", ");
|
||||
if (i == numScalingFactors - 2)
|
||||
printf("or ");
|
||||
}
|
||||
if (i % 8 == 0 && i != 0) printf("\n ");
|
||||
}
|
||||
printf(")\n\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, retval = 0;
|
||||
int colorspace, fastDCT = -1, fastUpsample = -1, maxMemory = -1,
|
||||
maxScans = -1, pixelFormat = TJPF_UNKNOWN, precision, stopOnWarning = -1,
|
||||
subsamp;
|
||||
tjregion croppingRegion = TJUNCROPPED;
|
||||
tjscalingfactor scalingFactor = TJUNSCALED;
|
||||
tjhandle tjInstance = NULL;
|
||||
FILE *jpegFile = NULL;
|
||||
long size = 0;
|
||||
size_t jpegSize, sampleSize;
|
||||
int width, height;
|
||||
unsigned char *jpegBuf = NULL;
|
||||
void *dstBuf = NULL;
|
||||
|
||||
if ((scalingFactors = tj3GetScalingFactors(&numScalingFactors)) == NULL)
|
||||
THROW_TJ("getting scaling factors");
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
if (MATCH_ARG(argv[i], "-crop", 2) && i < argc - 1) {
|
||||
char tempc = -1;
|
||||
|
||||
if (sscanf(argv[++i], "%d%c%d+%d+%d", &croppingRegion.w, &tempc,
|
||||
&croppingRegion.h, &croppingRegion.x,
|
||||
&croppingRegion.y) != 5 || croppingRegion.w < 1 ||
|
||||
(tempc != 'x' && tempc != 'X') || croppingRegion.h < 1 ||
|
||||
croppingRegion.x < 0 || croppingRegion.y < 0)
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-dct", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "fast", 1))
|
||||
fastDCT = 1;
|
||||
else if (!MATCH_ARG(argv[i], "int", 1))
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-grayscale", 2) ||
|
||||
MATCH_ARG(argv[i], "-greyscale", 2))
|
||||
pixelFormat = TJPF_GRAY;
|
||||
else if (MATCH_ARG(argv[i], "-maxscans", 5) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 0) usage(argv[0]);
|
||||
maxScans = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-maxmemory", 2) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 0) usage(argv[0]);
|
||||
maxMemory = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-nosmooth", 2))
|
||||
fastUpsample = 1;
|
||||
else if (MATCH_ARG(argv[i], "-rgb", 2))
|
||||
pixelFormat = TJPF_RGB;
|
||||
else if (MATCH_ARG(argv[i], "-strict", 3))
|
||||
stopOnWarning = 1;
|
||||
else if (MATCH_ARG(argv[i], "-scale", 2) && i < argc - 1) {
|
||||
int match = 0, temp_num = 0, temp_denom = 0, j;
|
||||
|
||||
if (sscanf(argv[++i], "%d/%d", &temp_num, &temp_denom) < 2)
|
||||
usage(argv[0]);
|
||||
if (temp_num < 1 || temp_denom < 1)
|
||||
usage(argv[0]);
|
||||
for (j = 0; j < numScalingFactors; j++) {
|
||||
if ((double)temp_num / (double)temp_denom ==
|
||||
(double)scalingFactors[j].num / (double)scalingFactors[j].denom) {
|
||||
scalingFactor = scalingFactors[j];
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match != 1)
|
||||
usage(argv[0]);
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (i != argc - 2)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((tjInstance = tj3Init(TJINIT_DECOMPRESS)) == NULL)
|
||||
THROW_TJ("creating TurboJPEG instance");
|
||||
|
||||
if (stopOnWarning >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_STOPONWARNING, stopOnWarning) < 0)
|
||||
THROW_TJ("setting TJPARAM_STOPONWARNING");
|
||||
if (fastUpsample >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_FASTUPSAMPLE, fastUpsample) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTUPSAMPLE");
|
||||
if (fastDCT >= 0 && tj3Set(tjInstance, TJPARAM_FASTDCT, fastDCT) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTDCT");
|
||||
if (maxScans >= 0 && tj3Set(tjInstance, TJPARAM_SCANLIMIT, maxScans) < 0)
|
||||
THROW_TJ("setting TJPARAM_SCANLIMIT");
|
||||
if (maxMemory >= 0 && tj3Set(tjInstance, TJPARAM_MAXMEMORY, maxMemory) < 0)
|
||||
THROW_TJ("setting TJPARAM_MAXMEMORY");
|
||||
|
||||
if ((jpegFile = fopen(argv[i++], "rb")) == NULL)
|
||||
THROW_UNIX("opening input file");
|
||||
if (fseek(jpegFile, 0, SEEK_END) < 0 || ((size = ftell(jpegFile)) < 0) ||
|
||||
fseek(jpegFile, 0, SEEK_SET) < 0)
|
||||
THROW_UNIX("determining input file size");
|
||||
if (size == 0)
|
||||
THROW("determining input file size", "Input file contains no data");
|
||||
jpegSize = size;
|
||||
if ((jpegBuf = (unsigned char *)malloc(jpegSize)) == NULL)
|
||||
THROW_UNIX("allocating JPEG buffer");
|
||||
if (fread(jpegBuf, jpegSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("reading input file");
|
||||
fclose(jpegFile); jpegFile = NULL;
|
||||
|
||||
if (tj3DecompressHeader(tjInstance, jpegBuf, jpegSize) < 0)
|
||||
THROW_TJ("reading JPEG header");
|
||||
subsamp = tj3Get(tjInstance, TJPARAM_SUBSAMP);
|
||||
width = tj3Get(tjInstance, TJPARAM_JPEGWIDTH);
|
||||
height = tj3Get(tjInstance, TJPARAM_JPEGHEIGHT);
|
||||
precision = tj3Get(tjInstance, TJPARAM_PRECISION);
|
||||
sampleSize = (precision <= 8 ? sizeof(unsigned char) : sizeof(short));
|
||||
colorspace = tj3Get(tjInstance, TJPARAM_COLORSPACE);
|
||||
|
||||
if (pixelFormat == TJPF_UNKNOWN) {
|
||||
if (colorspace == TJCS_GRAY)
|
||||
pixelFormat = TJPF_GRAY;
|
||||
else if (colorspace == TJCS_CMYK || colorspace == TJCS_YCCK)
|
||||
pixelFormat = TJPF_CMYK;
|
||||
else
|
||||
pixelFormat = TJPF_RGB;
|
||||
}
|
||||
|
||||
if (!tj3Get(tjInstance, TJPARAM_LOSSLESS)) {
|
||||
if (tj3SetScalingFactor(tjInstance, scalingFactor) < 0)
|
||||
THROW_TJ("setting scaling factor");
|
||||
width = TJSCALED(width, scalingFactor);
|
||||
height = TJSCALED(height, scalingFactor);
|
||||
|
||||
if (IS_CROPPED(croppingRegion)) {
|
||||
int adjustment;
|
||||
|
||||
if (subsamp == TJSAMP_UNKNOWN)
|
||||
THROW("adjusting cropping region",
|
||||
"Could not determine subsampling level of JPEG image");
|
||||
adjustment =
|
||||
croppingRegion.x % TJSCALED(tjMCUWidth[subsamp], scalingFactor);
|
||||
croppingRegion.x -= adjustment;
|
||||
croppingRegion.w += adjustment;
|
||||
if (tj3SetCroppingRegion(tjInstance, croppingRegion) < 0)
|
||||
THROW_TJ("setting cropping region");
|
||||
width = croppingRegion.w;
|
||||
height = croppingRegion.h;
|
||||
}
|
||||
}
|
||||
|
||||
#if ULLONG_MAX > SIZE_MAX
|
||||
if ((unsigned long long)width * height * tjPixelSize[pixelFormat] *
|
||||
sampleSize > (unsigned long long)((size_t)-1))
|
||||
THROW("allocating uncompressed image buffer", "Image is too large");
|
||||
#endif
|
||||
if ((dstBuf =
|
||||
(unsigned char *)malloc(sizeof(unsigned char) * width * height *
|
||||
tjPixelSize[pixelFormat] * sampleSize)) == NULL)
|
||||
THROW_UNIX("allocating uncompressed image buffer");
|
||||
|
||||
if (precision <= 8) {
|
||||
if (tj3Decompress8(tjInstance, jpegBuf, jpegSize, dstBuf, 0,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("decompressing JPEG image");
|
||||
} else if (precision <= 12) {
|
||||
if (tj3Decompress12(tjInstance, jpegBuf, jpegSize, dstBuf, 0,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("decompressing JPEG image");
|
||||
} else {
|
||||
if (tj3Decompress16(tjInstance, jpegBuf, jpegSize, dstBuf, 0,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("decompressing JPEG image");
|
||||
}
|
||||
tj3Free(jpegBuf); jpegBuf = NULL;
|
||||
|
||||
if (precision <= 8) {
|
||||
if (tj3SaveImage8(tjInstance, argv[i], dstBuf, width, 0, height,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("saving output image");
|
||||
} else if (precision <= 12) {
|
||||
if (tj3SaveImage12(tjInstance, argv[i], dstBuf, width, 0, height,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("saving output image");
|
||||
} else {
|
||||
if (tj3SaveImage16(tjInstance, argv[i], dstBuf, width, 0, height,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("saving output image");
|
||||
}
|
||||
|
||||
bailout:
|
||||
tj3Destroy(tjInstance);
|
||||
if (jpegFile) fclose(jpegFile);
|
||||
tj3Free(jpegBuf);
|
||||
free(dstBuf);
|
||||
return retval;
|
||||
}
|
413
src/tjexample.c
413
src/tjexample.c
@ -1,413 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017, 2019, 2021-2024
|
||||
* D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to compress, decompress, and transform JPEG
|
||||
* images using the TurboJPEG C API
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1600
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <turbojpeg.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#define THROW(action, message) { \
|
||||
printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
|
||||
retval = -1; goto bailout; \
|
||||
}
|
||||
|
||||
#define THROW_TJ(action) THROW(action, tj3GetErrorStr(tjInstance))
|
||||
|
||||
#define THROW_UNIX(action) THROW(action, strerror(errno))
|
||||
|
||||
#define DEFAULT_SUBSAMP TJSAMP_444
|
||||
#define DEFAULT_QUALITY 95
|
||||
|
||||
|
||||
static const char *subsampName[TJ_NUMSAMP] = {
|
||||
"4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1", "4:4:1"
|
||||
};
|
||||
|
||||
static const char *colorspaceName[TJ_NUMCS] = {
|
||||
"RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
|
||||
};
|
||||
|
||||
static tjscalingfactor *scalingFactors = NULL;
|
||||
static int numScalingFactors = 0;
|
||||
|
||||
|
||||
/* DCT filter example. This produces a negative of the image. */
|
||||
|
||||
static int customFilter(short *coeffs, tjregion arrayRegion,
|
||||
tjregion planeRegion, int componentIndex,
|
||||
int transformIndex, tjtransform *transform)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < arrayRegion.w * arrayRegion.h; i++)
|
||||
coeffs[i] = -coeffs[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void usage(char *programName)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\nUSAGE: %s <Input image> <Output image> [options]\n\n",
|
||||
programName);
|
||||
|
||||
printf("Input and output images can be in Windows BMP or PBMPLUS (PPM/PGM) format. If\n");
|
||||
printf("either filename ends in a .jpg extension, then the TurboJPEG API will be used\n");
|
||||
printf("to compress or decompress the image.\n\n");
|
||||
|
||||
printf("Compression Options (used if the output image is a JPEG image)\n");
|
||||
printf("--------------------------------------------------------------\n\n");
|
||||
|
||||
printf("-subsamp <444|422|420|gray> = Apply this level of chrominance subsampling when\n");
|
||||
printf(" compressing the output image. The default is to use the same level of\n");
|
||||
printf(" subsampling as in the input image, if the input image is also a JPEG\n");
|
||||
printf(" image, or to use grayscale if the input image is a grayscale non-JPEG\n");
|
||||
printf(" image, or to use %s subsampling otherwise.\n\n",
|
||||
subsampName[DEFAULT_SUBSAMP]);
|
||||
|
||||
printf("-q <1-100> = Compress the output image with this JPEG quality level\n");
|
||||
printf(" (default = %d).\n\n", DEFAULT_QUALITY);
|
||||
|
||||
printf("Decompression Options (used if the input image is a JPEG image)\n");
|
||||
printf("---------------------------------------------------------------\n\n");
|
||||
|
||||
printf("-scale M/N = Scale the input image by a factor of M/N when decompressing it.\n");
|
||||
printf("(M/N = ");
|
||||
for (i = 0; i < numScalingFactors; i++) {
|
||||
printf("%d/%d", scalingFactors[i].num, scalingFactors[i].denom);
|
||||
if (numScalingFactors == 2 && i != numScalingFactors - 1)
|
||||
printf(" or ");
|
||||
else if (numScalingFactors > 2) {
|
||||
if (i != numScalingFactors - 1)
|
||||
printf(", ");
|
||||
if (i == numScalingFactors - 2)
|
||||
printf("or ");
|
||||
}
|
||||
}
|
||||
printf(")\n\n");
|
||||
|
||||
printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =\n");
|
||||
printf(" Perform one of these lossless transform operations on the input image\n");
|
||||
printf(" prior to decompressing it (these options are mutually exclusive.)\n\n");
|
||||
|
||||
printf("-grayscale = Perform lossless grayscale conversion on the input image prior\n");
|
||||
printf(" to decompressing it (can be combined with the other transform operations\n");
|
||||
printf(" above.)\n\n");
|
||||
|
||||
printf("-crop WxH+X+Y = Perform lossless cropping on the input image prior to\n");
|
||||
printf(" decompressing it. X and Y specify the upper left corner of the cropping\n");
|
||||
printf(" region, and W and H specify the width and height of the cropping region.\n");
|
||||
printf(" X and Y must be evenly divible by the iMCU size (8x8 if the input image\n");
|
||||
printf(" was compressed using no subsampling or grayscale, 16x8 if it was\n");
|
||||
printf(" compressed using 4:2:2 subsampling, or 16x16 if it was compressed using\n");
|
||||
printf(" 4:2:0 subsampling.)\n\n");
|
||||
|
||||
printf("General Options\n");
|
||||
printf("---------------\n\n");
|
||||
|
||||
printf("-fastupsample = Use the fastest chrominance upsampling algorithm available\n\n");
|
||||
|
||||
printf("-fastdct = Use the fastest DCT/IDCT algorithm available\n\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
tjscalingfactor scalingFactor = TJUNSCALED;
|
||||
int outSubsamp = -1, outQual = -1;
|
||||
tjtransform xform;
|
||||
int fastUpsample = 0, fastDCT = 0;
|
||||
int width, height;
|
||||
char *inFormat, *outFormat;
|
||||
FILE *jpegFile = NULL;
|
||||
unsigned char *imgBuf = NULL, *jpegBuf = NULL;
|
||||
int retval = 0, i, pixelFormat = TJPF_UNKNOWN;
|
||||
tjhandle tjInstance = NULL;
|
||||
|
||||
if ((scalingFactors = tj3GetScalingFactors(&numScalingFactors)) == NULL)
|
||||
THROW_TJ("getting scaling factors");
|
||||
memset(&xform, 0, sizeof(tjtransform));
|
||||
|
||||
if (argc < 3)
|
||||
usage(argv[0]);
|
||||
|
||||
/* Parse arguments. */
|
||||
for (i = 3; i < argc; i++) {
|
||||
if (!strncasecmp(argv[i], "-sc", 3) && i < argc - 1) {
|
||||
int match = 0, temp1 = 0, temp2 = 0, j;
|
||||
|
||||
if (sscanf(argv[++i], "%d/%d", &temp1, &temp2) < 2)
|
||||
usage(argv[0]);
|
||||
for (j = 0; j < numScalingFactors; j++) {
|
||||
if ((double)temp1 / (double)temp2 == (double)scalingFactors[j].num /
|
||||
(double)scalingFactors[j].denom) {
|
||||
scalingFactor = scalingFactors[j];
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match != 1)
|
||||
usage(argv[0]);
|
||||
} else if (!strncasecmp(argv[i], "-su", 3) && i < argc - 1) {
|
||||
i++;
|
||||
if (!strncasecmp(argv[i], "g", 1))
|
||||
outSubsamp = TJSAMP_GRAY;
|
||||
else if (!strcasecmp(argv[i], "444"))
|
||||
outSubsamp = TJSAMP_444;
|
||||
else if (!strcasecmp(argv[i], "422"))
|
||||
outSubsamp = TJSAMP_422;
|
||||
else if (!strcasecmp(argv[i], "420"))
|
||||
outSubsamp = TJSAMP_420;
|
||||
else
|
||||
usage(argv[0]);
|
||||
} else if (!strncasecmp(argv[i], "-q", 2) && i < argc - 1) {
|
||||
outQual = atoi(argv[++i]);
|
||||
if (outQual < 1 || outQual > 100)
|
||||
usage(argv[0]);
|
||||
} else if (!strncasecmp(argv[i], "-g", 2))
|
||||
xform.options |= TJXOPT_GRAY;
|
||||
else if (!strcasecmp(argv[i], "-hflip"))
|
||||
xform.op = TJXOP_HFLIP;
|
||||
else if (!strcasecmp(argv[i], "-vflip"))
|
||||
xform.op = TJXOP_VFLIP;
|
||||
else if (!strcasecmp(argv[i], "-transpose"))
|
||||
xform.op = TJXOP_TRANSPOSE;
|
||||
else if (!strcasecmp(argv[i], "-transverse"))
|
||||
xform.op = TJXOP_TRANSVERSE;
|
||||
else if (!strcasecmp(argv[i], "-rot90"))
|
||||
xform.op = TJXOP_ROT90;
|
||||
else if (!strcasecmp(argv[i], "-rot180"))
|
||||
xform.op = TJXOP_ROT180;
|
||||
else if (!strcasecmp(argv[i], "-rot270"))
|
||||
xform.op = TJXOP_ROT270;
|
||||
else if (!strcasecmp(argv[i], "-custom"))
|
||||
xform.customFilter = customFilter;
|
||||
else if (!strncasecmp(argv[i], "-c", 2) && i < argc - 1) {
|
||||
if (sscanf(argv[++i], "%dx%d+%d+%d", &xform.r.w, &xform.r.h, &xform.r.x,
|
||||
&xform.r.y) < 4 ||
|
||||
xform.r.x < 0 || xform.r.y < 0 || xform.r.w < 1 || xform.r.h < 1)
|
||||
usage(argv[0]);
|
||||
xform.options |= TJXOPT_CROP;
|
||||
} else if (!strcasecmp(argv[i], "-fastupsample")) {
|
||||
printf("Using fast upsampling code\n");
|
||||
fastUpsample = 1;
|
||||
} else if (!strcasecmp(argv[i], "-fastdct")) {
|
||||
printf("Using fastest DCT/IDCT algorithm\n");
|
||||
fastDCT = 1;
|
||||
} else usage(argv[0]);
|
||||
}
|
||||
|
||||
/* Determine input and output image formats based on file extensions. */
|
||||
inFormat = strrchr(argv[1], '.');
|
||||
outFormat = strrchr(argv[2], '.');
|
||||
if (inFormat == NULL || outFormat == NULL || strlen(inFormat) < 2 ||
|
||||
strlen(outFormat) < 2)
|
||||
usage(argv[0]);
|
||||
inFormat = &inFormat[1];
|
||||
outFormat = &outFormat[1];
|
||||
|
||||
if ((tjInstance = tj3Init(TJINIT_TRANSFORM)) == NULL)
|
||||
THROW_TJ("creating TurboJPEG instance");
|
||||
|
||||
if (!strcasecmp(inFormat, "jpg")) {
|
||||
/* Input image is a JPEG image. Decompress and/or transform it. */
|
||||
long size;
|
||||
int inSubsamp, inColorspace;
|
||||
int doTransform = (xform.op != TJXOP_NONE || xform.options != 0 ||
|
||||
xform.customFilter != NULL);
|
||||
size_t jpegSize;
|
||||
|
||||
/* Read the JPEG file into memory. */
|
||||
if ((jpegFile = fopen(argv[1], "rb")) == NULL)
|
||||
THROW_UNIX("opening input file");
|
||||
if (fseek(jpegFile, 0, SEEK_END) < 0 || ((size = ftell(jpegFile)) < 0) ||
|
||||
fseek(jpegFile, 0, SEEK_SET) < 0)
|
||||
THROW_UNIX("determining input file size");
|
||||
if (size == 0)
|
||||
THROW("determining input file size", "Input file contains no data");
|
||||
jpegSize = size;
|
||||
if ((jpegBuf = tj3Alloc(jpegSize)) == NULL)
|
||||
THROW_UNIX("allocating JPEG buffer");
|
||||
if (fread(jpegBuf, jpegSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("reading input file");
|
||||
fclose(jpegFile); jpegFile = NULL;
|
||||
|
||||
if (doTransform) {
|
||||
/* Transform it. */
|
||||
unsigned char *dstBuf = NULL; /* Dynamically allocate the JPEG buffer */
|
||||
size_t dstSize = 0;
|
||||
|
||||
xform.options |= TJXOPT_TRIM;
|
||||
if (tj3Transform(tjInstance, jpegBuf, jpegSize, 1, &dstBuf, &dstSize,
|
||||
&xform) < 0) {
|
||||
tj3Free(dstBuf);
|
||||
THROW_TJ("transforming input image");
|
||||
}
|
||||
tj3Free(jpegBuf);
|
||||
jpegBuf = dstBuf;
|
||||
jpegSize = dstSize;
|
||||
}
|
||||
if (tj3Set(tjInstance, TJPARAM_FASTUPSAMPLE, fastUpsample) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTUPSAMPLE");
|
||||
if (tj3Set(tjInstance, TJPARAM_FASTDCT, fastDCT) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTDCT");
|
||||
|
||||
if (tj3DecompressHeader(tjInstance, jpegBuf, jpegSize) < 0)
|
||||
THROW_TJ("reading JPEG header");
|
||||
width = tj3Get(tjInstance, TJPARAM_JPEGWIDTH);
|
||||
height = tj3Get(tjInstance, TJPARAM_JPEGHEIGHT);
|
||||
inSubsamp = tj3Get(tjInstance, TJPARAM_SUBSAMP);
|
||||
inColorspace = tj3Get(tjInstance, TJPARAM_COLORSPACE);
|
||||
|
||||
if (tj3Get(tjInstance, TJPARAM_LOSSLESS))
|
||||
scalingFactor = TJUNSCALED;
|
||||
|
||||
printf("%s Image: %d x %d pixels, %s subsampling, %s colorspace\n",
|
||||
(doTransform ? "Transformed" : "Input"), width, height,
|
||||
subsampName[inSubsamp], colorspaceName[inColorspace]);
|
||||
|
||||
if (!strcasecmp(outFormat, "jpg") && doTransform &&
|
||||
scalingFactor.num == 1 && scalingFactor.denom == 1 && outSubsamp < 0 &&
|
||||
outQual < 0) {
|
||||
/* Input image has been transformed, and no re-compression options
|
||||
have been selected. Write the transformed image to disk and exit. */
|
||||
if ((jpegFile = fopen(argv[2], "wb")) == NULL)
|
||||
THROW_UNIX("opening output file");
|
||||
if (fwrite(jpegBuf, jpegSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("writing output file");
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
/* Scaling and/or a non-JPEG output image format and/or compression options
|
||||
have been selected, so we need to decompress the input/transformed
|
||||
image. */
|
||||
if (tj3SetScalingFactor(tjInstance, scalingFactor) < 0)
|
||||
THROW_TJ("setting scaling factor");
|
||||
width = TJSCALED(width, scalingFactor);
|
||||
height = TJSCALED(height, scalingFactor);
|
||||
if (outSubsamp < 0)
|
||||
outSubsamp = inSubsamp;
|
||||
|
||||
pixelFormat = TJPF_BGRX;
|
||||
#if ULLONG_MAX > SIZE_MAX
|
||||
if ((unsigned long long)width * height * tjPixelSize[pixelFormat] >
|
||||
(unsigned long long)((size_t)-1))
|
||||
THROW("allocating uncompressed image buffer", "Image is too large");
|
||||
#endif
|
||||
if ((imgBuf =
|
||||
(unsigned char *)malloc(sizeof(unsigned char) * width * height *
|
||||
tjPixelSize[pixelFormat])) == NULL)
|
||||
THROW_UNIX("allocating uncompressed image buffer");
|
||||
|
||||
if (tj3Decompress8(tjInstance, jpegBuf, jpegSize, imgBuf, 0,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("decompressing JPEG image");
|
||||
tj3Free(jpegBuf); jpegBuf = NULL;
|
||||
} else {
|
||||
/* Input image is not a JPEG image. Load it into memory. */
|
||||
if ((imgBuf = tj3LoadImage8(tjInstance, argv[1], &width, 1, &height,
|
||||
&pixelFormat)) == NULL)
|
||||
THROW_TJ("loading input image");
|
||||
if (outSubsamp < 0) {
|
||||
if (pixelFormat == TJPF_GRAY)
|
||||
outSubsamp = TJSAMP_GRAY;
|
||||
else
|
||||
outSubsamp = TJSAMP_444;
|
||||
}
|
||||
printf("Input Image: %d x %d pixels\n", width, height);
|
||||
}
|
||||
|
||||
printf("Output Image (%s): %d x %d pixels", outFormat, width, height);
|
||||
|
||||
if (!strcasecmp(outFormat, "jpg")) {
|
||||
/* Output image format is JPEG. Compress the uncompressed image. */
|
||||
size_t jpegSize = 0;
|
||||
|
||||
jpegBuf = NULL; /* Dynamically allocate the JPEG buffer */
|
||||
|
||||
if (outQual < 0)
|
||||
outQual = DEFAULT_QUALITY;
|
||||
printf(", %s subsampling, quality = %d\n", subsampName[outSubsamp],
|
||||
outQual);
|
||||
|
||||
if (tj3Set(tjInstance, TJPARAM_SUBSAMP, outSubsamp) < 0)
|
||||
THROW_TJ("setting TJPARAM_SUBSAMP");
|
||||
if (tj3Set(tjInstance, TJPARAM_QUALITY, outQual) < 0)
|
||||
THROW_TJ("setting TJPARAM_QUALITY");
|
||||
if (tj3Set(tjInstance, TJPARAM_FASTDCT, fastDCT) < 0)
|
||||
THROW_TJ("setting TJPARAM_FASTDCT");
|
||||
if (tj3Compress8(tjInstance, imgBuf, width, 0, height, pixelFormat,
|
||||
&jpegBuf, &jpegSize) < 0)
|
||||
THROW_TJ("compressing image");
|
||||
|
||||
/* Write the JPEG image to disk. */
|
||||
if ((jpegFile = fopen(argv[2], "wb")) == NULL)
|
||||
THROW_UNIX("opening output file");
|
||||
if (fwrite(jpegBuf, jpegSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("writing output file");
|
||||
} else {
|
||||
/* Output image format is not JPEG. Save the uncompressed image
|
||||
directly to disk. */
|
||||
printf("\n");
|
||||
if (tj3SaveImage8(tjInstance, argv[2], imgBuf, width, 0, height,
|
||||
pixelFormat) < 0)
|
||||
THROW_TJ("saving output image");
|
||||
}
|
||||
|
||||
bailout:
|
||||
tj3Free(imgBuf);
|
||||
tj3Destroy(tjInstance);
|
||||
tj3Free(jpegBuf);
|
||||
if (jpegFile) fclose(jpegFile);
|
||||
return retval;
|
||||
}
|
309
src/tjtran.c
Normal file
309
src/tjtran.c
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (C)2011-2012, 2014-2015, 2017, 2019, 2021-2024
|
||||
* D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - 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.
|
||||
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* 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 HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program demonstrates how to use the TurboJPEG C API to approximate the
|
||||
* functionality of the IJG's jpegtran program. jpegtran features that are not
|
||||
* covered:
|
||||
*
|
||||
* - Adding restart markers to the output image
|
||||
* - Scan scripts
|
||||
* - Expanding the input image when cropping
|
||||
* - Wiping a region of the input image
|
||||
* - Dropping another JPEG image into the input image
|
||||
* - Copying only comment markers or ICC profile markers
|
||||
* - Embedding an ICC color management profile
|
||||
* - Progress reporting
|
||||
* - Debug output
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_MSC_VER) || _MSC_VER > 1600
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <turbojpeg.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define MATCH_ARG(arg, string, minChars) \
|
||||
!strncasecmp(arg, string, max(strlen(arg), minChars))
|
||||
|
||||
#define IS_CROPPED(cr) (cr.x != 0 || cr.y != 0 || cr.w != 0 || cr.h != 0)
|
||||
|
||||
#define THROW(action, message) { \
|
||||
printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
|
||||
retval = -1; goto bailout; \
|
||||
}
|
||||
|
||||
#define THROW_TJ(action) { \
|
||||
int errorCode = tj3GetErrorCode(tjInstance); \
|
||||
printf("%s in line %d while %s:\n%s\n", \
|
||||
errorCode == TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, action, \
|
||||
tj3GetErrorStr(tjInstance)); \
|
||||
if (errorCode == TJERR_FATAL || stopOnWarning == 1) { \
|
||||
retval = -1; goto bailout; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define THROW_UNIX(action) THROW(action, strerror(errno))
|
||||
|
||||
|
||||
static void usage(char *programName)
|
||||
{
|
||||
printf("\nUSAGE: %s [options] <JPEG input image> <JPEG output image>\n\n",
|
||||
programName);
|
||||
|
||||
printf("This program reads the DCT coefficients from the lossy JPEG input image,\n");
|
||||
printf("optionally transforms them, and writes them to a lossy JPEG output image.\n\n");
|
||||
|
||||
printf("OPTIONS (CAN BE ABBREVBIATED)\n");
|
||||
printf("-----------------------------\n");
|
||||
printf("-arithmetic\n");
|
||||
printf(" Use arithmetic entropy coding in the output image instead of Huffman\n");
|
||||
printf(" entropy coding (can be combined with -progressive)\n");
|
||||
printf("-copy all\n");
|
||||
printf(" Copy all extra markers (including comments, JFIF thumbnails, Exif data, and\n");
|
||||
printf(" ICC profile data) from the input image to the output image [default]\n");
|
||||
printf("-copy none\n");
|
||||
printf(" Copy no extra markers from the input image to the output image\n");
|
||||
printf("-crop WxH+X+Y\n");
|
||||
printf(" Include only the specified region of the input image. (W, H, X, and Y are\n");
|
||||
printf(" the width, height, left boundary, and upper boundary of the region, all\n");
|
||||
printf(" specified relative to the transformed image dimensions.) If necessary, X\n");
|
||||
printf(" and Y will be shifted up and left to the nearest iMCU boundary, and W and H\n");
|
||||
printf(" will be increased accordingly.\n");
|
||||
printf("-flip {horizontal|vertical}, -rotate {90|180|270}, -transpose, -transverse\n");
|
||||
printf(" Perform the specified lossless transform operation (these options are\n");
|
||||
printf(" mutually exclusive)\n");
|
||||
printf("-grayscale\n");
|
||||
printf(" Create a grayscale output image from a full-color input image\n");
|
||||
printf("-maxmemory N\n");
|
||||
printf(" Memory limit (in megabytes) for intermediate buffers used with progressive\n");
|
||||
printf(" JPEG compression, Huffman table optimization, and lossless transformation\n");
|
||||
printf(" [default = no limit]\n");
|
||||
printf("-maxscans N\n");
|
||||
printf(" Refuse to transform progressive JPEG images that have more than N scans\n");
|
||||
printf("-optimize\n");
|
||||
printf(" Use Huffman table optimization in the output image\n");
|
||||
printf("-perfect\n");
|
||||
printf(" Abort if the requested transform operation is imperfect (non-reversible.)\n");
|
||||
printf(" '-flip horizontal', '-rotate 180', '-rotate 270', and '-transverse' are\n");
|
||||
printf(" imperfect if the image width is not evenly divisible by the iMCU width.\n");
|
||||
printf(" '-flip vertical', '-rotate 90', '-rotate 180', and '-transverse' are\n");
|
||||
printf(" imperfect if the image height is not evenly divisible by the iMCU height.\n");
|
||||
printf("-progressive\n");
|
||||
printf(" Create a progressive output image instead of a single-scan output image\n");
|
||||
printf(" (can be combined with -arithmetic; implies -optimize unless -arithmetic is\n");
|
||||
printf(" also specified)\n");
|
||||
printf("-strict\n");
|
||||
printf(" Treat all warnings as fatal; abort immediately if incomplete or corrupt\n");
|
||||
printf(" data is encountered in the input image, rather than trying to salvage the\n");
|
||||
printf(" rest of the image\n");
|
||||
printf("-trim\n");
|
||||
printf(" If necessary, trim the partial iMCUs at the right or bottom edge of the\n");
|
||||
printf(" image to make the requested transform perfect\n\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, retval = 0;
|
||||
int arithmetic = 0, maxMemory = -1, maxScans = -1, optimize = -1,
|
||||
progressive = 0, stopOnWarning = -1, subsamp;
|
||||
tjtransform xform;
|
||||
tjhandle tjInstance = NULL;
|
||||
FILE *jpegFile = NULL;
|
||||
long size = 0;
|
||||
size_t srcSize, dstSize;
|
||||
unsigned char *srcBuf = NULL, *dstBuf = NULL;
|
||||
|
||||
memset(&xform, 0, sizeof(tjtransform));
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (MATCH_ARG(argv[i], "-arithmetic", 2))
|
||||
arithmetic = 1;
|
||||
else if (MATCH_ARG(argv[i], "-crop", 3) && i < argc - 1) {
|
||||
char tempc = -1;
|
||||
|
||||
if (sscanf(argv[++i], "%d%c%d+%d+%d", &xform.r.w, &tempc, &xform.r.h,
|
||||
&xform.r.x, &xform.r.y) != 5 || xform.r.w < 1 ||
|
||||
(tempc != 'x' && tempc != 'X') || xform.r.h < 1 || xform.r.x < 0 ||
|
||||
xform.r.y < 0)
|
||||
usage(argv[0]);
|
||||
xform.options |= TJXOPT_CROP;
|
||||
} else if (MATCH_ARG(argv[i], "-copy", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "none", 1))
|
||||
xform.options |= TJXOPT_COPYNONE;
|
||||
else if (!MATCH_ARG(argv[i], "all", 1))
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-flip", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "horizontal", 1))
|
||||
xform.op = TJXOP_HFLIP;
|
||||
else if (MATCH_ARG(argv[i], "vertical", 1))
|
||||
xform.op = TJXOP_VFLIP;
|
||||
else
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-grayscale", 2) ||
|
||||
MATCH_ARG(argv[i], "-greyscale", 2))
|
||||
xform.options |= TJXOPT_GRAY;
|
||||
else if (MATCH_ARG(argv[i], "-maxscans", 5) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 0) usage(argv[0]);
|
||||
maxScans = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-maxmemory", 2) && i < argc - 1) {
|
||||
int tempi = atoi(argv[++i]);
|
||||
|
||||
if (tempi < 0) usage(argv[0]);
|
||||
maxMemory = tempi;
|
||||
} else if (MATCH_ARG(argv[i], "-optimize", 2) ||
|
||||
MATCH_ARG(argv[i], "-optimise", 2))
|
||||
optimize = 1;
|
||||
else if (MATCH_ARG(argv[i], "-perfect", 3))
|
||||
xform.options |= TJXOPT_PERFECT;
|
||||
else if (MATCH_ARG(argv[i], "-progressive", 2))
|
||||
progressive = 1;
|
||||
else if (MATCH_ARG(argv[i], "-rotate", 2) && i < argc - 1) {
|
||||
i++;
|
||||
if (MATCH_ARG(argv[i], "90", 2))
|
||||
xform.op = TJXOP_ROT90;
|
||||
else if (MATCH_ARG(argv[i], "180", 3))
|
||||
xform.op = TJXOP_ROT180;
|
||||
else if (MATCH_ARG(argv[i], "270", 3))
|
||||
xform.op = TJXOP_ROT270;
|
||||
else
|
||||
usage(argv[0]);
|
||||
} else if (MATCH_ARG(argv[i], "-strict", 2))
|
||||
stopOnWarning = 1;
|
||||
else if (MATCH_ARG(argv[i], "-transverse", 7))
|
||||
xform.op = TJXOP_TRANSVERSE;
|
||||
else if (MATCH_ARG(argv[i], "-trim", 4))
|
||||
xform.options |= TJXOPT_TRIM;
|
||||
else if (MATCH_ARG(argv[i], "-transpose", 2))
|
||||
xform.op = TJXOP_TRANSPOSE;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (i != argc - 2)
|
||||
usage(argv[0]);
|
||||
|
||||
if ((tjInstance = tj3Init(TJINIT_TRANSFORM)) == NULL)
|
||||
THROW_TJ("creating TurboJPEG instance");
|
||||
|
||||
if (stopOnWarning >= 0 &&
|
||||
tj3Set(tjInstance, TJPARAM_STOPONWARNING, stopOnWarning) < 0)
|
||||
THROW_TJ("setting TJPARAM_STOPONWARNING");
|
||||
if (optimize >= 0 && tj3Set(tjInstance, TJPARAM_OPTIMIZE, optimize) < 0)
|
||||
THROW_TJ("setting TJPARAM_OPTIMIZE");
|
||||
if (maxScans >= 0 && tj3Set(tjInstance, TJPARAM_SCANLIMIT, maxScans) < 0)
|
||||
THROW_TJ("setting TJPARAM_SCANLIMIT");
|
||||
if (maxMemory >= 0 && tj3Set(tjInstance, TJPARAM_MAXMEMORY, maxMemory) < 0)
|
||||
THROW_TJ("setting TJPARAM_MAXMEMORY");
|
||||
|
||||
if ((jpegFile = fopen(argv[i++], "rb")) == NULL)
|
||||
THROW_UNIX("opening input file");
|
||||
if (fseek(jpegFile, 0, SEEK_END) < 0 || ((size = ftell(jpegFile)) < 0) ||
|
||||
fseek(jpegFile, 0, SEEK_SET) < 0)
|
||||
THROW_UNIX("determining input file size");
|
||||
if (size == 0)
|
||||
THROW("determining input file size", "Input file contains no data");
|
||||
srcSize = size;
|
||||
if ((srcBuf = tj3Alloc(srcSize)) == NULL)
|
||||
THROW_UNIX("allocating JPEG buffer");
|
||||
if (fread(srcBuf, srcSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("reading input file");
|
||||
fclose(jpegFile); jpegFile = NULL;
|
||||
|
||||
if (tj3DecompressHeader(tjInstance, srcBuf, srcSize) < 0)
|
||||
THROW_TJ("reading JPEG header");
|
||||
subsamp = tj3Get(tjInstance, TJPARAM_SUBSAMP);
|
||||
if (xform.options & TJXOPT_GRAY)
|
||||
subsamp = TJSAMP_GRAY;
|
||||
|
||||
if (tj3Set(tjInstance, TJPARAM_PROGRESSIVE, progressive) < 0)
|
||||
THROW_TJ("setting TJPARAM_PROGRESSIVE");
|
||||
if (tj3Set(tjInstance, TJPARAM_ARITHMETIC, arithmetic) < 0)
|
||||
THROW_TJ("setting TJPARAM_ARITHMETIC");
|
||||
|
||||
if (IS_CROPPED(xform.r)) {
|
||||
int xAdjust, yAdjust;
|
||||
|
||||
if (subsamp == TJSAMP_UNKNOWN)
|
||||
THROW("adjusting cropping region",
|
||||
"Could not determine subsampling level of input image");
|
||||
if (xform.op == TJXOP_TRANSPOSE || xform.op == TJXOP_TRANSVERSE ||
|
||||
xform.op == TJXOP_ROT90 || xform.op == TJXOP_ROT270) {
|
||||
xAdjust = xform.r.x % tjMCUHeight[subsamp];
|
||||
yAdjust = xform.r.y % tjMCUWidth[subsamp];
|
||||
} else {
|
||||
xAdjust = xform.r.x % tjMCUWidth[subsamp];
|
||||
yAdjust = xform.r.y % tjMCUHeight[subsamp];
|
||||
}
|
||||
xform.r.x -= xAdjust;
|
||||
xform.r.w += xAdjust;
|
||||
xform.r.y -= yAdjust;
|
||||
xform.r.h += yAdjust;
|
||||
}
|
||||
|
||||
if (tj3Transform(tjInstance, srcBuf, srcSize, 1, &dstBuf, &dstSize,
|
||||
&xform) < 0)
|
||||
THROW_TJ("transforming input image");
|
||||
tj3Free(srcBuf); srcBuf = NULL;
|
||||
|
||||
if ((jpegFile = fopen(argv[i], "wb")) == NULL)
|
||||
THROW_UNIX("opening output file");
|
||||
if (fwrite(dstBuf, dstSize, 1, jpegFile) < 1)
|
||||
THROW_UNIX("writing output file");
|
||||
|
||||
bailout:
|
||||
tj3Destroy(tjInstance);
|
||||
tj3Free(srcBuf);
|
||||
if (jpegFile) fclose(jpegFile);
|
||||
tj3Free(dstBuf);
|
||||
return retval;
|
||||
}
|
183
test/tjcomptest.in
Executable file
183
test/tjcomptest.in
Executable file
@ -0,0 +1,183 @@
|
||||
#/bin/bash
|
||||
|
||||
set -u
|
||||
set -e
|
||||
trap onexit INT
|
||||
trap onexit TERM
|
||||
trap onexit EXIT
|
||||
|
||||
onexit()
|
||||
{
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
}
|
||||
|
||||
runme()
|
||||
{
|
||||
echo \*\*\* $*
|
||||
"$@"
|
||||
}
|
||||
|
||||
IMGDIR=@CMAKE_SOURCE_DIR@/testimages
|
||||
OUTDIR=`mktemp -d /tmp/__tjcomptest_output.XXXXXX`
|
||||
EXEDIR=@CMAKE_BINARY_DIR@
|
||||
JAVA="@Java_JAVA_EXECUTABLE@"
|
||||
JAVAARGS="-cp $EXEDIR/java/turbojpeg.jar -Djava.library.path=$EXEDIR"
|
||||
TJCOMP=$EXEDIR/tjcomp
|
||||
JAVAARG=
|
||||
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-java)
|
||||
JAVAARG=-java
|
||||
TJCOMP="$JAVA $JAVAARGS TJComp"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exec >$EXEDIR/tjcomptest$JAVAARG.log
|
||||
|
||||
SUBSAMPOPT=(444 422 440 420 411 441)
|
||||
SAMPOPT=(1x1 2x1 1x2 2x2 4x1 1x4)
|
||||
|
||||
for precision in 8 12; do
|
||||
if [ $precision -le 8 ]; then
|
||||
RGBIMG=$IMGDIR/testorig.ppm
|
||||
GRAYIMG=$IMGDIR/testorig.pgm
|
||||
else
|
||||
RGBIMG=$IMGDIR/big_building16.ppm
|
||||
GRAYIMG=$IMGDIR/big_building16.pgm
|
||||
fi
|
||||
for restartarg in "" "-r 1" "-r 1b"; do
|
||||
for ariarg in "" "-a"; do
|
||||
for dctarg in "" "-dc fa"; do
|
||||
for optarg in "" "-o"; do
|
||||
if [ "$optarg" = "-o" ]; then
|
||||
if [[ "$ariarg" = "-a" || $precision -eq 12 ]]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
for progarg in "" "-p"; do
|
||||
if [[ "$progarg" = "-p" && "$optarg" = "-o" ]]; then
|
||||
continue
|
||||
fi
|
||||
for qualarg in "" "-q 1" "-q 100"; do
|
||||
blarg=
|
||||
if [ "$qualarg" = "-q 1" ]; then
|
||||
blarg=-baseline
|
||||
fi
|
||||
for sampi in {0..5}; do
|
||||
basename=`basename $RGBIMG .ppm`
|
||||
runme $TJCOMP -pre $precision $restartarg $ariarg $dctarg \
|
||||
$optarg $progarg $qualarg -s ${SUBSAMPOPT[$sampi]} \
|
||||
$RGBIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision $restartarg $ariarg \
|
||||
$dctarg $optarg $progarg $qualarg $blarg \
|
||||
-sa ${SAMPOPT[$sampi]} \
|
||||
-outf $OUTDIR/${basename}-cjpeg.jpg $RGBIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
|
||||
runme $TJCOMP -pre $precision $restartarg $ariarg $dctarg \
|
||||
$optarg $progarg $qualarg -s ${SUBSAMPOPT[$sampi]} \
|
||||
-g $RGBIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision $restartarg $ariarg \
|
||||
$dctarg $optarg $progarg $qualarg $blarg \
|
||||
-sa ${SAMPOPT[$sampi]} \
|
||||
-gr -outf $OUTDIR/${basename}-cjpeg.jpg $RGBIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
|
||||
runme $TJCOMP -pre $precision $restartarg $ariarg $dctarg \
|
||||
$optarg $progarg $qualarg -s ${SUBSAMPOPT[$sampi]} \
|
||||
-rg $RGBIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision $restartarg $ariarg \
|
||||
$dctarg $optarg $progarg $qualarg $blarg \
|
||||
-sa ${SAMPOPT[$sampi]} \
|
||||
-rgb -outf $OUTDIR/${basename}-cjpeg.jpg $RGBIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
|
||||
basename=`basename $GRAYIMG .pgm`
|
||||
runme $TJCOMP -pre $precision $restartarg $ariarg $dctarg \
|
||||
$optarg $progarg $qualarg -s ${SUBSAMPOPT[$sampi]} \
|
||||
$GRAYIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision $restartarg $ariarg \
|
||||
$dctarg $optarg $progarg $qualarg $blarg \
|
||||
-sa ${SAMPOPT[$sampi]} \
|
||||
-outf $OUTDIR/${basename}-cjpeg.jpg $GRAYIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
for precision in {2..16}; do
|
||||
if [ $precision -le 8 ]; then
|
||||
RGBIMG=$IMGDIR/testorig.ppm
|
||||
GRAYIMG=$IMGDIR/testorig.pgm
|
||||
else
|
||||
RGBIMG=$IMGDIR/big_building16.ppm
|
||||
GRAYIMG=$IMGDIR/big_building16.pgm
|
||||
fi
|
||||
for psv in {1..7}; do
|
||||
for pt in {0..15}; do
|
||||
if [ $pt -ge $precision ]; then
|
||||
continue
|
||||
fi
|
||||
for restartarg in "" "-r 1"; do
|
||||
basename=`basename $RGBIMG .ppm`
|
||||
runme $TJCOMP -pre $precision -l $psv,$pt $restartarg \
|
||||
$RGBIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision -l $psv,$pt $restartarg \
|
||||
-outf $OUTDIR/${basename}-cjpeg.jpg $RGBIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
|
||||
basename=`basename $GRAYIMG .pgm`
|
||||
runme $TJCOMP -pre $precision -l $psv,$pt $restartarg \
|
||||
$GRAYIMG $OUTDIR/${basename}-tjcomp.jpg
|
||||
runme $EXEDIR/cjpeg -pre $precision -l $psv,$pt $restartarg \
|
||||
-outf $OUTDIR/${basename}-cjpeg.jpg $GRAYIMG
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjcomp.jpg \
|
||||
$OUTDIR/${basename}-cjpeg.jpg
|
||||
cmp $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
rm $OUTDIR/${basename}-tjcomp.jpg $OUTDIR/${basename}-cjpeg.jpg
|
||||
echo
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
echo "GREAT SUCCESS!"
|
200
test/tjdecomptest.in
Executable file
200
test/tjdecomptest.in
Executable file
@ -0,0 +1,200 @@
|
||||
#/bin/bash
|
||||
|
||||
set -u
|
||||
set -e
|
||||
trap onexit INT
|
||||
trap onexit TERM
|
||||
trap onexit EXIT
|
||||
|
||||
onexit()
|
||||
{
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
}
|
||||
|
||||
runme()
|
||||
{
|
||||
echo \*\*\* $*
|
||||
"$@"
|
||||
}
|
||||
|
||||
IMGDIR=@CMAKE_SOURCE_DIR@/testimages
|
||||
OUTDIR=`mktemp -d /tmp/__tjdecomptest_output.XXXXXX`
|
||||
EXEDIR=@CMAKE_BINARY_DIR@
|
||||
JAVA="@Java_JAVA_EXECUTABLE@"
|
||||
JAVAARGS="-cp $EXEDIR/java/turbojpeg.jar -Djava.library.path=$EXEDIR"
|
||||
TJDECOMP=$EXEDIR/tjdecomp
|
||||
JAVAARG=
|
||||
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-java)
|
||||
JAVAARG=-java
|
||||
TJDECOMP="$JAVA $JAVAARGS TJDecomp"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exec >$EXEDIR/tjdecomptest$JAVAARG.log
|
||||
|
||||
SUBSAMPOPT=(444 422 440 420 411 441 410)
|
||||
SAMPOPT=(1x1 2x1 1x2 2x2 4x1 1x4 4x2)
|
||||
|
||||
for precision in 8 12; do
|
||||
if [ $precision -le 8 ]; then
|
||||
RGBIMG=$IMGDIR/testorig.ppm
|
||||
GRAYIMG=$IMGDIR/testorig.pgm
|
||||
else
|
||||
RGBIMG=$IMGDIR/big_building16.ppm
|
||||
GRAYIMG=$IMGDIR/big_building16.pgm
|
||||
fi
|
||||
|
||||
for sampi in {0..6}; do
|
||||
runme $EXEDIR/cjpeg -pre $precision -sa ${SAMPOPT[$sampi]} \
|
||||
-outf $OUTDIR/`basename $RGBIMG .ppm`-${SUBSAMPOPT[$sampi]}.jpg $RGBIMG
|
||||
done
|
||||
runme $EXEDIR/cjpeg -pre $precision \
|
||||
-outf $OUTDIR/`basename $GRAYIMG .pgm`-gray.jpg $GRAYIMG
|
||||
echo
|
||||
|
||||
for subsamp in ${SUBSAMPOPT[*]} gray; do
|
||||
for croparg in "" "-cr 14x14+23+23" "-cr 21x21+4+4" "-cr 18x18+13+13" \
|
||||
"-cr 21x21+0+0" "-cr 24x26+20+18"; do
|
||||
if [[ "$croparg" != "" && "$subsamp" = "410" ]]; then
|
||||
continue
|
||||
fi
|
||||
for scalearg in "" "-s 16/8" "-s 15/8" "-s 14/8" "-s 13/8" "-s 12/8" \
|
||||
"-s 11/8" "-s 10/8" "-s 9/8" "-s 7/8" "-s 6/8" "-s 5/8" "-s 4/8" \
|
||||
"-s 3/8" "-s 2/8" "-s 1/8"; do
|
||||
if [[ ("$scalearg" = "-s 1/8" || "$scalearg" = "-s 2/8" || \
|
||||
"$scalearg" = "-s 3/8") && "$croparg" != "" ]]; then
|
||||
continue
|
||||
fi
|
||||
for nsarg in "" "-nos"; do
|
||||
if [[ "$nsarg" = "-nos" && "$subsamp" != "422" && \
|
||||
"$subsamp" != "420" && "$subsamp" != "440" ]]; then
|
||||
continue
|
||||
fi
|
||||
for dctarg in "" "-dc fa"; do
|
||||
if [[ "$dctarg" = "-dc fa" && \
|
||||
("$scalearg" != "-s 4/8" || \
|
||||
("$subsamp" != "420" && "$subsamp" != "410")) && \
|
||||
"$scalearg" != "" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [ "$subsamp" = "gray" ]; then
|
||||
basename=`basename $GRAYIMG .pgm`
|
||||
runme $TJDECOMP $croparg $dctarg $nsarg $scalearg \
|
||||
$OUTDIR/${basename}-$subsamp.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.pgm
|
||||
runme $EXEDIR/djpeg $croparg $dctarg $nsarg $scalearg \
|
||||
-outf $OUTDIR/${basename}-djpeg.pgm \
|
||||
$OUTDIR/${basename}-$subsamp.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
rm $OUTDIR/${basename}-tjdecomp.pgm $OUTDIR/${basename}-djpeg.pgm
|
||||
echo
|
||||
|
||||
runme $TJDECOMP $croparg $dctarg $nsarg $scalearg \
|
||||
-r $OUTDIR/${basename}-$subsamp.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.ppm
|
||||
runme $EXEDIR/djpeg $croparg $dctarg $nsarg $scalearg \
|
||||
-rg -outf $OUTDIR/${basename}-djpeg.ppm \
|
||||
$OUTDIR/${basename}-$subsamp.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.ppm \
|
||||
$OUTDIR/${basename}-djpeg.ppm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.ppm \
|
||||
$OUTDIR/${basename}-djpeg.ppm
|
||||
rm $OUTDIR/${basename}-tjdecomp.ppm $OUTDIR/${basename}-djpeg.ppm
|
||||
echo
|
||||
else
|
||||
basename=`basename $RGBIMG .ppm`
|
||||
runme $TJDECOMP $croparg $dctarg $nsarg $scalearg \
|
||||
$OUTDIR/${basename}-$subsamp.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.ppm
|
||||
runme $EXEDIR/djpeg $croparg $dctarg $nsarg $scalearg \
|
||||
-outf $OUTDIR/${basename}-djpeg.ppm \
|
||||
$OUTDIR/${basename}-$subsamp.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.ppm \
|
||||
$OUTDIR/${basename}-djpeg.ppm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.ppm \
|
||||
$OUTDIR/${basename}-djpeg.ppm
|
||||
rm $OUTDIR/${basename}-tjdecomp.ppm $OUTDIR/${basename}-djpeg.ppm
|
||||
echo
|
||||
|
||||
if [[ "$nsarg" = "" ]]; then
|
||||
runme $TJDECOMP $croparg $dctarg $nsarg $scalearg \
|
||||
-g $OUTDIR/${basename}-$subsamp.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.pgm
|
||||
runme $EXEDIR/djpeg $croparg $dctarg $nsarg $scalearg \
|
||||
-gr -outf $OUTDIR/${basename}-djpeg.pgm \
|
||||
$OUTDIR/${basename}-$subsamp.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
rm $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
rm $OUTDIR/${basename}-$subsamp.jpg
|
||||
done
|
||||
done
|
||||
|
||||
for precision in {2..16}; do
|
||||
if [ $precision -le 8 ]; then
|
||||
RGBIMG=$IMGDIR/testorig.ppm
|
||||
GRAYIMG=$IMGDIR/testorig.pgm
|
||||
else
|
||||
RGBIMG=$IMGDIR/big_building16.ppm
|
||||
GRAYIMG=$IMGDIR/big_building16.pgm
|
||||
fi
|
||||
|
||||
basename=`basename $RGBIMG .ppm`
|
||||
runme $EXEDIR/cjpeg -pre $precision -l 1 \
|
||||
-outf $OUTDIR/${basename}-rgb.jpg $RGBIMG
|
||||
echo
|
||||
|
||||
runme $TJDECOMP $OUTDIR/${basename}-rgb.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.ppm
|
||||
runme $EXEDIR/djpeg -outf $OUTDIR/${basename}-djpeg.ppm \
|
||||
$OUTDIR/${basename}-rgb.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.ppm \
|
||||
$OUTDIR/${basename}-djpeg.ppm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.ppm $OUTDIR/${basename}-djpeg.ppm
|
||||
rm $OUTDIR/${basename}-tjdecomp.ppm $OUTDIR/${basename}-djpeg.ppm
|
||||
rm $OUTDIR/${basename}-rgb.jpg
|
||||
echo
|
||||
|
||||
basename=`basename $GRAYIMG .pgm`
|
||||
runme $EXEDIR/cjpeg -pre $precision -l 1 \
|
||||
-outf $OUTDIR/${basename}-gray.jpg $GRAYIMG
|
||||
echo
|
||||
|
||||
runme $TJDECOMP $OUTDIR/${basename}-gray.jpg \
|
||||
$OUTDIR/${basename}-tjdecomp.pgm
|
||||
runme $EXEDIR/djpeg -outf $OUTDIR/${basename}-djpeg.pgm \
|
||||
$OUTDIR/${basename}-gray.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjdecomp.pgm \
|
||||
$OUTDIR/${basename}-djpeg.pgm
|
||||
cmp $OUTDIR/${basename}-tjdecomp.pgm $OUTDIR/${basename}-djpeg.pgm
|
||||
rm $OUTDIR/${basename}-tjdecomp.pgm $OUTDIR/${basename}-djpeg.pgm
|
||||
rm $OUTDIR/${basename}-gray.jpg
|
||||
echo
|
||||
done
|
||||
|
||||
echo "GREAT SUCCESS!"
|
@ -1,186 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -u
|
||||
set -e
|
||||
trap onexit INT
|
||||
trap onexit TERM
|
||||
trap onexit EXIT
|
||||
|
||||
onexit()
|
||||
{
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
}
|
||||
|
||||
runme()
|
||||
{
|
||||
echo \*\*\* $*
|
||||
$*
|
||||
}
|
||||
|
||||
IMAGES="vgl_5674_0098.bmp vgl_6434_0018a.bmp vgl_6548_0026a.bmp big_tree8.bmp"
|
||||
IMGDIR=@CMAKE_SOURCE_DIR@/testimages
|
||||
OUTDIR=`mktemp -d /tmp/__tjexampletest_output.XXXXXX`
|
||||
EXEDIR=@CMAKE_BINARY_DIR@
|
||||
JAVA="@Java_JAVA_EXECUTABLE@"
|
||||
JAVAARGS="-cp $EXEDIR/java/turbojpeg.jar -Djava.library.path=$EXEDIR"
|
||||
TJEXAMPLE=$EXEDIR/tjexample
|
||||
JAVAARG=
|
||||
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-java)
|
||||
JAVAARG=-java
|
||||
TJEXAMPLE="$JAVA $JAVAARGS TJExample"
|
||||
# The Java version of TJExample can't currently handle pixel density
|
||||
# information, so it fails on big_tree8.bmp.
|
||||
IMAGES="vgl_5674_0098.bmp vgl_6434_0018a.bmp vgl_6548_0026a.bmp"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exec >$EXEDIR/tjexampletest$JAVAARG.log
|
||||
|
||||
for image in $IMAGES; do
|
||||
|
||||
cp $IMGDIR/$image $OUTDIR
|
||||
basename=`basename $image .bmp`
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -grayscale -outfile $OUTDIR/${basename}_GRAY_fast_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x2 -outfile $OUTDIR/${basename}_420_fast_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x1 -outfile $OUTDIR/${basename}_422_fast_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 1x1 -outfile $OUTDIR/${basename}_444_fast_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -grayscale -outfile $OUTDIR/${basename}_GRAY_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x2 -outfile $OUTDIR/${basename}_420_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x1 -outfile $OUTDIR/${basename}_422_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 1x1 -outfile $OUTDIR/${basename}_444_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $EXEDIR/djpeg -dct fast -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_fast_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
|
||||
runme $EXEDIR/djpeg -dct int -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_accurate_djpeg.bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg
|
||||
done
|
||||
for samp in 420 422; do
|
||||
runme $EXEDIR/djpeg -dct fast -nosmooth -bmp -outfile $OUTDIR/${basename}_${samp}_fast_nosmooth_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
|
||||
runme $EXEDIR/djpeg -dct int -nosmooth -bmp -outfile $OUTDIR/${basename}_${samp}_accurate_nosmooth_djpeg.bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg
|
||||
done
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -grayscale -outfile $OUTDIR/${basename}_GRAY_fast_cjpeg2.jpg $OUTDIR/${basename}_GRAY_fast_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x2 -outfile $OUTDIR/${basename}_420_fast_cjpeg2.jpg $OUTDIR/${basename}_420_fast_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x1 -outfile $OUTDIR/${basename}_422_fast_cjpeg2.jpg $OUTDIR/${basename}_422_fast_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 1x1 -outfile $OUTDIR/${basename}_444_fast_cjpeg2.jpg $OUTDIR/${basename}_444_fast_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -grayscale -outfile $OUTDIR/${basename}_GRAY_accurate_cjpeg2.jpg $OUTDIR/${basename}_GRAY_accurate_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x2 -outfile $OUTDIR/${basename}_420_accurate_cjpeg2.jpg $OUTDIR/${basename}_420_accurate_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x1 -outfile $OUTDIR/${basename}_422_accurate_cjpeg2.jpg $OUTDIR/${basename}_422_accurate_djpeg.bmp
|
||||
runme $EXEDIR/cjpeg -quality 95 -dct int -sample 1x1 -outfile $OUTDIR/${basename}_444_accurate_cjpeg2.jpg $OUTDIR/${basename}_444_accurate_djpeg.bmp
|
||||
|
||||
# Compression
|
||||
for dct in fast accurate; do
|
||||
dctarg=
|
||||
if [ "${dct}" = "fast" ]; then
|
||||
dctarg=-fastdct
|
||||
fi
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $TJEXAMPLE $OUTDIR/$image $OUTDIR/${basename}_${samp}_${dct}.jpg -q 95 -subsamp ${samp} ${dctarg}
|
||||
runme cmp $OUTDIR/${basename}_${samp}_${dct}.jpg $OUTDIR/${basename}_${samp}_${dct}_cjpeg.jpg
|
||||
done
|
||||
done
|
||||
|
||||
# Recompression
|
||||
for dct in fast accurate; do
|
||||
dctarg=
|
||||
if [ "${dct}" = "fast" ]; then
|
||||
dctarg=-fastdct
|
||||
fi
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_${dct}.jpg $OUTDIR/${basename}_${samp}_${dct}_recomp.jpg -q 95 -subsamp ${samp} ${dctarg}
|
||||
runme cmp $OUTDIR/${basename}_${samp}_${dct}_recomp.jpg $OUTDIR/${basename}_${samp}_${dct}_cjpeg2.jpg
|
||||
done
|
||||
done
|
||||
|
||||
# Decompression
|
||||
for dct in fast accurate; do
|
||||
dctarg=
|
||||
if [ "${dct}" = "fast" ]; then
|
||||
dctarg=-fastdct
|
||||
fi
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_${dct}.jpg $OUTDIR/${basename}_${samp}_${dct}.bmp ${dctarg}
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${dct}.bmp $OUTDIR/${basename}_${samp}_${dct}_djpeg.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${dct}.bmp
|
||||
done
|
||||
for samp in 420 422; do
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_${dct}.jpg $OUTDIR/${basename}_${samp}_${dct}_nosmooth.bmp -fastupsample ${dctarg}
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${dct}_nosmooth.bmp $OUTDIR/${basename}_${samp}_${dct}_nosmooth_djpeg.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${dct}_nosmooth.bmp
|
||||
done
|
||||
done
|
||||
|
||||
# Scaled decompression
|
||||
for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do
|
||||
scalearg=`echo $scale | sed 's/\_/\//g'`
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} -outfile $OUTDIR/${basename}_${samp}_${scale}_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${scale}.bmp -scale ${scalearg}
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${scale}.bmp $OUTDIR/${basename}_${samp}_${scale}_djpeg.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${scale}.bmp
|
||||
done
|
||||
done
|
||||
|
||||
# Transforms
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -flip horizontal -trim -outfile $OUTDIR/${basename}_${samp}_hflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -flip vertical -trim -outfile $OUTDIR/${basename}_${samp}_vflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -transpose -trim -outfile $OUTDIR/${basename}_${samp}_transpose_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -transverse -trim -outfile $OUTDIR/${basename}_${samp}_transverse_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 90 -trim -outfile $OUTDIR/${basename}_${samp}_rot90_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 180 -trim -outfile $OUTDIR/${basename}_${samp}_rot180_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 270 -trim -outfile $OUTDIR/${basename}_${samp}_rot270_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg
|
||||
done
|
||||
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
|
||||
for samp in GRAY 420 422 444; do
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.jpg -$xform -crop 70x60+16+16
|
||||
runme cmp $OUTDIR/${basename}_${samp}_${xform}.jpg $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
|
||||
runme $EXEDIR/djpeg -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.bmp -$xform -crop 70x60+16+16
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${xform}.bmp
|
||||
done
|
||||
for samp in 420 422; do
|
||||
runme $EXEDIR/djpeg -nosmooth -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.bmp -$xform -crop 70x60+16+16 -fastupsample
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${xform}.bmp
|
||||
done
|
||||
done
|
||||
|
||||
# Grayscale transform
|
||||
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
|
||||
for samp in GRAY 444 422 420; do
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.jpg -$xform -grayscale -crop 70x60+16+16
|
||||
runme cmp $OUTDIR/${basename}_${samp}_${xform}.jpg $OUTDIR/${basename}_GRAY_${xform}_jpegtran.jpg
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.bmp -$xform -grayscale -crop 70x60+16+16
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}.bmp $OUTDIR/${basename}_GRAY_${xform}_jpegtran.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${xform}.bmp
|
||||
done
|
||||
done
|
||||
|
||||
# Transforms with scaling
|
||||
for xform in hflip vflip transpose transverse rot90 rot180 rot270; do
|
||||
for samp in GRAY 444 422 420; do
|
||||
for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do
|
||||
scalearg=`echo $scale | sed 's/\_/\//g'`
|
||||
runme $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} -outfile $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg
|
||||
runme $TJEXAMPLE $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp -$xform -scale ${scalearg} -crop 70x60+16+16
|
||||
runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.bmp
|
||||
rm $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
done
|
||||
|
||||
echo SUCCESS!
|
153
test/tjtrantest.in
Executable file
153
test/tjtrantest.in
Executable file
@ -0,0 +1,153 @@
|
||||
#/bin/bash
|
||||
|
||||
set -u
|
||||
set -e
|
||||
trap onexit INT
|
||||
trap onexit TERM
|
||||
trap onexit EXIT
|
||||
|
||||
onexit()
|
||||
{
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
}
|
||||
|
||||
runme()
|
||||
{
|
||||
echo \*\*\* $*
|
||||
"$@"
|
||||
}
|
||||
|
||||
IMGDIR=@CMAKE_SOURCE_DIR@/testimages
|
||||
OUTDIR=`mktemp -d /tmp/__tjtrantest_output.XXXXXX`
|
||||
EXEDIR=@CMAKE_BINARY_DIR@
|
||||
JAVA="@Java_JAVA_EXECUTABLE@"
|
||||
JAVAARGS="-cp $EXEDIR/java/turbojpeg.jar -Djava.library.path=$EXEDIR"
|
||||
TJTRAN=$EXEDIR/tjtran
|
||||
JAVAARG=
|
||||
|
||||
if [ -d $OUTDIR ]; then
|
||||
rm -rf $OUTDIR
|
||||
fi
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-java)
|
||||
JAVAARG=-java
|
||||
TJTRAN="$JAVA $JAVAARGS TJTran"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exec >$EXEDIR/tjtrantest$JAVAARG.log
|
||||
|
||||
SUBSAMPOPT=(444 422 440 420 411 441 410)
|
||||
SAMPOPT=(1x1 2x1 1x2 2x2 4x1 1x4 4x2)
|
||||
|
||||
for precision in 8 12; do
|
||||
if [ $precision -le 8 ]; then
|
||||
RGBIMG=$IMGDIR/testorig.ppm
|
||||
GRAYIMG=$IMGDIR/testorig.pgm
|
||||
else
|
||||
RGBIMG=$IMGDIR/big_building16.ppm
|
||||
GRAYIMG=$IMGDIR/big_building16.pgm
|
||||
fi
|
||||
|
||||
for sampi in {0..6}; do
|
||||
EXTRA_ARGS=
|
||||
if [ $sampi = 1 ]; then
|
||||
EXTRA_ARGS=-p
|
||||
elif [ $sampi = 2 ]; then
|
||||
EXTRA_ARGS=-a
|
||||
elif [ $sampi = 3 ]; then
|
||||
EXTRA_ARGS=-o
|
||||
fi
|
||||
runme $EXEDIR/cjpeg -pre $precision -sa ${SAMPOPT[$sampi]} $EXTRA_ARGS \
|
||||
-outf $OUTDIR/`basename $RGBIMG .ppm`-${SUBSAMPOPT[$sampi]}.jpg $RGBIMG
|
||||
if [ $sampi = 4 ]; then
|
||||
$EXEDIR/wrjpgcom -comment "This is a test" \
|
||||
$OUTDIR/`basename $RGBIMG .ppm`-${SUBSAMPOPT[$sampi]}.jpg \
|
||||
>$OUTDIR/temp.jpg
|
||||
mv $OUTDIR/temp.jpg \
|
||||
$OUTDIR/`basename $RGBIMG .ppm`-${SUBSAMPOPT[$sampi]}.jpg
|
||||
fi
|
||||
done
|
||||
runme $EXEDIR/cjpeg -pre $precision \
|
||||
-outf $OUTDIR/`basename $GRAYIMG .pgm`-gray.jpg $GRAYIMG
|
||||
echo
|
||||
|
||||
for subsamp in ${SUBSAMPOPT[*]} gray; do
|
||||
if [ "$subsamp" = "gray" ]; then
|
||||
basename=`basename $GRAYIMG .pgm`
|
||||
else
|
||||
basename=`basename $RGBIMG .ppm`
|
||||
fi
|
||||
for ariarg in "" "-a"; do
|
||||
for copyarg in "" "-c n"; do
|
||||
if [[ "$copyarg" = "-c n" && "$subsamp" != "411" ]]; then
|
||||
continue
|
||||
fi
|
||||
for croparg in "" "-cr 14x14+23+23" "-cr 21x21+4+4" "-cr 18x18+13+13" \
|
||||
"-cr 21x21+0+0" "-cr 24x26+20+18"; do
|
||||
for xformarg in "" "-f h" "-f v" "-ro 90" "-ro 180" "-ro 270" "-t" \
|
||||
"-transv"; do
|
||||
for grayarg in "" "-g"; do
|
||||
if [ "$grayarg" = "" ]; then
|
||||
if [[ "$subsamp" = "410" && "$croparg" != "" ]]; then
|
||||
continue
|
||||
fi
|
||||
else
|
||||
if [ "$subsamp" = "gray" ]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
for optarg in "" "-o"; do
|
||||
if [ "$optarg" = "-o" ]; then
|
||||
if [[ "$ariarg" = "-a" || $precision -eq 12 ]]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
for progarg in "" "-p"; do
|
||||
if [[ "$progarg" = "-p" && "$optarg" = "-o" ]]; then
|
||||
continue
|
||||
fi
|
||||
for trimarg in "" "-tri"; do
|
||||
if [ "$trimarg" = "-tri" ]; then
|
||||
if [[ "$xformarg" = "-t" || "$xformarg" = "" ]]; then
|
||||
continue
|
||||
fi
|
||||
if [ "$croparg" != "" ]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
runme $TJTRAN $ariarg $copyarg $croparg $xformarg \
|
||||
$grayarg $optarg $progarg $trimarg \
|
||||
$OUTDIR/${basename}-$subsamp.jpg \
|
||||
$OUTDIR/${basename}-tjtran.jpg
|
||||
runme $EXEDIR/jpegtran $ariarg $copyarg $croparg \
|
||||
$xformarg $grayarg $optarg $progarg $trimarg \
|
||||
-outf $OUTDIR/${basename}-jpegtran.jpg \
|
||||
$OUTDIR/${basename}-$subsamp.jpg
|
||||
$EXEDIR/src/md5/md5sum $OUTDIR/${basename}-tjtran.jpg \
|
||||
$OUTDIR/${basename}-jpegtran.jpg
|
||||
cmp $OUTDIR/${basename}-tjtran.jpg \
|
||||
$OUTDIR/${basename}-jpegtran.jpg
|
||||
rm $OUTDIR/${basename}-tjtran.jpg \
|
||||
$OUTDIR/${basename}-jpegtran.jpg
|
||||
echo
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
rm $OUTDIR/${basename}-$subsamp.jpg
|
||||
done
|
||||
done
|
||||
|
||||
echo "GREAT SUCCESS!"
|
BIN
testimages/big_building16.pgm
Normal file
BIN
testimages/big_building16.pgm
Normal file
Binary file not shown.
4
testimages/testorig.pgm
Normal file
4
testimages/testorig.pgm
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user