Author: damjan
Date: Wed Mar 30 17:12:08 2011
New Revision: 1087018
URL: http://svn.apache.org/viewvc?rev=1087018&view=rev
Log:
Added support for reading and writing WBMP images,
and the relevant tests.
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java
(with props)
commons/proper/sanselan/trunk/src/test/data/images/wbmp/
commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/
commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/Oregon Scientific
DS6639 - DSC_0307 - small.wbmp (with props)
commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt (with
props)
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java
(with props)
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java
(with props)
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageFormat.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/roundtrip/RoundtripTest.java
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageFormat.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageFormat.java?rev=1087018&r1=1087017&r2=1087018&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageFormat.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageFormat.java
Wed Mar 30 17:12:08 2011
@@ -73,6 +73,7 @@ public class ImageFormat
public static final ImageFormat IMAGE_FORMAT_TGA = new ImageFormat("TGA");
public static final ImageFormat IMAGE_FORMAT_JBIG2 = new
ImageFormat("JBig2");
public static final ImageFormat IMAGE_FORMAT_ICNS = new
ImageFormat("ICNS");
+ public static final ImageFormat IMAGE_FORMAT_WBMP = new
ImageFormat("WBMP");
public static final ImageFormat[] getAllFormats()
{
@@ -81,7 +82,7 @@ public class ImageFormat
IMAGE_FORMAT_TIFF, IMAGE_FORMAT_JPEG, IMAGE_FORMAT_BMP,
IMAGE_FORMAT_PSD, IMAGE_FORMAT_PBM, IMAGE_FORMAT_PGM,
IMAGE_FORMAT_PPM, IMAGE_FORMAT_PNM, IMAGE_FORMAT_TGA,
- IMAGE_FORMAT_JBIG2, IMAGE_FORMAT_ICNS,
+ IMAGE_FORMAT_JBIG2, IMAGE_FORMAT_ICNS, IMAGE_FORMAT_WBMP,
};
return result;
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java?rev=1087018&r1=1087017&r2=1087018&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/ImageParser.java
Wed Mar 30 17:12:08 2011
@@ -42,6 +42,7 @@ import org.apache.sanselan.formats.png.P
import org.apache.sanselan.formats.pnm.PNMImageParser;
import org.apache.sanselan.formats.psd.PsdImageParser;
import org.apache.sanselan.formats.tiff.TiffImageParser;
+import org.apache.sanselan.formats.wbmp.WbmpImageParser;
import org.apache.sanselan.util.Debug;
public abstract class ImageParser extends BinaryFileParser implements
@@ -54,7 +55,7 @@ public abstract class ImageParser extend
new PngImageParser(), new BmpImageParser(),
new GifImageParser(), new PsdImageParser(),
new PNMImageParser(), new IcoImageParser(),
- new IcnsImageParser(),
+ new IcnsImageParser(), new WbmpImageParser(),
// new JBig2ImageParser(),
// new TgaImageParser(),
};
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java?rev=1087018&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java
Wed Mar 30 17:12:08 2011
@@ -0,0 +1,323 @@
+/*
+ * Licensed 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.
+ * under the License.
+ */
+
+package org.apache.sanselan.formats.wbmp;
+
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.IndexColorModel;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import org.apache.sanselan.ImageFormat;
+import org.apache.sanselan.ImageInfo;
+import org.apache.sanselan.ImageParser;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.ImageWriteException;
+import org.apache.sanselan.common.IImageMetadata;
+import org.apache.sanselan.common.byteSources.ByteSource;
+
+public class WbmpImageParser extends ImageParser
+{
+ public WbmpImageParser()
+ {
+ }
+
+ public String getName()
+ {
+ return "Wbmp-Custom";
+ }
+
+ public String getDefaultExtension()
+ {
+ return DEFAULT_EXTENSION;
+ }
+ private static final String DEFAULT_EXTENSION = ".wbmp";
+ private static final String ACCEPTED_EXTENSIONS[] =
+ {
+ ".wbmp",
+ };
+
+ protected String[] getAcceptedExtensions()
+ {
+ return ACCEPTED_EXTENSIONS;
+ }
+
+ protected ImageFormat[] getAcceptedTypes()
+ {
+ return new ImageFormat[]
+ {
+ ImageFormat.IMAGE_FORMAT_WBMP, //
+ };
+ }
+
+ public boolean embedICCProfile(File src, File dst, byte profile[])
+ {
+ return false;
+ }
+
+ public IImageMetadata getMetadata(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ return null;
+ }
+
+ public ImageInfo getImageInfo(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
+ return new ImageInfo("WBMP", 1, new ArrayList(),
+ ImageFormat.IMAGE_FORMAT_WBMP,
+ "Wireless Application Protocol Bitmap",
+ wbmpHeader.height, "image/vnd.wap.wbmp", 1,
+ 0, 0, 0, 0,
+ wbmpHeader.width, false, false, false,
+ ImageInfo.COLOR_TYPE_BW,
+ ImageInfo.COMPRESSION_ALGORITHM_NONE);
+ }
+
+ public Dimension getImageSize(ByteSource byteSource,
+ Map params)
+ throws ImageReadException, IOException
+ {
+ WbmpHeader wbmpHeader = readWbmpHeader(byteSource);
+ return new Dimension(wbmpHeader.width, wbmpHeader.height);
+ }
+
+ public byte[] getICCProfileBytes(ByteSource byteSource,
+ Map params)
+ throws ImageReadException, IOException
+ {
+ return null;
+ }
+
+ static class WbmpHeader
+ {
+ int typeField;
+ byte fixHeaderField;
+ int width;
+ int height;
+
+ public WbmpHeader(int typeField, byte fixHeaderField, int width, int
height)
+ {
+ this.typeField = typeField;
+ this.fixHeaderField = fixHeaderField;
+ this.width = width;
+ this.height = height;
+ }
+
+ public void dump(PrintWriter pw)
+ {
+ pw.println("WbmpHeader");
+ pw.println("TypeField: " + typeField);
+ pw.println("FixHeaderField: 0x" + Integer.toHexString(0xff &
fixHeaderField));
+ pw.println("Width: " + width);
+ pw.println("Height: " + height);
+ }
+ }
+
+ private int readMultiByteInteger(InputStream is)
+ throws ImageReadException, IOException
+ {
+ int value = 0;
+ int nextByte;
+ int totalBits = 0;
+ do
+ {
+ nextByte = readByte("Header", is, "Error reading WBMP header");
+ value <<= 7;
+ value |= nextByte & 0x7f;
+ totalBits += 7;
+ if (totalBits > 31)
+ throw new ImageReadException("Overflow reading WBMP multi-byte
field");
+ } while ((nextByte & 0x80) != 0);
+ return value;
+ }
+
+ private void writeMultiByteInteger(OutputStream os, int value)
+ throws ImageWriteException, IOException
+ {
+ boolean wroteYet = false;
+ for (int position = 4*7; position > 0; position -= 7)
+ {
+ int next7Bits = 0x7f & (value >>> position);
+ if (next7Bits != 0 || wroteYet)
+ {
+ os.write(0x80 | next7Bits);
+ wroteYet = true;
+ }
+ }
+ os.write(0x7f & value);
+ }
+
+ private WbmpHeader readWbmpHeader(ByteSource byteSource)
+ throws ImageReadException, IOException
+ {
+ InputStream is = null;
+ try
+ {
+ is = byteSource.getInputStream();
+ return readWbmpHeader(is);
+ }
+ finally
+ {
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ }
+
+ private WbmpHeader readWbmpHeader(InputStream is)
+ throws ImageReadException, IOException
+ {
+ int typeField = readMultiByteInteger(is);
+ if (typeField != 0)
+ throw new ImageReadException("Invalid/unsupported WBMP type " +
typeField);
+
+ byte fixHeaderField = readByte("FixHeaderField", is, "Invalid WBMP
File");
+ if ((fixHeaderField & 0x9f) != 0)
+ throw new ImageReadException("Invalid/unsupported WBMP
FixHeaderField 0x" +
+ Integer.toHexString(0xff & fixHeaderField));
+
+ int width = readMultiByteInteger(is);
+
+ int height = readMultiByteInteger(is);
+
+ return new WbmpHeader(typeField, fixHeaderField, width, height);
+ }
+
+ public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
+ throws ImageReadException, IOException
+ {
+ readWbmpHeader(byteSource).dump(pw);
+ return true;
+ }
+
+ private BufferedImage readImage(WbmpHeader wbmpHeader, InputStream is)
+ throws ImageReadException, IOException
+ {
+ int rowLength = (wbmpHeader.width + 7) / 8;
+ byte[] image = readByteArray("Pixels", rowLength * wbmpHeader.height,
is,
+ "Error reading image pixels");
+ DataBufferByte dataBuffer = new DataBufferByte(image, image.length);
+ WritableRaster raster = WritableRaster.createPackedRaster(dataBuffer,
+ wbmpHeader.width, wbmpHeader.height, 1, null);
+ int[] palette = {0x000000, 0xffffff};
+ IndexColorModel colorModel = new IndexColorModel(1, 2, palette, 0,
+ false, -1, DataBuffer.TYPE_BYTE);
+ return new BufferedImage(colorModel, raster,
+ colorModel.isAlphaPremultiplied(), new Properties());
+ }
+
+ public final BufferedImage getBufferedImage(ByteSource byteSource,
+ Map params) throws ImageReadException, IOException
+ {
+ InputStream is = null;
+ try
+ {
+ is = byteSource.getInputStream();
+ WbmpHeader wbmpHeader = readWbmpHeader(is);
+ return readImage(wbmpHeader, is);
+ }
+ finally
+ {
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (IOException ignored)
+ {
+ }
+ }
+ }
+
+ public void writeImage(BufferedImage src, OutputStream os, Map params)
+ throws ImageWriteException, IOException
+ {
+ // make copy of params; we'll clear keys as we consume them.
+ params = (params == null) ? new HashMap() : new HashMap(params);
+
+ // clear format key.
+ if (params.containsKey(PARAM_KEY_FORMAT))
+ params.remove(PARAM_KEY_FORMAT);
+
+ if (params.size() > 0)
+ {
+ Object firstKey = params.keySet().iterator().next();
+ throw new ImageWriteException("Unknown parameter: " + firstKey);
+ }
+
+ writeMultiByteInteger(os, 0); // typeField
+ os.write(0); // fixHeaderField
+ writeMultiByteInteger(os, src.getWidth());
+ writeMultiByteInteger(os, src.getHeight());
+
+ for (int y = 0; y < src.getHeight(); y++)
+ {
+ int pixel = 0;
+ int nextBit = 0x80;
+ for (int x = 0; x < src.getWidth(); x++)
+ {
+ int argb = src.getRGB(x, y);
+ int red = 0xff & (argb >> 16);
+ int green = 0xff & (argb >> 8);
+ int blue = 0xff & (argb >> 0);
+ int sample = (red + green + blue) / 3;
+ if (sample > 127)
+ pixel |= nextBit;
+ nextBit >>>= 1;
+ if (nextBit == 0)
+ {
+ os.write(pixel);
+ pixel = 0;
+ nextBit = 0x80;
+ }
+ }
+ if (nextBit != 0x80)
+ os.write(pixel);
+ }
+ }
+
+ /**
+ * Extracts embedded XML metadata as XML string.
+ * <p>
+ *
+ * @param byteSource
+ * File containing image data.
+ * @param params
+ * Map of optional parameters, defined in SanselanConstants.
+ * @return Xmp Xml as String, if present. Otherwise, returns null.
+ */
+ public String getXmpXml(ByteSource byteSource, Map params)
+ throws ImageReadException, IOException
+ {
+ return null;
+ }
+}
Propchange:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/wbmp/WbmpImageParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/Oregon
Scientific DS6639 - DSC_0307 - small.wbmp
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/Oregon%20Scientific%20DS6639%20-%20DSC_0307%20-%20small.wbmp?rev=1087018&view=auto
==============================================================================
Binary file - no diff available.
Propchange: commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/Oregon
Scientific DS6639 - DSC_0307 - small.wbmp
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt?rev=1087018&view=auto
==============================================================================
--- commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt (added)
+++ commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt Wed Mar
30 17:12:08 2011
@@ -0,0 +1,2 @@
+Contributed to the project by Damjan Jovanovic.
+Converted from ../../pxm/1/Oregon Scientific DS6639 - DSC_0307 - small.pbm
Propchange: commons/proper/sanselan/trunk/src/test/data/images/wbmp/1/info.txt
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java?rev=1087018&r1=1087017&r2=1087018&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java
(original)
+++
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/common/byteSources/ByteSourceImageTest.java
Wed Mar 30 17:12:08 2011
@@ -59,7 +59,8 @@ public class ByteSourceImageTest extends
if (imageFile.getName().toLowerCase().endsWith(".ico")
|| imageFile.getName().toLowerCase().endsWith(".tga")
|| imageFile.getName().toLowerCase().endsWith(".jb2")
- || imageFile.getName().toLowerCase().endsWith(".psd"))
+ || imageFile.getName().toLowerCase().endsWith(".psd")
+ || imageFile.getName().toLowerCase().endsWith(".wbmp"))
{
// these formats can't be parsed without a filename hint.
// they have ambiguous "magic number" signatures.
Added:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java?rev=1087018&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java
(added)
+++
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java
Wed Mar 30 17:12:08 2011
@@ -0,0 +1,42 @@
+/*
+ * Licensed 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.
+ * under the License.
+ */
+
+package org.apache.sanselan.formats.wbmp;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.SanselanTest;
+
+public abstract class WbmpBaseTest extends SanselanTest
+{
+ private static boolean isWbmp(File file) throws IOException,
ImageReadException
+ {
+ return file.getName().toLowerCase().endsWith(".wbmp");
+ }
+
+ private static final ImageFilter IMAGE_FILTER = new ImageFilter() {
+ public boolean accept(File file) throws IOException, ImageReadException
+ {
+ return isWbmp(file);
+ }
+ };
+
+ protected List getWbmpImages() throws IOException, ImageReadException
+ {
+ return getTestImages(IMAGE_FILTER);
+ }
+}
Propchange:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpBaseTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java?rev=1087018&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java
(added)
+++
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java
Wed Mar 30 17:12:08 2011
@@ -0,0 +1,58 @@
+/*
+ * Licensed 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.
+ * under the License.
+ */
+
+package org.apache.sanselan.formats.wbmp;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.sanselan.ImageInfo;
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.Sanselan;
+import org.apache.sanselan.common.IImageMetadata;
+import org.apache.sanselan.util.Debug;
+
+public class WbmpReadTest extends WbmpBaseTest
+{
+
+ public void test() throws IOException, ImageReadException
+ {
+ Debug.debug("start");
+
+ List images = getWbmpImages();
+ for (int i = 0; i < images.size(); i++)
+ {
+ if (i % 10 == 0)
+ Debug.purgeMemory();
+
+ File imageFile = (File) images.get(i);
+ Debug.debug("imageFile", imageFile);
+
+ IImageMetadata metadata = Sanselan.getMetadata(imageFile);
+ // assertNotNull(metadata);
+
+ Map params = new HashMap();
+ ImageInfo imageInfo = Sanselan.getImageInfo(imageFile, params);
+ assertNotNull(imageInfo);
+
+ BufferedImage image = Sanselan.getBufferedImage(imageFile);
+ assertNotNull(image);
+ }
+ }
+
+}
Propchange:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/formats/wbmp/WbmpReadTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/roundtrip/RoundtripTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/roundtrip/RoundtripTest.java?rev=1087018&r1=1087017&r2=1087018&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/roundtrip/RoundtripTest.java
(original)
+++
commons/proper/sanselan/trunk/src/test/java/org/apache/sanselan/roundtrip/RoundtripTest.java
Wed Mar 30 17:12:08 2011
@@ -86,6 +86,8 @@ public class RoundtripTest extends Sanse
// COLOR_FULL_RGB, true), //
new FormatInfo(ImageFormat.IMAGE_FORMAT_TGA, false, false,
COLOR_FULL_RGB, true), //
+ new FormatInfo(ImageFormat.IMAGE_FORMAT_WBMP, true, true,
+ COLOR_BITMAP, true), //
};
private BufferedImage createArgbBitmapImage(int width, int height)