Skip to content

Commit

Permalink
Added UnsignedIntBuffer and UnsignedIntColorModel to facilitate unsig…
Browse files Browse the repository at this point in the history
…ned 32-bit BufferedImage construction. Closes #375.
  • Loading branch information
melissalinkert committed May 5, 2009
1 parent 154c592 commit 69cec13
Show file tree
Hide file tree
Showing 3 changed files with 302 additions and 14 deletions.
29 changes: 15 additions & 14 deletions components/bio-formats/src/loci/formats/AWTImageTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ public static BufferedImage makeImage(int[] data, int w, int h) {
* @param h Height of image plane.
* @param signed Whether the int values should be treated as signed
* (-2^31 to 2^31-1) instead of unsigned (0 to 2^32-1).
* <b>** Only signed int data is supported for now. **</b>
*/
public static BufferedImage makeImage(int[] data,
int w, int h, boolean signed)
Expand Down Expand Up @@ -268,22 +267,18 @@ public static BufferedImage makeImage(int[] data,
* while "RRR...GGG...BBB..." is sequential.
* @param signed Whether the int values should be treated as signed
* (-2^31 to 2^31-1) instead of unsigned (0 to 2^32-1).
* <b>** Only signed int data is supported for now. **</b>
*/
public static BufferedImage makeImage(int[] data,
int w, int h, int c, boolean interleaved, boolean signed)
{
if (c == 1) return makeImage(data, w, h, signed);
int dataType;
int dataType = DataBuffer.TYPE_INT;
DataBuffer buffer;
if (signed) {
dataType = DataBuffer.TYPE_INT;
buffer = new DataBufferInt(data, c * w * h);
}
else {
// NB: No built-in data buffer type for unsigned int data.
throw new IllegalArgumentException(
"Support for uint32 pixel type (unsigned ints) is unimplemented");
buffer = new UnsignedIntBuffer(data, c * w * h);
}
return constructImage(c, dataType, w, h, interleaved, false, buffer);
}
Expand Down Expand Up @@ -423,21 +418,17 @@ public static BufferedImage makeImage(int[][] data, int w, int h) {
* @param h Height of image plane.
* @param signed Whether the int values should be treated as signed
* (-2^31 to 2^31-1) instead of unsigned (0 to 2^32-1).
* <b>** Only signed int data is supported for now. **</b>
*/
public static BufferedImage makeImage(int[][] data,
int w, int h, boolean signed)
{
int dataType;
int dataType = DataBuffer.TYPE_INT;
DataBuffer buffer;
if (signed) {
dataType = DataBuffer.TYPE_INT;
buffer = new DataBufferInt(data, data[0].length);
}
else {
// NB: No built-in data buffer type for unsigned int data.
throw new IllegalArgumentException(
"Support for uint32 pixel type (unsigned ints) is unimplemented");
buffer = new UnsignedIntBuffer(data, data[0].length);
}
return constructImage(data.length, dataType, w, h, false, true, buffer);
}
Expand Down Expand Up @@ -686,6 +677,12 @@ public static BufferedImage constructImage(int c, int type, int w,
{
ColorModel colorModel = makeColorModel(c, type);
if (colorModel == null) return null;
if (buffer instanceof UnsignedIntBuffer) {
try {
colorModel = new UnsignedIntColorModel(32, type, c);
}
catch (IOException e) { }
}

SampleModel model;
if (c > 2 && type == DataBuffer.TYPE_INT && buffer.getNumBanks() == 1) {
Expand Down Expand Up @@ -1048,7 +1045,8 @@ else if (pixels instanceof double[][]) {
* </ul>
*/
public static int getPixelType(BufferedImage image) {
int type = image.getRaster().getDataBuffer().getDataType();
DataBuffer buffer = image.getRaster().getDataBuffer();
int type = buffer.getDataType();
int imageType = image.getType();
switch (type) {
case DataBuffer.TYPE_BYTE:
Expand All @@ -1064,6 +1062,9 @@ public static int getPixelType(BufferedImage image) {
{
return FormatTools.UINT8;
}
if (buffer instanceof UnsignedIntBuffer) {
return FormatTools.UINT32;
}
return FormatTools.INT32;
case DataBuffer.TYPE_SHORT:
return FormatTools.INT16;
Expand Down
125 changes: 125 additions & 0 deletions components/bio-formats/src/loci/formats/UnsignedIntBuffer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// UnsignedIntBuffer.java
//

/*
OME Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc.
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 loci.formats;

import java.awt.image.DataBuffer;

/**
* DataBuffer that stores unsigned ints.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/components/bio-formats/src/loci/formats/UnsignedIntBuffer.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/components/bio-formats/src/loci/formats/UnsignedIntBuffer.java">SVN</a></dd></dl>
*
* @author Melissa Linkert linkert at wisc.edu
*/
public class UnsignedIntBuffer extends DataBuffer {

private int[][] bankData;

/** Construct a new buffer of unsigned ints using the given int array. */
public UnsignedIntBuffer(int[] dataArray, int size) {
super(DataBuffer.TYPE_INT, size);
bankData = new int[1][];
bankData[0] = dataArray;
}

/** Construct a new buffer of unsigned ints using the given 2D int array. */
public UnsignedIntBuffer(int[][] dataArray, int size) {
super(DataBuffer.TYPE_INT, size);
bankData = dataArray;
}

/* @see java.awt.image.DataBuffer.getData() */
public int[] getData() {
return bankData[0];
}

/* @see java.awt.image.DataBuffer#getData(int) */
public int[] getData(int bank) {
return bankData[bank];
}

/* @see java.awt.image.DataBuffer#getElem(int) */
public int getElem(int i) {
return getElem(0, i);
}

/* @see java.awt.image.DataBuffer#getElem(int, int) */
public int getElem(int bank, int i) {
int value = bankData[bank][i + getOffsets()[bank]];
return (int) (value & 0xffffffffL);
}

/* @see java.awt.image.DataBuffer#getElemFloat(int) */
public float getElemFloat(int i) {
return getElemFloat(0, i);
}

/* @see java.awt.image.DataBuffer#getElemFloat(int, int) */
public float getElemFloat(int bank, int i) {
return (float) (getElem(bank, i) & 0xffffffffL);
}

/* @see java.awt.image.DataBuffer#getElemDouble(int) */
public double getElemDouble(int i) {
return getElemDouble(0, i);
}

/* @see java.awt.image.DataBuffer#getElemDouble(int, int) */
public double getElemDouble(int bank, int i) {
return (double) (getElem(bank, i) & 0xffffffffL);
}

/* @see java.awt.image.DataBuffer#setElem(int, int) */
public void setElem(int i, int val) {
setElem(0, i, val);
}

/* @see java.awt.image.DataBuffer#setElem(int, int, int) */
public void setElem(int bank, int i, int val) {
bankData[bank][i + getOffsets()[bank]] = val;
}

/* @see java.awt.image.DataBuffer#setElemFloat(int, float) */
public void setElemFloat(int i, float val) {
setElemFloat(0, i, val);
}

/* @see java.awt.image.DataBuffer#setElemFloat(int, int, float) */
public void setElemFloat(int bank, int i, float val) {
bankData[bank][i + getOffsets()[bank]] = (int) val;
}

/* @see java.awt.image.DataBuffer#setElemDouble(int, double) */
public void setElemDouble(int i, double val) {
setElemDouble(0, i, val);
}

/* @see java.awt.image.DataBuffer#setElemDouble(int, int, double) */
public void setElemDouble(int bank, int i, double val) {
bankData[bank][i + getOffsets()[bank]] = (int) val;
}

}
162 changes: 162 additions & 0 deletions components/bio-formats/src/loci/formats/UnsignedIntColorModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
//
// UnsignedIntColorModel.java
//

/*
OME Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ UW-Madison LOCI and Glencoe Software, Inc.
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 loci.formats;

import java.awt.image.*;
import java.io.IOException;

/**
* ColorModel that handles unsigned 32 bit data.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/components/bio-formats/src/loci/formats/UnsignedIntColorModel.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/components/bio-formats/src/loci/formats/UnsignedIntColorModel.java">SVN</a></dd></dl>
*/
public class UnsignedIntColorModel extends ColorModel {

// -- Fields --

private int pixelBits;
private int nChannels;
private ComponentColorModel helper;

// -- Constructors --

public UnsignedIntColorModel(int pixelBits, int dataType, int nChannels)
throws IOException
{
super(pixelBits, makeBitArray(nChannels, pixelBits),
AWTImageTools.makeColorSpace(nChannels), nChannels == 4, false,
ColorModel.TRANSLUCENT, dataType);

helper = new ComponentColorModel(AWTImageTools.makeColorSpace(nChannels),
nChannels == 4, false, ColorModel.TRANSLUCENT, dataType);

this.pixelBits = pixelBits;
this.nChannels = nChannels;
}

// -- ColorModel API methods --

/* @see java.awt.image.ColorModel#getDataElements(int, Object) */
public synchronized Object getDataElements(int rgb, Object pixel) {
return helper.getDataElements(rgb, pixel);
}

/* @see java.awt.image.ColorModel#isCompatibleRaster(Raster) */
public boolean isCompatibleRaster(Raster raster) {
return raster.getNumBands() == getNumComponents() &&
raster.getTransferType() == getTransferType();
}

/* @see java.awt.image.ColorModel#createCompatibleWritableRaster(int, int) */
public WritableRaster createCompatibleWritableRaster(int w, int h) {
return helper.createCompatibleWritableRaster(w, h);
}

/* @see java.awt.image.ColorModel#getAlpha(int) */
public int getAlpha(int pixel) {
return (int) (Math.pow(2, 32) - 1);
}

/* @see java.awt.image.ColorModel#getBlue(int) */
public int getBlue(int pixel) {
return getComponent(pixel, 3);
}

/* @see java.awt.image.ColorModel#getGreen(int) */
public int getGreen(int pixel) {
return getComponent(pixel, 2);
}

/* @see java.awt.image.ColorModel#getRed(int) */
public int getRed(int pixel) {
return getComponent(pixel, 1);
}

/* @see java.awt.image.ColorModel#getAlpha(Object) */
public int getAlpha(Object data) {
int max = (int) Math.pow(2, 32) - 1;
if (data instanceof int[]) {
int[] i = (int[]) data;
if (i.length == 1) return getAlpha(i[0]);
return getAlpha(i.length == 4 ? i[0] : max);
}
return max;
}

/* @see java.awt.image.ColorModel#getRed(Object) */
public int getRed(Object data) {
int max = (int) Math.pow(2, 32) - 1;
if (data instanceof int[]) {
int[] i = (int[]) data;
if (i.length == 1) return getRed(i[0]);
return getRed(i.length != 4 ? i[0] : i[1]);
}
return max;
}

/* @see java.awt.image.ColorModel#getGreen(Object) */
public int getGreen(Object data) {
int max = (int) Math.pow(2, 32) - 1;
if (data instanceof int[]) {
int[] i = (int[]) data;
if (i.length == 1) return getGreen(i[0]);
return getGreen(i.length != 4 ? i[1] : i[2]);
}
return max;
}

/* @see java.awt.image.ColorModel#getBlue(Object) */
public int getBlue(Object data) {
int max = (int) Math.pow(2, 32) - 1;
if (data instanceof int[]) {
int[] i = (int[]) data;
if (i.length == 1) return getBlue(i[0]);
return getBlue(i[i.length - 1]);
}
return max;
}

// -- Helper methods --

private int getComponent(int pixel, int index) {
long v = pixel & 0xffffffffL;
if (nChannels == 1) {
double f = v / (Math.pow(2, 32) - 1);
return (int) (255 * f);
}
int shift = (nChannels - index) * 8;
return (int) (v & (0xff << shift)) >> shift;
}

private static int[] makeBitArray(int nChannels, int nBits) {
int[] bits = new int[nChannels];
for (int i=0; i<bits.length; i++) {
bits[i] = nBits;
}
return bits;
}

}

0 comments on commit 69cec13

Please sign in to comment.