Various changes to the imaging code:
- added Image.trim(), that trims an image based on a specified pixel, just like in Photoshop. - saveAs exists in two versions now, one that takes a filename, the other an OutputStream + Mime type (first step toward an Java activation framework based approach)
This commit is contained in:
parent
e78b126148
commit
29f4faa3a1
5 changed files with 188 additions and 71 deletions
|
@ -21,6 +21,7 @@ import helma.main.Server;
|
|||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
|
@ -208,4 +209,16 @@ public abstract class ImageGenerator {
|
|||
*/
|
||||
public abstract void write(ImageWrapper wrapper, String filename,
|
||||
float quality, boolean alpha) throws IOException;
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from the dataSource.
|
||||
*
|
||||
* @param wrapper
|
||||
* @param out
|
||||
* @param quality
|
||||
* @param alpha
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract void write(ImageWrapper wrapper, OutputStream out, String type,
|
||||
float quality, boolean alpha) throws IOException;
|
||||
}
|
|
@ -221,6 +221,7 @@ public class ImageInfo {
|
|||
private int width;
|
||||
private int height;
|
||||
private int bitsPerPixel;
|
||||
private int numColors;
|
||||
private int colorType = COLOR_TYPE_UNKNOWN;
|
||||
private boolean progressive;
|
||||
private int format;
|
||||
|
@ -257,6 +258,7 @@ public class ImageInfo {
|
|||
numberOfImages = 1;
|
||||
physicalHeightDpi = -1;
|
||||
physicalWidthDpi = -1;
|
||||
numColors = -1;
|
||||
comments = null;
|
||||
try {
|
||||
int b1 = read() & 0xff;
|
||||
|
@ -353,13 +355,13 @@ public class ImageInfo {
|
|||
int flags = a[8] & 0xff;
|
||||
bitsPerPixel = ((flags >> 4) & 0x07) + 1;
|
||||
progressive = (flags & 0x02) != 0;
|
||||
if (!determineNumberOfImages) {
|
||||
return true;
|
||||
}
|
||||
// skip global color palette
|
||||
if ((flags & 0x80) != 0) {
|
||||
int tableSize = (1 << ((flags & 7) + 1)) * 3;
|
||||
skip(tableSize);
|
||||
numColors = (1 << ((flags & 7) + 1));
|
||||
skip(numColors * 3);
|
||||
}
|
||||
if (!determineNumberOfImages) {
|
||||
return true;
|
||||
}
|
||||
numberOfImages = 0;
|
||||
int blockType;
|
||||
|
@ -379,7 +381,11 @@ public class ImageInfo {
|
|||
bitsPerPixel = localBitsPerPixel;
|
||||
}
|
||||
if ((flags & 0x80) != 0) {
|
||||
skip((1 << localBitsPerPixel) * 3);
|
||||
int localNumColors = 1 << localBitsPerPixel;
|
||||
skip(localNumColors * 3);
|
||||
if (localNumColors > numColors) {
|
||||
numColors = localNumColors;
|
||||
}
|
||||
}
|
||||
skip(1); // initial code length
|
||||
int n;
|
||||
|
@ -777,6 +783,13 @@ public class ImageInfo {
|
|||
return bitsPerPixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return number of colors, for palette based images
|
||||
*/
|
||||
public int getNumColors() {
|
||||
return numColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index'th comment retrieved from the image.
|
||||
* @throws IllegalArgumentException if index is smaller than 0 or larger than or equal
|
||||
|
|
|
@ -785,10 +785,6 @@ public class Quantize {
|
|||
int db = b1 - b2;
|
||||
|
||||
return da * da + dr * dr + dg * dg + db * db;
|
||||
// return (SQUARES[r1 - r2 + MAX_RGB] +
|
||||
// SQUARES[g1 - g2 + MAX_RGB] +
|
||||
// SQUARES[b1 - b2 + MAX_RGB] +
|
||||
// SQUARES[a1 - a2 + MAX_RGB]);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
|
|
@ -71,36 +71,8 @@ public class ImageIOGenerator extends ImageGenerator {
|
|||
return ImageIO.read(new ByteArrayInputStream(src));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from filename.
|
||||
*
|
||||
* @param filename ...
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, String filename, float quality, boolean alpha) throws IOException {
|
||||
int pos = filename.lastIndexOf('.');
|
||||
if (pos != -1) {
|
||||
String extension = filename.substring(pos + 1,
|
||||
filename.length()).toLowerCase();
|
||||
|
||||
// Find a writer for that file extensions
|
||||
ImageWriter writer = null;
|
||||
Iterator iter = ImageIO.getImageWritersByFormatName(extension);
|
||||
if (iter.hasNext())
|
||||
writer = (ImageWriter) iter.next();
|
||||
if (writer != null) {
|
||||
ImageOutputStream ios = null;
|
||||
try {
|
||||
protected void write(ImageWrapper wrapper, ImageWriter writer, float quality, boolean alpha) throws IOException {
|
||||
BufferedImage bi = wrapper.getBufferedImage();
|
||||
// Prepare output file
|
||||
File file = new File(filename);
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
ios = ImageIO.createImageOutputStream(file);
|
||||
writer.setOutput(ios);
|
||||
// Set some parameters
|
||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||
if (param.canWriteCompressed() &&
|
||||
|
@ -117,7 +89,7 @@ public class ImageIOGenerator extends ImageGenerator {
|
|||
// create a new BufferedImage that uses a WritableRaster of bi, with all the bands except the alpha band:
|
||||
WritableRaster raster = bi.getRaster();
|
||||
WritableRaster newRaster = raster.createWritableChild(
|
||||
0, 0, wrapper.getWidth(), wrapper.getHeight(),
|
||||
0, 0, raster.getWidth(), raster.getHeight(),
|
||||
0, 0, new int[] {0, 1, 2 }
|
||||
);
|
||||
// create a ColorModel that represents the one of the ARGB except the alpha channel:
|
||||
|
@ -134,6 +106,38 @@ public class ImageIOGenerator extends ImageGenerator {
|
|||
writer.write(null, new IIOImage(bi, null, null),
|
||||
param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from filename.
|
||||
*
|
||||
* @param filename ...
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, String filename, float quality, boolean alpha) throws IOException {
|
||||
// determine suffix:
|
||||
int pos = filename.lastIndexOf('.');
|
||||
if (pos != -1) {
|
||||
String extension = filename.substring(pos + 1, filename.length()).toLowerCase();
|
||||
|
||||
// Find a writer for that file suffix
|
||||
ImageWriter writer = null;
|
||||
Iterator iter = ImageIO.getImageWritersBySuffix(extension);
|
||||
if (iter.hasNext())
|
||||
writer = (ImageWriter)iter.next();
|
||||
if (writer != null) {
|
||||
ImageOutputStream ios = null;
|
||||
try {
|
||||
// Prepare output file
|
||||
File file = new File(filename);
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
ios = ImageIO.createImageOutputStream(file);
|
||||
writer.setOutput(ios);
|
||||
this.write(wrapper, writer, quality, alpha);
|
||||
} finally {
|
||||
if (ios != null)
|
||||
ios.close();
|
||||
|
@ -142,4 +146,34 @@ public class ImageIOGenerator extends ImageGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from type.
|
||||
*
|
||||
* @param out ...
|
||||
* @param type ...
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.io.OutputStream, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, OutputStream out, String mimeType, float quality, boolean alpha) throws IOException {
|
||||
// Find a writer for that type
|
||||
ImageWriter writer = null;
|
||||
Iterator iter = ImageIO.getImageWritersByMIMEType(mimeType);
|
||||
if (iter.hasNext())
|
||||
writer = (ImageWriter)iter.next();
|
||||
if (writer != null) {
|
||||
ImageOutputStream ios = null;
|
||||
try {
|
||||
ios = ImageIO.createImageOutputStream(out);
|
||||
writer.setOutput(ios);
|
||||
this.write(wrapper, writer, quality, alpha);
|
||||
} finally {
|
||||
if (ios != null)
|
||||
ios.close();
|
||||
writer.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,25 +28,24 @@ import com.sun.jimi.core.options.JPGOptions;
|
|||
import com.sun.jimi.core.options.PNGOptions;
|
||||
|
||||
public class JimiGenerator extends ImageGenerator {
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from filename.
|
||||
* Internal function for writing images.
|
||||
*
|
||||
* @param filename ...
|
||||
* @param wrapper ...
|
||||
* @param type either a file extension or a mimetype with stripped image/ or image/x-
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, String filename, float quality, boolean alpha) throws IOException {
|
||||
protected boolean write(ImageWrapper wrapper, String type, OutputStream out, float quality, boolean alpha) throws IOException {
|
||||
try {
|
||||
String lowerCaseName = filename.toLowerCase();
|
||||
if (lowerCaseName.endsWith(".gif")) {
|
||||
if ("gif".equals(type)) {
|
||||
// sun's jimi package doesn't encode gifs, use helma's encoder instead
|
||||
DataOutputStream out = new DataOutputStream(
|
||||
new FileOutputStream(filename));
|
||||
DataOutputStream dataOut = new DataOutputStream(out);
|
||||
GIFEncoder encoder = new GIFEncoder();
|
||||
encoder.encode(wrapper.getBufferedImage(), out);
|
||||
out.close();
|
||||
encoder.encode(wrapper.getBufferedImage(), dataOut);
|
||||
} else {
|
||||
// let's not rely on Jimi's file-extension detecting mechanisms,
|
||||
// as these do not seem to specify file type depending options
|
||||
|
@ -54,8 +53,7 @@ public class JimiGenerator extends ImageGenerator {
|
|||
|
||||
JimiImage source = Jimi.createRasterImage(wrapper.getSource());
|
||||
JimiEncoder encoder = null;
|
||||
if (lowerCaseName.endsWith(".jpg")
|
||||
|| lowerCaseName.endsWith(".jpeg")) {
|
||||
if ("jpg".equals(type) || "jpeg".equals(type)) {
|
||||
// JPEG
|
||||
encoder = new JPGEncoder();
|
||||
// the quality value does mean something here and can be specified:
|
||||
|
@ -64,7 +62,7 @@ public class JimiGenerator extends ImageGenerator {
|
|||
options.setQuality(Math.round(quality * 100));
|
||||
source.setOptions(options);
|
||||
}
|
||||
} else if (lowerCaseName.endsWith(".png")) {
|
||||
} else if ("png".equals(type)) {
|
||||
// PNG
|
||||
encoder = new PNGEncoder();
|
||||
// the alpha parameter does mean something here:
|
||||
|
@ -74,17 +72,80 @@ public class JimiGenerator extends ImageGenerator {
|
|||
options.setCompressionType(PNGOptions.COMPRESSION_MAX);
|
||||
source.setOptions(options);
|
||||
}
|
||||
if (encoder != null) {
|
||||
FileOutputStream out = new FileOutputStream(filename);
|
||||
// if no encoder was found, return false. let jimi handle this in the functions bellow
|
||||
if (encoder == null) return false;
|
||||
encoder.encodeImages(new JimiImageEnumeration(source), out);
|
||||
out.close();
|
||||
} else { // if nothing worked, fall back to the Jimi mechanisms and see wether something comes out
|
||||
Jimi.putImage(wrapper.getImage(), filename);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (JimiException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from filename.
|
||||
*
|
||||
* @param wrapper ...
|
||||
* @param filename ...
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, String filename, float quality, boolean alpha) throws IOException {
|
||||
// determine the type from the file extension
|
||||
int pos = filename.lastIndexOf('.');
|
||||
if (pos != -1) {
|
||||
String extension = filename.substring(pos + 1, filename.length()).toLowerCase();
|
||||
FileOutputStream out = new FileOutputStream(filename);
|
||||
boolean written = false;
|
||||
try {
|
||||
written = this.write(wrapper, extension, out, quality, alpha);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
// if nothing worked, fall back to the Jimi mechanisms and see wether something comes out
|
||||
if (!written) {
|
||||
try {
|
||||
Jimi.putImage(wrapper.getImage(), filename);
|
||||
} catch (JimiException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the image. Image format is deduced from filename.
|
||||
*
|
||||
* @param wrapper ...
|
||||
* @param out ...
|
||||
* @param mimeType ...
|
||||
* @param quality ...
|
||||
* @param alpha ...
|
||||
* @throws IOException
|
||||
* @see helma.image.ImageGenerator#write(helma.image.ImageWrapper, java.io.OutputStream, java.lang.String, float, boolean)
|
||||
*/
|
||||
public void write(ImageWrapper wrapper, OutputStream out, String mimeType, float quality, boolean alpha) throws IOException {
|
||||
// determine the type from the mime type by taking away image/ and image/x-
|
||||
if (mimeType.startsWith("image/")) {
|
||||
String type = mimeType.substring(6);
|
||||
if (type.startsWith("x-"))
|
||||
type = type.substring(2);
|
||||
boolean written = false;
|
||||
try {
|
||||
written = this.write(wrapper, type, out, quality, alpha);
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
// if nothing worked, fall back to the Jimi mechanisms and see wether something comes out
|
||||
if (!written) {
|
||||
try {
|
||||
Jimi.putImage(mimeType, wrapper.getImage(), out);
|
||||
} catch (JimiException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue