![JAR search and dependency download from the Maven repository](/logo.png)
com.mortennobel.imagescaling.ImageUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-image-scaling Show documentation
Show all versions of java-image-scaling Show documentation
The purpose of the library is to provide better image scaling options than the Java runtime provides.
The newest version!
/*
* Copyright 2013, Morten Nobel-Joergensen
*
* License: The BSD 3-Clause License
* http://opensource.org/licenses/BSD-3-Clause
*/
package com.mortennobel.imagescaling;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.*;
import java.util.Iterator;
/**
* @author Heinz Doerr
* @author Morten Nobel-Joergensen
*/
public class ImageUtils {
static public String imageTypeName(BufferedImage img) {
switch (img.getType()) {
case BufferedImage.TYPE_3BYTE_BGR: return "TYPE_3BYTE_BGR";
case BufferedImage.TYPE_4BYTE_ABGR: return "TYPE_4BYTE_ABGR";
case BufferedImage.TYPE_4BYTE_ABGR_PRE: return "TYPE_4BYTE_ABGR_PRE";
case BufferedImage.TYPE_BYTE_BINARY: return "TYPE_BYTE_BINARY";
case BufferedImage.TYPE_BYTE_GRAY: return "TYPE_BYTE_GRAY";
case BufferedImage.TYPE_BYTE_INDEXED: return "TYPE_BYTE_INDEXED";
case BufferedImage.TYPE_CUSTOM: return "TYPE_CUSTOM";
case BufferedImage.TYPE_INT_ARGB: return "TYPE_INT_ARGB";
case BufferedImage.TYPE_INT_ARGB_PRE: return "TYPE_INT_ARGB_PRE";
case BufferedImage.TYPE_INT_BGR: return "TYPE_INT_BGR";
case BufferedImage.TYPE_INT_RGB: return "TYPE_INT_RGB";
case BufferedImage.TYPE_USHORT_555_RGB: return "TYPE_USHORT_555_RGB";
case BufferedImage.TYPE_USHORT_565_RGB: return "TYPE_USHORT_565_RGB";
case BufferedImage.TYPE_USHORT_GRAY: return "TYPE_USHORT_GRAY";
}
return "unknown image type #" + img.getType();
}
static public int nrChannels(BufferedImage img) {
switch (img.getType()) {
case BufferedImage.TYPE_3BYTE_BGR: return 3;
case BufferedImage.TYPE_4BYTE_ABGR: return 4;
case BufferedImage.TYPE_BYTE_GRAY: return 1;
case BufferedImage.TYPE_INT_BGR: return 3;
case BufferedImage.TYPE_INT_ARGB: return 4;
case BufferedImage.TYPE_INT_RGB: return 3;
case BufferedImage.TYPE_CUSTOM: return 4;
case BufferedImage.TYPE_4BYTE_ABGR_PRE: return 4;
case BufferedImage.TYPE_INT_ARGB_PRE: return 4;
case BufferedImage.TYPE_USHORT_555_RGB: return 3;
case BufferedImage.TYPE_USHORT_565_RGB: return 3;
case BufferedImage.TYPE_USHORT_GRAY: return 1;
}
return 0;
}
/**
*
* returns one row (height == 1) of byte packed image data in BGR or AGBR form
*
* @param img
* @param y
* @param w
* @param array
* @param temp must be either null or a array with length of w*h
* @return
*/
public static byte[] getPixelsBGR(BufferedImage img, int y, int w, byte[] array, int[] temp) {
final int x= 0;
final int h= 1;
assert array.length == temp.length * nrChannels(img);
assert (temp.length == w);
int imageType= img.getType();
Raster raster;
switch (imageType) {
case BufferedImage.TYPE_3BYTE_BGR:
case BufferedImage.TYPE_4BYTE_ABGR:
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
case BufferedImage.TYPE_BYTE_GRAY:
raster= img.getRaster();
//int ttype= raster.getTransferType();
raster.getDataElements(x, y, w, h, array);
break;
case BufferedImage.TYPE_INT_BGR:
raster= img.getRaster();
raster.getDataElements(x, y, w, h, temp);
ints2bytes(temp, array, 0, 1, 2); // bgr --> bgr
break;
case BufferedImage.TYPE_INT_RGB:
raster= img.getRaster();
raster.getDataElements(x, y, w, h, temp);
ints2bytes(temp, array, 2, 1, 0); // rgb --> bgr
break;
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_ARGB_PRE:
raster= img.getRaster();
raster.getDataElements(x, y, w, h, temp);
ints2bytes(temp, array, 2, 1, 0, 3); // argb --> abgr
break;
case BufferedImage.TYPE_CUSTOM: // TODO: works for my icon image loader, but else ???
img.getRGB(x, y, w, h, temp, 0, w);
ints2bytes(temp, array, 2, 1, 0, 3); // argb --> abgr
break;
default:
img.getRGB(x, y, w, h, temp, 0, w);
ints2bytes(temp, array, 2, 1, 0); // rgb --> bgr
break;
}
return array;
}
/**
* converts and copies byte packed BGR or ABGR into the img buffer,
* the img type may vary (e.g. RGB or BGR, int or byte packed)
* but the number of components (w/o alpha, w alpha, gray) must match
*
* does not unmange the image for all (A)RGN and (A)BGR and gray imaged
*
*/
public static void setBGRPixels(byte[] bgrPixels, BufferedImage img, int x, int y, int w, int h) {
int imageType= img.getType();
WritableRaster raster= img.getRaster();
//int ttype= raster.getTransferType();
if (imageType == BufferedImage.TYPE_3BYTE_BGR ||
imageType == BufferedImage.TYPE_4BYTE_ABGR ||
imageType == BufferedImage.TYPE_4BYTE_ABGR_PRE ||
imageType == BufferedImage.TYPE_BYTE_GRAY) {
raster.setDataElements(x, y, w, h, bgrPixels);
} else {
int[] pixels;
if (imageType == BufferedImage.TYPE_INT_BGR) {
pixels= bytes2int(bgrPixels, 2, 1, 0); // bgr --> bgr
} else if (imageType == BufferedImage.TYPE_INT_ARGB ||
imageType == BufferedImage.TYPE_INT_ARGB_PRE) {
pixels= bytes2int(bgrPixels, 3, 0, 1, 2); // abgr --> argb
} else {
pixels= bytes2int(bgrPixels, 0, 1, 2); // bgr --> rgb
}
if (w == 0 || h == 0) {
return;
} else if (pixels.length < w * h) {
throw new IllegalArgumentException("pixels array must have a length" + " >= w*h");
}
if (imageType == BufferedImage.TYPE_INT_ARGB ||
imageType == BufferedImage.TYPE_INT_RGB ||
imageType == BufferedImage.TYPE_INT_ARGB_PRE ||
imageType == BufferedImage.TYPE_INT_BGR) {
raster.setDataElements(x, y, w, h, pixels);
} else {
// Unmanages the image
img.setRGB(x, y, w, h, pixels, 0, w);
}
}
}
public static void ints2bytes(int[] in, byte[] out, int index1, int index2, int index3) {
for (int i= 0; i < in.length; i++) {
int index= i * 3;
int value= in[i];
out[index + index1]= (byte)value;
value= value >> 8;
out[index + index2]= (byte)value;
value= value >> 8;
out[index + index3]= (byte)value;
}
}
public static void ints2bytes(int[] in, byte[] out, int index1, int index2, int index3, int index4) {
for (int i= 0; i < in.length; i++) {
int index= i * 4;
int value= in[i];
out[index + index1]= (byte)value;
value= value >> 8;
out[index + index2]= (byte)value;
value= value >> 8;
out[index + index3]= (byte)value;
value= value >> 8;
out[index + index4]= (byte)value;
}
}
public static int[] bytes2int(byte[] in, int index1, int index2, int index3) {
int[] out= new int[in.length / 3];
for (int i= 0; i < out.length; i++) {
int index= i * 3;
int b1= (in[index +index1] & 0xff) << 16;
int b2= (in[index + index2] & 0xff) << 8;
int b3= in[index + index3] & 0xff;
out[i]= b1 | b2 | b3;
}
return out;
}
public static int[] bytes2int(byte[] in, int index1, int index2, int index3, int index4) {
int[] out= new int[in.length / 4];
for (int i= 0; i < out.length; i++) {
int index= i * 4;
int b1= (in[index +index1] & 0xff) << 24;
int b2= (in[index +index2] & 0xff) << 16;
int b3= (in[index + index3] & 0xff) << 8;
int b4= in[index + index4] & 0xff;
out[i]= b1 | b2 | b3 | b4;
}
return out;
}
public static BufferedImage convert(BufferedImage src, int bufImgType) {
BufferedImage img= new BufferedImage(src.getWidth(), src.getHeight(), bufImgType);
Graphics2D g2d= img.createGraphics();
g2d.drawImage(src, 0, 0, null);
g2d.dispose();
return img;
}
/**
* Copy jpeg meta data (exif) from source to dest and save it to out.
*
* @param source
* @param dest
* @return result
* @throws IOException
*/
public static byte[] copyJpegMetaData(byte[] source, byte[] dest) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream out = new MemoryCacheImageOutputStream(baos);
copyJpegMetaData(new ByteArrayInputStream(source),new ByteArrayInputStream(dest), out);
return baos.toByteArray();
}
/**
* Copy jpeg meta data (exif) from source to dest and save it to out
*
* @param source
* @param dest
* @param out
* @throws IOException
*/
public static void copyJpegMetaData(InputStream source, InputStream dest, ImageOutputStream out) throws IOException {
// Read meta data from src image
Iterator iter = ImageIO.getImageReadersByFormatName("jpeg");
ImageReader reader=(ImageReader) iter.next();
ImageInputStream iis = new MemoryCacheImageInputStream(source);
reader.setInput(iis);
IIOMetadata metadata = reader.getImageMetadata(0);
iis.close();
// Read dest image
ImageInputStream outIis = new MemoryCacheImageInputStream(dest);
reader.setInput(outIis);
IIOImage image = reader.readAll(0,null);
image.setMetadata(metadata);
outIis.close();
// write dest image
iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer=(ImageWriter) iter.next();
writer.setOutput(out);
writer.write(image);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy