|
shun-iwasawa |
82a8f5 |
/*
|
|
shun-iwasawa |
82a8f5 |
* Copyright (C)2011-2012, 2014-2015, 2017-2018 D. R. Commander.
|
|
shun-iwasawa |
82a8f5 |
* All Rights Reserved.
|
|
shun-iwasawa |
82a8f5 |
*
|
|
shun-iwasawa |
82a8f5 |
* Redistribution and use in source and binary forms, with or without
|
|
shun-iwasawa |
82a8f5 |
* modification, are permitted provided that the following conditions are met:
|
|
shun-iwasawa |
82a8f5 |
*
|
|
shun-iwasawa |
82a8f5 |
* - Redistributions of source code must retain the above copyright notice,
|
|
shun-iwasawa |
82a8f5 |
* this list of conditions and the following disclaimer.
|
|
shun-iwasawa |
82a8f5 |
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
shun-iwasawa |
82a8f5 |
* this list of conditions and the following disclaimer in the documentation
|
|
shun-iwasawa |
82a8f5 |
* and/or other materials provided with the distribution.
|
|
shun-iwasawa |
82a8f5 |
* - Neither the name of the libjpeg-turbo Project nor the names of its
|
|
shun-iwasawa |
82a8f5 |
* contributors may be used to endorse or promote products derived from this
|
|
shun-iwasawa |
82a8f5 |
* software without specific prior written permission.
|
|
shun-iwasawa |
82a8f5 |
*
|
|
shun-iwasawa |
82a8f5 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
|
|
shun-iwasawa |
82a8f5 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
shun-iwasawa |
82a8f5 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
shun-iwasawa |
82a8f5 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
|
shun-iwasawa |
82a8f5 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
shun-iwasawa |
82a8f5 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
shun-iwasawa |
82a8f5 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
shun-iwasawa |
82a8f5 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
shun-iwasawa |
82a8f5 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
shun-iwasawa |
82a8f5 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
shun-iwasawa |
82a8f5 |
* POSSIBILITY OF SUCH DAMAGE.
|
|
shun-iwasawa |
82a8f5 |
*/
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/*
|
|
shun-iwasawa |
82a8f5 |
* This program demonstrates how to compress, decompress, and transform JPEG
|
|
shun-iwasawa |
82a8f5 |
* images using the TurboJPEG Java API
|
|
shun-iwasawa |
82a8f5 |
*/
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
import java.io.*;
|
|
shun-iwasawa |
82a8f5 |
import java.awt.*;
|
|
shun-iwasawa |
82a8f5 |
import java.awt.image.*;
|
|
shun-iwasawa |
82a8f5 |
import java.nio.*;
|
|
shun-iwasawa |
82a8f5 |
import javax.imageio.*;
|
|
shun-iwasawa |
82a8f5 |
import javax.swing.*;
|
|
shun-iwasawa |
82a8f5 |
import org.libjpegturbo.turbojpeg.*;
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
@SuppressWarnings("checkstyle:JavadocType")
|
|
shun-iwasawa |
82a8f5 |
class TJExample implements TJCustomFilter {
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static final String CLASS_NAME =
|
|
shun-iwasawa |
82a8f5 |
new TJExample().getClass().getName();
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static final int DEFAULT_SUBSAMP = TJ.SAMP_444;
|
|
shun-iwasawa |
82a8f5 |
static final int DEFAULT_QUALITY = 95;
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static final String[] SUBSAMP_NAME = {
|
|
shun-iwasawa |
82a8f5 |
"4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1"
|
|
shun-iwasawa |
82a8f5 |
};
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static final String[] COLORSPACE_NAME = {
|
|
shun-iwasawa |
82a8f5 |
"RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
|
|
shun-iwasawa |
82a8f5 |
};
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* DCT filter example. This produces a negative of the image. */
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
@SuppressWarnings("checkstyle:JavadocMethod")
|
|
shun-iwasawa |
82a8f5 |
public void customFilter(ShortBuffer coeffBuffer, Rectangle bufferRegion,
|
|
shun-iwasawa |
82a8f5 |
Rectangle planeRegion, int componentIndex,
|
|
shun-iwasawa |
82a8f5 |
int transformIndex, TJTransform transform)
|
|
shun-iwasawa |
82a8f5 |
throws TJException {
|
|
shun-iwasawa |
82a8f5 |
for (int i = 0; i < bufferRegion.width * bufferRegion.height; i++) {
|
|
shun-iwasawa |
82a8f5 |
coeffBuffer.put(i, (short)(-coeffBuffer.get(i)));
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static void usage() throws Exception {
|
|
shun-iwasawa |
82a8f5 |
System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
|
|
shun-iwasawa |
82a8f5 |
" <input image=""> <output image=""> [options]\n");</output>
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Input and output images can be in any image format that the Java Image I/O");
|
|
shun-iwasawa |
82a8f5 |
System.out.println("extensions understand. If either filename ends in a .jpg extension, then");
|
|
shun-iwasawa |
82a8f5 |
System.out.println("the TurboJPEG API will be used to compress or decompress the image.\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Compression Options (used if the output image is a JPEG image)");
|
|
shun-iwasawa |
82a8f5 |
System.out.println("--------------------------------------------------------------\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-subsamp <444|422|420|gray> = Apply this level of chrominance subsampling when");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" compressing the output image. The default is to use the same level of");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" subsampling as in the input image, if the input image is also a JPEG");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" image, or to use grayscale if the input image is a grayscale non-JPEG");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" image, or to use " +
|
|
shun-iwasawa |
82a8f5 |
SUBSAMP_NAME[DEFAULT_SUBSAMP] +
|
|
shun-iwasawa |
82a8f5 |
" subsampling otherwise.\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-q <1-100> = Compress the output image with this JPEG quality level");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" (default = " + DEFAULT_QUALITY + ").\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Decompression Options (used if the input image is a JPEG image)");
|
|
shun-iwasawa |
82a8f5 |
System.out.println("---------------------------------------------------------------\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-scale M/N = Scale the input image by a factor of M/N when decompressing it.");
|
|
shun-iwasawa |
82a8f5 |
System.out.print("(M/N = ");
|
|
shun-iwasawa |
82a8f5 |
for (int i = 0; i < SCALING_FACTORS.length; i++) {
|
|
shun-iwasawa |
82a8f5 |
System.out.print(SCALING_FACTORS[i].getNum() + "/" +
|
|
shun-iwasawa |
82a8f5 |
SCALING_FACTORS[i].getDenom());
|
|
shun-iwasawa |
82a8f5 |
if (SCALING_FACTORS.length == 2 && i != SCALING_FACTORS.length - 1)
|
|
shun-iwasawa |
82a8f5 |
System.out.print(" or ");
|
|
shun-iwasawa |
82a8f5 |
else if (SCALING_FACTORS.length > 2) {
|
|
shun-iwasawa |
82a8f5 |
if (i != SCALING_FACTORS.length - 1)
|
|
shun-iwasawa |
82a8f5 |
System.out.print(", ");
|
|
shun-iwasawa |
82a8f5 |
if (i == SCALING_FACTORS.length - 2)
|
|
shun-iwasawa |
82a8f5 |
System.out.print("or ");
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
System.out.println(")\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" Perform one of these lossless transform operations on the input image");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" prior to decompressing it (these options are mutually exclusive.)\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-grayscale = Perform lossless grayscale conversion on the input image prior");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" to decompressing it (can be combined with the other transform operations");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" above.)\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-crop WxH+X+Y = Perform lossless cropping on the input image prior to");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" decompressing it. X and Y specify the upper left corner of the cropping");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" region, and W and H specify the width and height of the cropping region.");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" X and Y must be evenly divible by the MCU block size (8x8 if the input");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" image was compressed using no subsampling or grayscale, 16x8 if it was");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" compressed using 4:2:2 subsampling, or 16x16 if it was compressed using");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" 4:2:0 subsampling.)\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("General Options");
|
|
shun-iwasawa |
82a8f5 |
System.out.println("---------------\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-display = Display output image (Output filename need not be specified in this");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" case.)\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-fastupsample = Use the fastest chrominance upsampling algorithm available in");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" the underlying codec.\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-fastdct = Use the fastest DCT/IDCT algorithms available in the underlying");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" codec.\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the");
|
|
shun-iwasawa |
82a8f5 |
System.out.println(" underlying codec.\n");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.exit(1);
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
public static void main(String[] argv) {
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
try {
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
TJScalingFactor scalingFactor = new TJScalingFactor(1, 1);
|
|
shun-iwasawa |
82a8f5 |
int outSubsamp = -1, outQual = -1;
|
|
shun-iwasawa |
82a8f5 |
TJTransform xform = new TJTransform();
|
|
shun-iwasawa |
82a8f5 |
boolean display = false;
|
|
shun-iwasawa |
82a8f5 |
int flags = 0;
|
|
shun-iwasawa |
82a8f5 |
int width, height;
|
|
shun-iwasawa |
82a8f5 |
String inFormat = "jpg", outFormat = "jpg";
|
|
shun-iwasawa |
82a8f5 |
BufferedImage img = null;
|
|
shun-iwasawa |
82a8f5 |
byte[] imgBuf = null;
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (argv.length < 2)
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (argv[1].substring(0, 2).equalsIgnoreCase("-d"))
|
|
shun-iwasawa |
82a8f5 |
display = true;
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* Parse arguments. */
|
|
shun-iwasawa |
82a8f5 |
for (int i = 2; i < argv.length; i++) {
|
|
shun-iwasawa |
82a8f5 |
if (argv[i].length() < 2)
|
|
shun-iwasawa |
82a8f5 |
continue;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].length() > 2 &&
|
|
shun-iwasawa |
82a8f5 |
argv[i].substring(0, 3).equalsIgnoreCase("-sc") &&
|
|
shun-iwasawa |
82a8f5 |
i < argv.length - 1) {
|
|
shun-iwasawa |
82a8f5 |
int match = 0;
|
|
shun-iwasawa |
82a8f5 |
String[] scaleArg = argv[++i].split("/");
|
|
shun-iwasawa |
82a8f5 |
if (scaleArg.length == 2) {
|
|
shun-iwasawa |
82a8f5 |
TJScalingFactor tempsf =
|
|
shun-iwasawa |
82a8f5 |
new TJScalingFactor(Integer.parseInt(scaleArg[0]),
|
|
shun-iwasawa |
82a8f5 |
Integer.parseInt(scaleArg[1]));
|
|
shun-iwasawa |
82a8f5 |
for (int j = 0; j < SCALING_FACTORS.length; j++) {
|
|
shun-iwasawa |
82a8f5 |
if (tempsf.equals(SCALING_FACTORS[j])) {
|
|
shun-iwasawa |
82a8f5 |
scalingFactor = SCALING_FACTORS[j];
|
|
shun-iwasawa |
82a8f5 |
match = 1;
|
|
shun-iwasawa |
82a8f5 |
break;
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
if (match != 1)
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].length() > 2 &&
|
|
shun-iwasawa |
82a8f5 |
argv[i].substring(0, 3).equalsIgnoreCase("-su") &&
|
|
shun-iwasawa |
82a8f5 |
i < argv.length - 1) {
|
|
shun-iwasawa |
82a8f5 |
i++;
|
|
shun-iwasawa |
82a8f5 |
if (argv[i].substring(0, 1).equalsIgnoreCase("g"))
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = TJ.SAMP_GRAY;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equals("444"))
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = TJ.SAMP_444;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equals("422"))
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = TJ.SAMP_422;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equals("420"))
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = TJ.SAMP_420;
|
|
shun-iwasawa |
82a8f5 |
else
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-q") &&
|
|
shun-iwasawa |
82a8f5 |
i < argv.length - 1) {
|
|
shun-iwasawa |
82a8f5 |
outQual = Integer.parseInt(argv[++i]);
|
|
shun-iwasawa |
82a8f5 |
if (outQual < 1 || outQual > 100)
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-g"))
|
|
shun-iwasawa |
82a8f5 |
xform.options |= TJTransform.OPT_GRAY;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-hflip"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_HFLIP;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-vflip"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_VFLIP;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-transpose"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_TRANSPOSE;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-transverse"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_TRANSVERSE;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-rot90"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_ROT90;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-rot180"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_ROT180;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-rot270"))
|
|
shun-iwasawa |
82a8f5 |
xform.op = TJTransform.OP_ROT270;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-custom"))
|
|
shun-iwasawa |
82a8f5 |
xform.cf = new TJExample();
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].length() > 2 &&
|
|
shun-iwasawa |
82a8f5 |
argv[i].substring(0, 2).equalsIgnoreCase("-c") &&
|
|
shun-iwasawa |
82a8f5 |
i < argv.length - 1) {
|
|
shun-iwasawa |
82a8f5 |
String[] cropArg = argv[++i].split("[x\\+]");
|
|
shun-iwasawa |
82a8f5 |
if (cropArg.length != 4)
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
xform.width = Integer.parseInt(cropArg[0]);
|
|
shun-iwasawa |
82a8f5 |
xform.height = Integer.parseInt(cropArg[1]);
|
|
shun-iwasawa |
82a8f5 |
xform.x = Integer.parseInt(cropArg[2]);
|
|
shun-iwasawa |
82a8f5 |
xform.y = Integer.parseInt(cropArg[3]);
|
|
shun-iwasawa |
82a8f5 |
if (xform.x < 0 || xform.y < 0 || xform.width < 1 ||
|
|
shun-iwasawa |
82a8f5 |
xform.height < 1)
|
|
shun-iwasawa |
82a8f5 |
usage();
|
|
shun-iwasawa |
82a8f5 |
xform.options |= TJTransform.OPT_CROP;
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].substring(0, 2).equalsIgnoreCase("-d"))
|
|
shun-iwasawa |
82a8f5 |
display = true;
|
|
shun-iwasawa |
82a8f5 |
else if (argv[i].equalsIgnoreCase("-fastupsample")) {
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Using fast upsampling code");
|
|
shun-iwasawa |
82a8f5 |
flags |= TJ.FLAG_FASTUPSAMPLE;
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].equalsIgnoreCase("-fastdct")) {
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Using fastest DCT/IDCT algorithm");
|
|
shun-iwasawa |
82a8f5 |
flags |= TJ.FLAG_FASTDCT;
|
|
shun-iwasawa |
82a8f5 |
} else if (argv[i].equalsIgnoreCase("-accuratedct")) {
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Using most accurate DCT/IDCT algorithm");
|
|
shun-iwasawa |
82a8f5 |
flags |= TJ.FLAG_ACCURATEDCT;
|
|
shun-iwasawa |
82a8f5 |
} else usage();
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* Determine input and output image formats based on file extensions. */
|
|
shun-iwasawa |
82a8f5 |
String[] inFileTokens = argv[0].split("\\.");
|
|
shun-iwasawa |
82a8f5 |
if (inFileTokens.length > 1)
|
|
shun-iwasawa |
82a8f5 |
inFormat = inFileTokens[inFileTokens.length - 1];
|
|
shun-iwasawa |
82a8f5 |
String[] outFileTokens;
|
|
shun-iwasawa |
82a8f5 |
if (display)
|
|
shun-iwasawa |
82a8f5 |
outFormat = "bmp";
|
|
shun-iwasawa |
82a8f5 |
else {
|
|
shun-iwasawa |
82a8f5 |
outFileTokens = argv[1].split("\\.");
|
|
shun-iwasawa |
82a8f5 |
if (outFileTokens.length > 1)
|
|
shun-iwasawa |
82a8f5 |
outFormat = outFileTokens[outFileTokens.length - 1];
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (inFormat.equalsIgnoreCase("jpg")) {
|
|
shun-iwasawa |
82a8f5 |
/* Input image is a JPEG image. Decompress and/or transform it. */
|
|
shun-iwasawa |
82a8f5 |
boolean doTransform = (xform.op != TJTransform.OP_NONE ||
|
|
shun-iwasawa |
82a8f5 |
xform.options != 0 || xform.cf != null);
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* Read the JPEG file into memory. */
|
|
shun-iwasawa |
82a8f5 |
File jpegFile = new File(argv[0]);
|
|
shun-iwasawa |
82a8f5 |
FileInputStream fis = new FileInputStream(jpegFile);
|
|
shun-iwasawa |
82a8f5 |
int jpegSize = fis.available();
|
|
shun-iwasawa |
82a8f5 |
if (jpegSize < 1) {
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Input file contains no data");
|
|
shun-iwasawa |
82a8f5 |
System.exit(1);
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
byte[] jpegBuf = new byte[jpegSize];
|
|
shun-iwasawa |
82a8f5 |
fis.read(jpegBuf);
|
|
shun-iwasawa |
82a8f5 |
fis.close();
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
TJDecompressor tjd;
|
|
shun-iwasawa |
82a8f5 |
if (doTransform) {
|
|
shun-iwasawa |
82a8f5 |
/* Transform it. */
|
|
shun-iwasawa |
82a8f5 |
TJTransformer tjt = new TJTransformer(jpegBuf);
|
|
shun-iwasawa |
82a8f5 |
TJTransform[] xforms = new TJTransform[1];
|
|
shun-iwasawa |
82a8f5 |
xforms[0] = xform;
|
|
shun-iwasawa |
82a8f5 |
xforms[0].options |= TJTransform.OPT_TRIM;
|
|
shun-iwasawa |
82a8f5 |
TJDecompressor[] tjds = tjt.transform(xforms, 0);
|
|
shun-iwasawa |
82a8f5 |
tjd = tjds[0];
|
|
shun-iwasawa |
82a8f5 |
tjt.close();
|
|
shun-iwasawa |
82a8f5 |
} else
|
|
shun-iwasawa |
82a8f5 |
tjd = new TJDecompressor(jpegBuf);
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
width = tjd.getWidth();
|
|
shun-iwasawa |
82a8f5 |
height = tjd.getHeight();
|
|
shun-iwasawa |
82a8f5 |
int inSubsamp = tjd.getSubsamp();
|
|
shun-iwasawa |
82a8f5 |
int inColorspace = tjd.getColorspace();
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
System.out.println((doTransform ? "Transformed" : "Input") +
|
|
shun-iwasawa |
82a8f5 |
" Image (jpg): " + width + " x " + height +
|
|
shun-iwasawa |
82a8f5 |
" pixels, " + SUBSAMP_NAME[inSubsamp] +
|
|
shun-iwasawa |
82a8f5 |
" subsampling, " + COLORSPACE_NAME[inColorspace]);
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (outFormat.equalsIgnoreCase("jpg") && doTransform &&
|
|
shun-iwasawa |
82a8f5 |
scalingFactor.isOne() && outSubsamp < 0 && outQual < 0) {
|
|
shun-iwasawa |
82a8f5 |
/* Input image has been transformed, and no re-compression options
|
|
shun-iwasawa |
82a8f5 |
have been selected. Write the transformed image to disk and
|
|
shun-iwasawa |
82a8f5 |
exit. */
|
|
shun-iwasawa |
82a8f5 |
File outFile = new File(argv[1]);
|
|
shun-iwasawa |
82a8f5 |
FileOutputStream fos = new FileOutputStream(outFile);
|
|
shun-iwasawa |
82a8f5 |
fos.write(tjd.getJPEGBuf(), 0, tjd.getJPEGSize());
|
|
shun-iwasawa |
82a8f5 |
fos.close();
|
|
shun-iwasawa |
82a8f5 |
System.exit(0);
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* Scaling and/or a non-JPEG output image format and/or compression
|
|
shun-iwasawa |
82a8f5 |
options have been selected, so we need to decompress the
|
|
shun-iwasawa |
82a8f5 |
input/transformed image. */
|
|
shun-iwasawa |
82a8f5 |
width = scalingFactor.getScaled(width);
|
|
shun-iwasawa |
82a8f5 |
height = scalingFactor.getScaled(height);
|
|
shun-iwasawa |
82a8f5 |
if (outSubsamp < 0)
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = inSubsamp;
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (!outFormat.equalsIgnoreCase("jpg"))
|
|
shun-iwasawa |
82a8f5 |
img = tjd.decompress(width, height, BufferedImage.TYPE_INT_RGB,
|
|
shun-iwasawa |
82a8f5 |
flags);
|
|
shun-iwasawa |
82a8f5 |
else
|
|
shun-iwasawa |
82a8f5 |
imgBuf = tjd.decompress(width, 0, height, TJ.PF_BGRX, flags);
|
|
shun-iwasawa |
82a8f5 |
tjd.close();
|
|
shun-iwasawa |
82a8f5 |
} else {
|
|
shun-iwasawa |
82a8f5 |
/* Input image is not a JPEG image. Load it into memory. */
|
|
shun-iwasawa |
82a8f5 |
img = ImageIO.read(new File(argv[0]));
|
|
shun-iwasawa |
82a8f5 |
if (img == null)
|
|
shun-iwasawa |
82a8f5 |
throw new Exception("Input image type not supported.");
|
|
shun-iwasawa |
82a8f5 |
width = img.getWidth();
|
|
shun-iwasawa |
82a8f5 |
height = img.getHeight();
|
|
shun-iwasawa |
82a8f5 |
if (outSubsamp < 0) {
|
|
shun-iwasawa |
82a8f5 |
if (img.getType() == BufferedImage.TYPE_BYTE_GRAY)
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = TJ.SAMP_GRAY;
|
|
shun-iwasawa |
82a8f5 |
else
|
|
shun-iwasawa |
82a8f5 |
outSubsamp = DEFAULT_SUBSAMP;
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
System.out.println("Input Image: " + width + " x " + height +
|
|
shun-iwasawa |
82a8f5 |
" pixels");
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
System.gc();
|
|
shun-iwasawa |
82a8f5 |
if (!display)
|
|
shun-iwasawa |
82a8f5 |
System.out.print("Output Image (" + outFormat + "): " + width +
|
|
shun-iwasawa |
82a8f5 |
" x " + height + " pixels");
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
if (display) {
|
|
shun-iwasawa |
82a8f5 |
/* Display the uncompressed image */
|
|
shun-iwasawa |
82a8f5 |
ImageIcon icon = new ImageIcon(img);
|
|
shun-iwasawa |
82a8f5 |
JLabel label = new JLabel(icon, JLabel.CENTER);
|
|
shun-iwasawa |
82a8f5 |
JOptionPane.showMessageDialog(null, label, "Output Image",
|
|
shun-iwasawa |
82a8f5 |
JOptionPane.PLAIN_MESSAGE);
|
|
shun-iwasawa |
82a8f5 |
} else if (outFormat.equalsIgnoreCase("jpg")) {
|
|
shun-iwasawa |
82a8f5 |
/* Output image format is JPEG. Compress the uncompressed image. */
|
|
shun-iwasawa |
82a8f5 |
if (outQual < 0)
|
|
shun-iwasawa |
82a8f5 |
outQual = DEFAULT_QUALITY;
|
|
shun-iwasawa |
82a8f5 |
System.out.println(", " + SUBSAMP_NAME[outSubsamp] +
|
|
shun-iwasawa |
82a8f5 |
" subsampling, quality = " + outQual);
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
TJCompressor tjc = new TJCompressor();
|
|
shun-iwasawa |
82a8f5 |
tjc.setSubsamp(outSubsamp);
|
|
shun-iwasawa |
82a8f5 |
tjc.setJPEGQuality(outQual);
|
|
shun-iwasawa |
82a8f5 |
if (img != null)
|
|
shun-iwasawa |
82a8f5 |
tjc.setSourceImage(img, 0, 0, 0, 0);
|
|
shun-iwasawa |
82a8f5 |
else
|
|
shun-iwasawa |
82a8f5 |
tjc.setSourceImage(imgBuf, 0, 0, width, 0, height, TJ.PF_BGRX);
|
|
shun-iwasawa |
82a8f5 |
byte[] jpegBuf = tjc.compress(flags);
|
|
shun-iwasawa |
82a8f5 |
int jpegSize = tjc.getCompressedSize();
|
|
shun-iwasawa |
82a8f5 |
tjc.close();
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
/* Write the JPEG image to disk. */
|
|
shun-iwasawa |
82a8f5 |
File outFile = new File(argv[1]);
|
|
shun-iwasawa |
82a8f5 |
FileOutputStream fos = new FileOutputStream(outFile);
|
|
shun-iwasawa |
82a8f5 |
fos.write(jpegBuf, 0, jpegSize);
|
|
shun-iwasawa |
82a8f5 |
fos.close();
|
|
shun-iwasawa |
82a8f5 |
} else {
|
|
shun-iwasawa |
82a8f5 |
/* Output image format is not JPEG. Save the uncompressed image
|
|
shun-iwasawa |
82a8f5 |
directly to disk. */
|
|
shun-iwasawa |
82a8f5 |
System.out.print("\n");
|
|
shun-iwasawa |
82a8f5 |
File outFile = new File(argv[1]);
|
|
shun-iwasawa |
82a8f5 |
ImageIO.write(img, outFormat, outFile);
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
} catch (Exception e) {
|
|
shun-iwasawa |
82a8f5 |
e.printStackTrace();
|
|
shun-iwasawa |
82a8f5 |
System.exit(-1);
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
}
|
|
shun-iwasawa |
82a8f5 |
|
|
shun-iwasawa |
82a8f5 |
static final TJScalingFactor[] SCALING_FACTORS =
|
|
shun-iwasawa |
82a8f5 |
TJ.getScalingFactors();
|
|
shun-iwasawa |
82a8f5 |
};
|