/* * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.imageio.plugins.wbmp; import java.awt.Rectangle;import java.awt.image.BufferedImage;import java.awt.image.DataBufferByte;import java.awt.image.MultiPixelPackedSampleModel;import java.awt.image.Raster;import java.awt.image.WritableRaster; import javax.imageio.IIOException;import javax.imageio.ImageReader;import javax.imageio.ImageReadParam;import javax.imageio.ImageTypeSpecifier;import javax.imageio.metadata.IIOMetadata;import javax.imageio.spi.ImageReaderSpi;import javax.imageio.stream.ImageInputStream; import java.io.*;import java.util.ArrayList;import java.util.Iterator; import com.sun.imageio.plugins.common.I18N;import com.sun.imageio.plugins.common.ReaderUtil; /** This class is the Java Image IO plugin reader for WBMP images. * It may subsample the image, clip the image, * and shift the decoded image origin if the proper decoding parameter * are set in the provided <code>WBMPImageReadParam</code>. */public class WBMPImageReader extends ImageReader { /** The input stream where reads from */ private ImageInputStream iis = null; /** Indicates whether the header is read. */ private boolean gotHeader = false; /** The original image width. */ private int width; /** The original image height. */ private int height; private int wbmpType; private WBMPMetadata metadata; /** Constructs <code>WBMPImageReader</code> from the provided * <code>ImageReaderSpi</code>. */ public WBMPImageReader(ImageReaderSpi originator) { super(originator); } /** Overrides the method defined in the superclass. */ public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); iis = (ImageInputStream) input; // Always works gotHeader = false; } /** Overrides the method defined in the superclass. */ public int getNumImages(boolean allowSearch) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("GetNumImages0")); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException(I18N.getString("GetNumImages1")); } return 1; } public int getWidth(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return width; } public int getHeight(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); return height; } public boolean isRandomAccessEasy(int imageIndex) throws IOException { checkIndex(imageIndex); return true; } private void checkIndex(int imageIndex) { if (imageIndex != 0) { throw new IndexOutOfBoundsException(I18N.getString("WBMPImageReader0")); } } public void readHeader() throws IOException { if (gotHeader) return; if (iis == null) { throw new IllegalStateException("Input source not set!"); } metadata = new WBMPMetadata(); wbmpType = iis.readByte(); // TypeField byte fixHeaderField = iis.readByte(); // check for valid wbmp image if (fixHeaderField != 0 || !isValidWbmpType(wbmpType)) { throw new IIOException(I18N.getString("WBMPImageReader2")); } metadata.wbmpType = wbmpType; // Read image width width = ReaderUtil.readMultiByteInteger(iis); metadata.width = width; // Read image height height = ReaderUtil.readMultiByteInteger(iis); metadata.height = height; gotHeader = true; } public Iterator getImageTypes(int imageIndex) throws IOException { checkIndex(imageIndex); readHeader(); BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); ArrayList list = new ArrayList(1); list.add(new ImageTypeSpecifier(bi)); return list.iterator(); } public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } public IIOMetadata getImageMetadata(int imageIndex) throws IOException { checkIndex(imageIndex); if (metadata == null) { readHeader(); } return metadata; } public IIOMetadata getStreamMetadata() throws IOException { return null; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("WBMPImageReader1")); } checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); //read header readHeader(); Rectangle sourceRegion = new Rectangle(0, 0, 0, 0); Rectangle destinationRegion = new Rectangle(0, 0, 0, 0); computeRegions(param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); // If the destination is provided, then use it. Otherwise, create new one BufferedImage bi = param.getDestination(); if (bi == null) bi = new BufferedImage(destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height, BufferedImage.TYPE_BYTE_BINARY); boolean noTransform = destinationRegion.equals(new Rectangle(0, 0, width, height)) && destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight())); // Get the image data. WritableRaster tile = bi.getWritableTile(0, 0); // Get the SampleModel. MultiPixelPackedSampleModel sm = (MultiPixelPackedSampleModel)bi.getSampleModel(); if (noTransform) { if (abortRequested()) { processReadAborted(); return bi; } // If noTransform is necessary, read the data. iis.read(((DataBufferByte)tile.getDataBuffer()).getData(), 0, height*sm.getScanlineStride()); processImageUpdate(bi, 0, 0, width, height, 1, 1, new int[]{0}); processImageProgress(100.0F); } else { int len = (this.width + 7) / 8; byte[] buf = new byte[len]; byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData(); int lineStride = sm.getScanlineStride(); iis.skipBytes(len * sourceRegion.y); int skipLength = len * (scaleY - 1); // cache the values to avoid duplicated computation int[] srcOff = new int[destinationRegion.width]; int[] destOff = new int[destinationRegion.width]; int[] srcPos = new int[destinationRegion.width]; int[] destPos = new int[destinationRegion.width]; for (int i = destinationRegion.x, x = sourceRegion.x, j = 0; i < destinationRegion.x + destinationRegion.width; i++, j++, x += scaleX) { srcPos[j] = x >> 3; srcOff[j] = 7 - (x & 7); destPos[j] = i >> 3; destOff[j] = 7 - (i & 7); } for (int j = 0, y = sourceRegion.y, k = destinationRegion.y * lineStride; j < destinationRegion.height; j++, y+=scaleY) { if (abortRequested()) break; iis.read(buf, 0, len); for (int i = 0; i < destinationRegion.width; i++) { //get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 1; data[k + destPos[i]] |= v << destOff[i]; } k += lineStride; iis.skipBytes(skipLength); processImageUpdate(bi, 0, j, destinationRegion.width, 1, 1, 1, new int[]{0}); processImageProgress(100.0F*j/destinationRegion.height); } } if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; } public boolean canReadRaster() { return true; } public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException { BufferedImage bi = read(imageIndex, param); return bi.getData(); } public void reset() { super.reset(); iis = null; gotHeader = false; } /* * This method verifies that given byte is valid wbmp type marker. * At the moment only 0x0 marker is described by wbmp spec. */ boolean isValidWbmpType(int type) { return type == 0; }}
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.imageio.IIOException;
import javax.imageio.ImageReader;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import com.sun.imageio.plugins.common.I18N;
import com.sun.imageio.plugins.common.ReaderUtil;
/** This class is the Java Image IO plugin reader for WBMP images.
* It may subsample the image, clip the image,
* and shift the decoded image origin if the proper decoding parameter
* are set in the provided <code>WBMPImageReadParam</code>.
*/
public class WBMPImageReader extends ImageReader {
/** The input stream where reads from */
private ImageInputStream iis = null;
/** Indicates whether the header is read. */
private boolean gotHeader = false;
/** The original image width. */
private int width;
/** The original image height. */
private int height;
private int wbmpType;
private WBMPMetadata metadata;
/** Constructs <code>WBMPImageReader</code> from the provided
* <code>ImageReaderSpi</code>.
*/
public WBMPImageReader(ImageReaderSpi originator) {
super(originator);
}
/** Overrides the method defined in the superclass. */
public void setInput(Object input,
boolean seekForwardOnly,
boolean ignoreMetadata) {
super.setInput(input, seekForwardOnly, ignoreMetadata);
iis = (ImageInputStream) input; // Always works
gotHeader = false;
}
/** Overrides the method defined in the superclass. */
public int getNumImages(boolean allowSearch) throws IOException {
if (iis == null) {
throw new IllegalStateException(I18N.getString("GetNumImages0"));
}
if (seekForwardOnly && allowSearch) {
throw new IllegalStateException(I18N.getString("GetNumImages1"));
}
return 1;
}
public int getWidth(int imageIndex) throws IOException {
checkIndex(imageIndex);
readHeader();
return width;
}
public int getHeight(int imageIndex) throws IOException {
checkIndex(imageIndex);
readHeader();
return height;
}
public boolean isRandomAccessEasy(int imageIndex) throws IOException {
checkIndex(imageIndex);
return true;
}
private void checkIndex(int imageIndex) {
if (imageIndex != 0) {
throw new IndexOutOfBoundsException(I18N.getString("WBMPImageReader0"));
}
}
public void readHeader() throws IOException {
if (gotHeader)
return;
if (iis == null) {
throw new IllegalStateException("Input source not set!");
}
metadata = new WBMPMetadata();
wbmpType = iis.readByte(); // TypeField
byte fixHeaderField = iis.readByte();
// check for valid wbmp image
if (fixHeaderField != 0
|| !isValidWbmpType(wbmpType))
{
throw new IIOException(I18N.getString("WBMPImageReader2"));
}
metadata.wbmpType = wbmpType;
// Read image width
width = ReaderUtil.readMultiByteInteger(iis);
metadata.width = width;
// Read image height
height = ReaderUtil.readMultiByteInteger(iis);
metadata.height = height;
gotHeader = true;
}
public Iterator getImageTypes(int imageIndex)
throws IOException {
checkIndex(imageIndex);
readHeader();
BufferedImage bi =
new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
ArrayList list = new ArrayList(1);
list.add(new ImageTypeSpecifier(bi));
return list.iterator();
}
public ImageReadParam getDefaultReadParam() {
return new ImageReadParam();
}
public IIOMetadata getImageMetadata(int imageIndex)
throws IOException {
checkIndex(imageIndex);
if (metadata == null) {
readHeader();
}
return metadata;
}
public IIOMetadata getStreamMetadata() throws IOException {
return null;
}
public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {
if (iis == null) {
throw new IllegalStateException(I18N.getString("WBMPImageReader1"));
}
checkIndex(imageIndex);
clearAbortRequest();
processImageStarted(imageIndex);
if (param == null)
param = getDefaultReadParam();
//read header
readHeader();
Rectangle sourceRegion = new Rectangle(0, 0, 0, 0);
Rectangle destinationRegion = new Rectangle(0, 0, 0, 0);
computeRegions(param, this.width, this.height,
param.getDestination(),
sourceRegion,
destinationRegion);
int scaleX = param.getSourceXSubsampling();
int scaleY = param.getSourceYSubsampling();
int xOffset = param.getSubsamplingXOffset();
int yOffset = param.getSubsamplingYOffset();
// If the destination is provided, then use it. Otherwise, create new one
BufferedImage bi = param.getDestination();
if (bi == null)
bi = new BufferedImage(destinationRegion.x + destinationRegion.width,
destinationRegion.y + destinationRegion.height,
BufferedImage.TYPE_BYTE_BINARY);
boolean noTransform =
destinationRegion.equals(new Rectangle(0, 0, width, height)) &&
destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
// Get the image data.
WritableRaster tile = bi.getWritableTile(0, 0);
// Get the SampleModel.
MultiPixelPackedSampleModel sm =
(MultiPixelPackedSampleModel)bi.getSampleModel();
if (noTransform) {
if (abortRequested()) {
processReadAborted();
return bi;
}
// If noTransform is necessary, read the data.
iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
0, height*sm.getScanlineStride());
processImageUpdate(bi,
0, 0,
width, height, 1, 1,
new int[]{0});
processImageProgress(100.0F);
} else {
int len = (this.width + 7) / 8;
byte[] buf = new byte[len];
byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
int lineStride = sm.getScanlineStride();
iis.skipBytes(len * sourceRegion.y);
int skipLength = len * (scaleY - 1);
// cache the values to avoid duplicated computation
int[] srcOff = new int[destinationRegion.width];
int[] destOff = new int[destinationRegion.width];
int[] srcPos = new int[destinationRegion.width];
int[] destPos = new int[destinationRegion.width];
for (int i = destinationRegion.x, x = sourceRegion.x, j = 0;
i < destinationRegion.x + destinationRegion.width;
i++, j++, x += scaleX) {
srcPos[j] = x >> 3;
srcOff[j] = 7 - (x & 7);
destPos[j] = i >> 3;
destOff[j] = 7 - (i & 7);
}
for (int j = 0, y = sourceRegion.y,
k = destinationRegion.y * lineStride;
j < destinationRegion.height; j++, y+=scaleY) {
if (abortRequested())
break;
iis.read(buf, 0, len);
for (int i = 0; i < destinationRegion.width; i++) {
//get the bit and assign to the data buffer of the raster
int v = (buf[srcPos[i]] >> srcOff[i]) & 1;
data[k + destPos[i]] |= v << destOff[i];
}
k += lineStride;
iis.skipBytes(skipLength);
processImageUpdate(bi,
0, j,
destinationRegion.width, 1, 1, 1,
new int[]{0});
processImageProgress(100.0F*j/destinationRegion.height);
}
}
if (abortRequested())
processReadAborted();
else
processImageComplete();
return bi;
}
public boolean canReadRaster() {
return true;
}
public Raster readRaster(int imageIndex,
ImageReadParam param) throws IOException {
BufferedImage bi = read(imageIndex, param);
return bi.getData();
}
public void reset() {
super.reset();
iis = null;
gotHeader = false;
}
/*
* This method verifies that given byte is valid wbmp type marker.
* At the moment only 0x0 marker is described by wbmp spec.
*/
boolean isValidWbmpType(int type) {
return type == 0;
}
}