/*******************************************************************************
* Copyright (C) 2009-2011 Amir Hassan <amir@viel-zu.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
******************************************************************************/
package org.wooden.image;
import java.awt.Component;
import java.awt.Container;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageToolkit {
private static Container observer = new Container();
public static int[] average(int pixel1[], int pixel2[], int preAlloc[]) {
if (preAlloc == null)
preAlloc = new int[3];
preAlloc[0] = (pixel1[0] + pixel2[0]) / 2;
preAlloc[1] = (pixel1[1] + pixel2[1]) / 2;
preAlloc[2] = (pixel1[2] + pixel2[2]) / 2;
return preAlloc;
}
public static int calculateContrast(int r1, int g1, int b1, int r2, int g2,
int b2) {
return Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);
}
public static int[][] colorVariantsToBase(int alpha, int red, int green,
int blue, int base, int preAlloc[][]) {
int channels[] = { red, green, blue };
for (int i = 0; i < channels.length; i++) {
int modulo = channels[i] % base;
if (blue - modulo >= 0)
channels[i] -= modulo;
else
channels[i] += base - modulo;
}
for (int i = 0; i < channels.length; i++) {
int encColor = encodeColorInfo(alpha, channels[0], channels[1],
channels[2]);
preAlloc[i] = decodeColorInfo(encColor, preAlloc[i]);
}
return preAlloc;
}
public static BufferedImage createBufferedImagePixels(int w, int h,
int pixels[]) {
System.out.println("createBufferedImage");
BufferedImage image = new BufferedImage(w, h, 1);
image.getRaster().setPixels(0, 0, w, h, pixels);
return image;
}
public static BufferedImage createBufferedImageRGB(int w, int h, int rgb[],
int rgbType) {
System.out.println("createBufferedImage");
BufferedImage image = new BufferedImage(w, h, rgbType);
image.setRGB(0, 0, w, h, rgb, 0, w);
return image;
}
public static byte[] createJpegData(BufferedImage img) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(img);
param.setQuality(1.0F, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(img);
return out.toByteArray();
}
public static BufferedImage createJpegImage(byte data[]) throws IOException {
return readJpegImage(new ByteArrayInputStream(data));
}
public static int[] decodeColorInfo(int rgb) {
return decodeColorInfo(rgb, new int[3]);
}
public static int[] decodeColorInfo(int rgb, int preAlloc[]) {
preAlloc[0] = rgb >>> 24 & 0xff;
preAlloc[1] = rgb >>> 16 & 0xff;
preAlloc[2] = rgb >>> 8 & 0xff;
preAlloc[3] = rgb >>> 0 & 0xff;
return preAlloc;
}
public static int[] decodeDataPixels(InputStream inSrc) throws IOException {
DataInputStream in;
if (inSrc instanceof DataInputStream)
in = (DataInputStream) inSrc;
else
in = new DataInputStream(inSrc);
int r = 0;
int g = 0;
int b = 0;
int pixels[] = new int[in.readInt()];
int onepercent = pixels.length / 100;
short pixelCount = 0;
for (int i = 0; i + 1 < pixels.length;) {
pixelCount = 1;
int curr = in.read();
if (curr == 0) {
pixelCount = (short) (in.readShort() + 1);
curr = in.read();
}
r = curr;
g = in.read();
b = in.read();
for (int j = 0; j < pixelCount; j++) {
pixels[i] = r;
pixels[i + 1] = g;
pixels[i + 2] = b;
i += 3;
}
}
in.close();
return pixels;
}
public static int[] decodeDataRGB(InputStream inSrc) throws IOException {
DataInputStream in;
if (inSrc instanceof DataInputStream)
in = (DataInputStream) inSrc;
else
in = new DataInputStream(inSrc);
int r = 0;
int g = 0;
int b = 0;
int arrRGB[] = new int[in.readInt()];
int onepercent = arrRGB.length / 100;
int rgb = 0;
short pixelCount = 0;
for (int i = 0; i + 1 < arrRGB.length;) {
rgb = 0;
pixelCount = 1;
int curr = in.read();
if (curr == 0) {
pixelCount = (short) (in.readShort() + 1);
curr = in.read();
}
r = curr;
g = in.read();
b = in.read();
rgb = encodeColorInfo(255, r, g, b);
for (int j = 0; j < pixelCount; j++) {
arrRGB[i] = rgb;
i++;
}
}
in.close();
return arrRGB;
}
public static int encodeColorInfo(int rgbColor[]) {
return encodeColorInfo(rgbColor[0], rgbColor[1], rgbColor[2], rgbColor[3]);
}
public static int encodeColorInfo(int alpha, int red, int green, int blue) {
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
public static void encodeDataPixels(int pixels[], int level,
OutputStream outDest) throws IOException {
DataOutputStream out;
if (outDest instanceof DataOutputStream)
out = (DataOutputStream) outDest;
else
out = new DataOutputStream(outDest);
short pixelCount = 0;
int r = 0;
int g = 0;
int b = 0;
int avgR = 0;
int avgG = 0;
int avgB = 0;
int dec[] = null;
int onepercent = pixels.length / 100;
out.writeInt(pixels.length);
for (int i = 0; i < pixels.length; i += 3) {
int currR = pixels[i];
int currG = pixels[i + 1];
int currB = pixels[i + 2];
if (i == 0) {
avgR = r = currR;
avgG = g = currG;
avgB = b = currB;
}
int diff = calculateContrast(r, g, b, currR, currG, currB);
if (diff > level || pixelCount > 32765 || i == pixels.length - 1) {
if (pixelCount > 0) {
out.write(0);
out.writeShort(pixelCount);
}
out.write(avgR);
out.write(avgG);
out.write(avgB);
avgR = r = currR;
avgG = g = currG;
avgB = b = currB;
pixelCount = 0;
} else {
avgR = (avgR + currR) / 2;
avgG = (avgG + currG) / 2;
avgB = (avgB + currB) / 2;
pixelCount++;
}
}
out.close();
}
public static void encodeDataRGB(int rgb[], int level, OutputStream outDest)
throws IOException {
DataOutputStream out;
if (outDest instanceof DataOutputStream)
out = (DataOutputStream) outDest;
else
out = new DataOutputStream(outDest);
short pixelCount = 0;
int r = 0;
int g = 0;
int b = 0;
int avgR = 0;
int avgG = 0;
int avgB = 0;
int dec[] = null;
int onepercent = rgb.length / 100;
out.writeInt(rgb.length);
for (int i = 0; i < rgb.length; i++) {
dec = decodeColorInfo(rgb[i]);
for (int j = 1; j < dec.length; j++)
if (dec[j] == 0)
dec[j]++;
int currR = dec[1];
int currG = dec[2];
int currB = dec[3];
if (i == 0) {
avgR = r = currR;
avgG = g = currG;
avgB = b = currB;
}
int diff = calculateContrast(r, g, b, currR, currG, currB);
if (diff > level || pixelCount > 32765 || i == rgb.length - 1) {
if (pixelCount > 0) {
out.write(0);
out.writeShort(pixelCount);
}
out.write(avgR);
out.write(avgG);
out.write(avgB);
avgR = r = currR;
avgG = g = currG;
avgB = b = currB;
pixelCount = 0;
} else {
avgR = (avgR + currR) / 2;
avgG = (avgG + currG) / 2;
avgB = (avgB + currB) / 2;
pixelCount++;
}
}
out.close();
}
public static int[] getDataRGB(BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
return image.getRGB(0, 0, w, h, new int[w * h], 0, w);
}
public static void loadImageChecked(Image img) {
loadImageChecked(img, ((observer)));
}
public static void loadImageChecked(Image img, Component observer) {
int status;
for (int failure = 0x80 | 0x40; ((status = observer.checkImage(img,
observer)) & failure) == 0;) {
System.out.println((new StringBuilder(String.valueOf(img
.getWidth(observer)))).append(" ").append(status & 1).append("/")
.append(img.getHeight(observer)).append(" ").append(status & 2)
.toString());
if ((status & 1) > 0 && (status & 2) > 0) {
observer.prepareImage(img, observer);
return;
}
try {
Thread.sleep(100L);
} catch (InterruptedException interruptedexception) {}
}
String strStatus = "ABORT";
if ((status & 0x40) != 0)
strStatus = "ERROR";
throw new RasterFormatException((new StringBuilder(
"Illegal image Format (checkImage: ")).append(strStatus).append(")")
.toString());
}
public static int[] readDataRGB(File source) throws IOException {
long size = source.length();
if (size % 4L > 0L)
System.err.println("Invalid file size");
int rgb[] = new int[(int) (size / 4L)];
DataInputStream in = new DataInputStream(new FileInputStream(source));
for (int i = 0; i < rgb.length; i++)
rgb[i] = in.readInt();
in.close();
return rgb;
}
public static BufferedImage readJpegImage(InputStream in) throws IOException {
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
return decoder.decodeAsBufferedImage();
}
public static BufferedImage readPngImage(File f) throws IOException {
Image img = observer.getToolkit().getImage(f.getCanonicalPath());
MediaTracker mt = new MediaTracker(observer);
mt.addImage(img, 0);
try {
mt.waitForAll();
} catch (InterruptedException interruptedexception) {}
BufferedImage image = new BufferedImage(img.getWidth(observer),
img.getHeight(observer), 1);
image.getGraphics().drawImage(img, 0, 0, observer);
return image;
}
public static void writeDataRGB(int rgb[], File dest) throws IOException {
DataOutputStream out = new DataOutputStream(new FileOutputStream(dest));
for (int element : rgb)
out.writeInt(element);
out.close();
}
public static void writeJpepImage(BufferedImage img, OutputStream out)
throws IOException {
out.write(createJpegData(img));
out.close();
}
private ImageToolkit() {}
}