org.apache.xmlgraphics.image.codec.tiff.ImageInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmlgraphics-commons Show documentation
Show all versions of xmlgraphics-commons Show documentation
Apache XML Graphics Commons is a library that consists of several reusable
components used by Apache Batik and Apache FOP. Many of these components
can easily be used separately outside the domains of SVG and XSL-FO.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlgraphics.image.codec.tiff;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
final class ImageInfo {
// Default values
private static final int DEFAULT_ROWS_PER_STRIP = 8;
private final int numExtraSamples;
private final ExtraSamplesType extraSampleType;
private final ImageType imageType;
private final int colormapSize;
private final char[] colormap;
private final int tileWidth;
private final int tileHeight;
private final int numTiles;
private final long bytesPerRow;
private final long bytesPerTile;
private ImageInfo(ImageInfoBuilder builder) {
this.numExtraSamples = builder.numExtraSamples;
this.extraSampleType = builder.extraSampleType;
this.imageType = builder.imageType;
this.colormapSize = builder.colormapSize;
this.colormap = copyColormap(builder.colormap);
this.tileWidth = builder.tileWidth;
this.tileHeight = builder.tileHeight;
this.numTiles = builder.numTiles;
this.bytesPerRow = builder.bytesPerRow;
this.bytesPerTile = builder.bytesPerTile;
}
private static char[] copyColormap(char[] colorMap) {
if (colorMap == null) {
return null;
}
char[] copy = new char[colorMap.length];
System.arraycopy(colorMap, 0, copy, 0, colorMap.length);
return copy;
}
private static int getNumberOfExtraSamplesForColorSpace(ColorSpace colorSpace,
ImageType imageType, int numBands) {
if (imageType == ImageType.GENERIC) {
return numBands - 1;
} else if (numBands > 1) {
return numBands - colorSpace.getNumComponents();
} else {
return 0;
}
}
private static char[] createColormap(final int sizeOfColormap, byte[] r, byte[] g, byte[] b) {
int redIndex = 0;
int greenIndex = sizeOfColormap;
int blueIndex = 2 * sizeOfColormap;
char[] colormap = new char[sizeOfColormap * 3];
for (int i = 0; i < sizeOfColormap; i++) {
// beware of sign extended bytes
colormap[redIndex++] = convertColorToColormapChar(0xff & r[i]);
colormap[greenIndex++] = convertColorToColormapChar(0xff & g[i]);
colormap[blueIndex++] = convertColorToColormapChar(0xff & b[i]);
}
return colormap;
}
private static char convertColorToColormapChar(int color) {
return (char) (color << 8 | color);
}
int getNumberOfExtraSamples() {
return numExtraSamples;
}
ExtraSamplesType getExtraSamplesType() {
return extraSampleType;
}
ImageType getType() {
return imageType;
}
int getColormapSize() {
return colormapSize;
}
char[] getColormap() {
return copyColormap(colormap);
}
int getTileWidth() {
return tileWidth;
}
int getTileHeight() {
return tileHeight;
}
int getNumTiles() {
return numTiles;
}
long getBytesPerRow() {
return bytesPerRow;
}
long getBytesPerTile() {
return bytesPerTile;
}
static ImageInfo newInstance(RenderedImage im, int dataTypeSize, int numBands,
ColorModel colorModel, TIFFEncodeParam params) {
ImageInfoBuilder builder = new ImageInfoBuilder();
if (colorModel instanceof IndexColorModel) { // Bilevel or palette
IndexColorModel indexColorModel = (IndexColorModel) colorModel;
int colormapSize = indexColorModel.getMapSize();
byte[] r = new byte[colormapSize];
indexColorModel.getReds(r);
byte[] g = new byte[colormapSize];
indexColorModel.getGreens(g);
byte[] b = new byte[colormapSize];
indexColorModel.getBlues(b);
builder.imageType = ImageType.getTypeFromRGB(colormapSize, r, g, b, dataTypeSize,
numBands);
if (builder.imageType == ImageType.PALETTE) {
builder.colormap = createColormap(colormapSize, r, g, b);
builder.colormapSize = colormapSize * 3;
}
} else if (colorModel == null) {
if (dataTypeSize == 1 && numBands == 1) { // bilevel
builder.imageType = ImageType.BILEVEL_BLACK_IS_ZERO;
} else {
builder.imageType = ImageType.GENERIC;
builder.numExtraSamples = numBands > 1 ? numBands - 1 : 0;
}
} else {
ColorSpace colorSpace = colorModel.getColorSpace();
builder.imageType = ImageType.getTypeFromColorSpace(colorSpace, params);
builder.numExtraSamples = getNumberOfExtraSamplesForColorSpace(colorSpace,
builder.imageType, numBands);
builder.extraSampleType = ExtraSamplesType.getValue(colorModel,
builder.numExtraSamples);
}
// Initialize tile dimensions.
final int width = im.getWidth();
final int height = im.getHeight();
if (params.getWriteTiled()) {
builder.tileWidth = params.getTileWidth() > 0 ? params.getTileWidth() : width;
builder.tileHeight = params.getTileHeight() > 0 ? params.getTileHeight() : height;
// NB: Parentheses are used in this statement for correct rounding.
builder.numTiles = ((width + builder.tileWidth - 1) / builder.tileWidth)
* ((height + builder.tileHeight - 1) / builder.tileHeight);
} else {
builder.tileWidth = width;
builder.tileHeight = params.getTileHeight() > 0 ? params.getTileHeight()
: DEFAULT_ROWS_PER_STRIP;
builder.numTiles = (int) Math.ceil(height / (double) builder.tileHeight);
}
builder.setBytesPerRow(dataTypeSize, numBands)
.setBytesPerTile();
return builder.build();
}
private static final class ImageInfoBuilder {
private ImageType imageType = ImageType.UNSUPPORTED;
private int numExtraSamples;
private char[] colormap;
private int colormapSize;
private ExtraSamplesType extraSampleType = ExtraSamplesType.UNSPECIFIED;
private int tileWidth;
private int tileHeight;
private int numTiles;
private long bytesPerRow;
private long bytesPerTile;
private ImageInfoBuilder setBytesPerRow(int dataTypeSize, int numBands) {
bytesPerRow = (long) Math.ceil((dataTypeSize / 8.0) * tileWidth * numBands);
return this;
}
private ImageInfoBuilder setBytesPerTile() {
bytesPerTile = bytesPerRow * tileHeight;
return this;
}
private ImageInfo build() {
return new ImageInfo(this);
}
}
}