mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-10-04 11:26:44 -04:00
It all works
This commit is contained in:
25
imageio/imageio-thumbsdb/license.txt
Executable file
25
imageio/imageio-thumbsdb/license.txt
Executable file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2009, Harald Kuhr
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name "TwelveMonkeys" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
imageio/imageio-thumbsdb/pom.xml
Normal file
31
imageio/imageio-thumbsdb/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>twelvemonkeys-imageio-thumbsdb</artifactId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
<name>TwelveMonkeys ImageIO Thumbs.db plugin</name>
|
||||
<description>
|
||||
ImageIO plugin for Windows Thumbs DB (Thumbs.db) format.
|
||||
</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>twelvemonkeys-imageio</artifactId>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<version>2.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>twelvemonkeys-imageio-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>twelvemonkeys-imageio-core</artifactId>
|
||||
<classifier>tests</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.thumbsdb;
|
||||
|
||||
import com.twelvemonkeys.io.LittleEndianDataInputStream;
|
||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.DataInput;
|
||||
import java.util.Iterator;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Represents a {@code Catalog} structure, typically found in a {@link com.twelvemonkeys.io.ole2.CompoundDocument}.
|
||||
*
|
||||
* @see <a href="http://www.petedavis.net/MySite/DynPageView.aspx?pageid=31">PeteDavis.NET</a>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku$
|
||||
* @version $Id: Catalog.java,v 1.0 01.feb.2007 17:19:59 haku Exp$
|
||||
*/
|
||||
// TODO: Consider moving this one to io.ole2
|
||||
public final class Catalog implements Iterable<Catalog.CatalogItem> {
|
||||
|
||||
private final CatalogHeader mHeader;
|
||||
private final CatalogItem[] mItems;
|
||||
|
||||
Catalog(final CatalogHeader pHeader, final CatalogItem[] pItems) {
|
||||
mHeader = pHeader;
|
||||
mItems = pItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the {@code Catalog} entry from the given input stream.
|
||||
*
|
||||
* @param pInput the input stream
|
||||
* @return a new {@code Catalog}
|
||||
*
|
||||
* @throws java.io.IOException if an I/O exception occurs during read
|
||||
*/
|
||||
public static Catalog read(final InputStream pInput) throws IOException {
|
||||
DataInput dataInput = new LittleEndianDataInputStream(pInput);
|
||||
return read(dataInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the {@code Catalog} entry from the given input stream.
|
||||
* <p/>
|
||||
* The data is assumed to be in little endian byte order.
|
||||
*
|
||||
* @param pDataInput the input stream
|
||||
* @return a new {@code Catalog}
|
||||
*
|
||||
* @throws java.io.IOException if an I/O exception occurs during read
|
||||
*/
|
||||
public static Catalog read(final DataInput pDataInput) throws IOException {
|
||||
CatalogHeader header = CatalogHeader.read(pDataInput);
|
||||
|
||||
CatalogItem[] items = new CatalogItem[header.getThumbnailCount()];
|
||||
for (int i = 0; i < header.getThumbnailCount(); i++) {
|
||||
CatalogItem item = CatalogItem.read(pDataInput);
|
||||
//System.out.println("item: " + item);
|
||||
items[item.getItemId() - 1] = item;
|
||||
}
|
||||
|
||||
return new Catalog(header, items);
|
||||
}
|
||||
|
||||
public final int getThumbnailCount() {
|
||||
return mHeader.mThumbCount;
|
||||
}
|
||||
|
||||
public final int getMaxThumbnailWidth() {
|
||||
return mHeader.mThumbWidth;
|
||||
}
|
||||
|
||||
public final int getMaxThumbnailHeight() {
|
||||
return mHeader.mThumbHeight;
|
||||
}
|
||||
|
||||
final CatalogItem getItem(final int pIndex) {
|
||||
return mItems[pIndex];
|
||||
}
|
||||
|
||||
final CatalogItem getItem(final String pName) {
|
||||
return mItems[getIndex(pName)];
|
||||
}
|
||||
|
||||
final int getItemId(final int pIndex) {
|
||||
return mItems[pIndex].getItemId();
|
||||
}
|
||||
|
||||
public final int getIndex(final String pName) {
|
||||
for (int i = 0; i < mItems.length; i++) {
|
||||
CatalogItem item = mItems[i];
|
||||
|
||||
if (item.getName().equals(pName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public final String getStreamName(final int pIndex) {
|
||||
return StringUtil.reverse(String.valueOf(getItemId(pIndex)));
|
||||
}
|
||||
|
||||
public final String getName(String pStreamName) {
|
||||
return getName(Integer.parseInt(StringUtil.reverse(pStreamName)));
|
||||
}
|
||||
|
||||
final String getName(int pItemId) {
|
||||
return mItems[pItemId - 1].getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s[%s]", getClass().getSimpleName(), mHeader);
|
||||
}
|
||||
|
||||
public Iterator<CatalogItem> iterator() {
|
||||
return new Iterator<CatalogItem>() {
|
||||
int mCurrentIdx;
|
||||
|
||||
public boolean hasNext() {
|
||||
return mCurrentIdx < mItems.length;
|
||||
}
|
||||
|
||||
public CatalogItem next() {
|
||||
return mItems[mCurrentIdx++];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Remove not supported");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class CatalogHeader {
|
||||
short mReserved1;
|
||||
short mReserved2;
|
||||
int mThumbCount;
|
||||
int mThumbWidth;
|
||||
int mThumbHeight;
|
||||
|
||||
CatalogHeader() {
|
||||
}
|
||||
|
||||
public static CatalogHeader read(final DataInput pDataInput) throws IOException {
|
||||
CatalogHeader header = new CatalogHeader();
|
||||
|
||||
header.mReserved1 = pDataInput.readShort();
|
||||
header.mReserved2 = pDataInput.readShort();
|
||||
header.mThumbCount = pDataInput.readInt();
|
||||
header.mThumbWidth = pDataInput.readInt();
|
||||
header.mThumbHeight = pDataInput.readInt();
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
public int getThumbnailCount() {
|
||||
return mThumbCount;
|
||||
}
|
||||
|
||||
public int getThumbHeight() {
|
||||
return mThumbHeight;
|
||||
}
|
||||
|
||||
public int getThumbWidth() {
|
||||
return mThumbWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"%s: %s %s thumbs: %d maxWidth: %d maxHeight: %d",
|
||||
getClass().getSimpleName(), mReserved1, mReserved2, mThumbCount, mThumbWidth, mThumbHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CatalogItem {
|
||||
int mReserved1;
|
||||
int mItemId; // Reversed stream name
|
||||
String mFilename;
|
||||
short mReserved2;
|
||||
private long mLastModified;
|
||||
|
||||
private static CatalogItem read(final DataInput pDataInput) throws IOException {
|
||||
CatalogItem item = new CatalogItem();
|
||||
item.mReserved1 = pDataInput.readInt();
|
||||
item.mItemId = pDataInput.readInt();
|
||||
|
||||
item.mLastModified = CompoundDocument.toJavaTimeInMillis(pDataInput.readLong());
|
||||
|
||||
char[] chars = new char[256];
|
||||
char ch;
|
||||
int len = 0;
|
||||
while ((ch = pDataInput.readChar()) != 0) {
|
||||
chars[len++] = ch;
|
||||
}
|
||||
|
||||
String name = new String(chars, 0, len);
|
||||
item.mFilename = StringUtil.getLastElement(name, "\\");
|
||||
|
||||
item.mReserved2 = pDataInput.readShort();
|
||||
return item;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return mItemId;
|
||||
}
|
||||
|
||||
public long lastModified() {
|
||||
return mLastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"%s: %d itemId: %d lastModified: %s fileName: %s %s",
|
||||
getClass().getSimpleName(), mReserved1, mItemId, new Date(mLastModified), mFilename, mReserved2
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.thumbsdb;
|
||||
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||
import com.twelvemonkeys.io.ole2.Entry;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Iterator;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
* ThumbsDBImageReader
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku$
|
||||
* @version $Id: ThumbsDBImageReader.java,v 1.0 22.jan.2007 18:49:38 haku Exp$
|
||||
* @see com.twelvemonkeys.io.ole2.CompoundDocument
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Thumbs.db>Wikipedia: Thumbs.db</a>
|
||||
*/
|
||||
public class ThumbsDBImageReader extends ImageReaderBase {
|
||||
private static final int THUMBNAIL_OFFSET = 12;
|
||||
private Entry mRoot;
|
||||
private Catalog mCatalog;
|
||||
|
||||
private BufferedImage[] mThumbnails;
|
||||
private final ImageReader mReader;
|
||||
private int mCurrentImage = -1;
|
||||
|
||||
private boolean mLoadEagerly;
|
||||
|
||||
public ThumbsDBImageReader() {
|
||||
this(new ThumbsDBImageReaderSpi());
|
||||
}
|
||||
|
||||
protected ThumbsDBImageReader(final ThumbsDBImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
mReader = createJPEGReader(pProvider);
|
||||
initReaderListeners();
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
mRoot = null;
|
||||
mCatalog = null;
|
||||
mThumbnails = null;
|
||||
}
|
||||
|
||||
private static ImageReader createJPEGReader(final ThumbsDBImageReaderSpi pProvider) {
|
||||
return pProvider.createJPEGReader();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
mReader.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public boolean isLoadEagerly() {
|
||||
return mLoadEagerly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the reader wether it should read and cache alle thumbnails
|
||||
* in sequence, during the first read operation.
|
||||
* <p/>
|
||||
* This is useful mainly if you need to read all the thumbnails, and you
|
||||
* need them in random order, as it requires less repositioning in the
|
||||
* underlying stream.
|
||||
*
|
||||
* @param pLoadEagerly {@code true} if the reader should read all thumbs on first read
|
||||
*/
|
||||
public void setLoadEagerly(final boolean pLoadEagerly) {
|
||||
mLoadEagerly = pLoadEagerly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the image data from the given input stream, and returns it as a
|
||||
* {@code BufferedImage}.
|
||||
*
|
||||
* @param pIndex the index of the image to read
|
||||
* @param pParam additional parameters used while decoding, may be
|
||||
* {@code null}, in which case defaults will be used
|
||||
* @return a {@code BufferedImage}
|
||||
* @throws IndexOutOfBoundsException if {@code pIndex} is out of bounds
|
||||
* @throws IllegalStateException if the input source has not been set
|
||||
* @throws java.io.IOException if an error occurs during reading
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage read(final int pIndex, final ImageReadParam pParam) throws IOException {
|
||||
init();
|
||||
checkBounds(pIndex);
|
||||
|
||||
// Quick look-up
|
||||
BufferedImage image = null;
|
||||
if (pIndex < mThumbnails.length) {
|
||||
image = mThumbnails[pIndex];
|
||||
}
|
||||
|
||||
if (image == null) {
|
||||
// Read the image, it's a JFIF stream, inside the OLE 2 CompoundDocument
|
||||
init(pIndex);
|
||||
|
||||
image = mReader.read(0, pParam);
|
||||
mReader.reset();
|
||||
|
||||
if (pParam == null) {
|
||||
mThumbnails[pIndex] = image; // TODO: Caching is not kosher, as images are mutable!!
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Keep progress listeners happy
|
||||
processImageStarted(pIndex);
|
||||
processImageProgress(100);
|
||||
processImageComplete();
|
||||
}
|
||||
|
||||
// Fake destination support
|
||||
if (pParam != null && (pParam.getDestination() != null && pParam.getDestination() != image ||
|
||||
pParam.getDestinationType() != null && pParam.getDestinationType().getBufferedImageType() != image.getType())) {
|
||||
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), getWidth(pIndex), getHeight(pIndex));
|
||||
|
||||
Graphics2D g = destination.createGraphics();
|
||||
try {
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(image, 0, 0, null);
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
image = destination;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the image data from the given input stream, and returns it as a
|
||||
* {@code BufferedImage}.
|
||||
*
|
||||
* @param pName the name of the image to read
|
||||
* @param pParam additional parameters used while decoding, may be
|
||||
* {@code null}, in which case defaults will be used
|
||||
* @return a {@code BufferedImage}
|
||||
* @throws java.io.FileNotFoundException if the given file name is not found in the
|
||||
* "Catalog" entry of the {@code CompoundDocument}
|
||||
* @throws IllegalStateException if the input source has not been set
|
||||
* @throws java.io.IOException if an error occurs during reading
|
||||
*/
|
||||
public BufferedImage read(final String pName, final ImageReadParam pParam) throws IOException {
|
||||
initCatalog();
|
||||
|
||||
int index = mCatalog.getIndex(pName);
|
||||
if (index < 0) {
|
||||
throw new FileNotFoundException("Name not found in \"Catalog\" entry: " + pName);
|
||||
}
|
||||
|
||||
return read(index, pParam);
|
||||
}
|
||||
|
||||
public void abort() {
|
||||
super.abort();
|
||||
mReader.abort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) {
|
||||
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
|
||||
if (mImageInput != null) {
|
||||
mImageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
}
|
||||
|
||||
private void init(final int pIndex) throws IOException {
|
||||
if (mCurrentImage == -1 || pIndex != mCurrentImage || mReader.getInput() == null) {
|
||||
init();
|
||||
checkBounds(pIndex);
|
||||
mCurrentImage = pIndex;
|
||||
|
||||
initReader(pIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void initReader(final int pIndex) throws IOException {
|
||||
String name = mCatalog.getStreamName(pIndex);
|
||||
Entry entry = mRoot.getChildEntry(name);
|
||||
// TODO: It might be possible to speed this up, with less wrapping...
|
||||
// Use in-memory input stream for max speed, images are small
|
||||
ImageInputStream input = new MemoryCacheImageInputStream(entry.getInputStream());
|
||||
input.skipBytes(THUMBNAIL_OFFSET);
|
||||
mReader.setInput(input);
|
||||
}
|
||||
|
||||
private void initReaderListeners() {
|
||||
mReader.addIIOReadProgressListener(new ProgressListenerBase() {
|
||||
@Override
|
||||
public void imageComplete(ImageReader pSource) {
|
||||
processImageComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void imageStarted(ImageReader pSource, int pImageIndex) {
|
||||
processImageStarted(mCurrentImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void imageProgress(ImageReader pSource, float pPercentageDone) {
|
||||
processImageProgress(pPercentageDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAborted(ImageReader pSource) {
|
||||
processReadAborted();
|
||||
}
|
||||
});
|
||||
// TODO: Update listeners
|
||||
// TODO: Warning listeners
|
||||
}
|
||||
|
||||
private void init() throws IOException {
|
||||
assertInput();
|
||||
if (mRoot == null) {
|
||||
mRoot = new CompoundDocument(mImageInput).getRootEntry();
|
||||
SortedSet children = mRoot.getChildEntries();
|
||||
|
||||
mThumbnails = new BufferedImage[children.size() - 1];
|
||||
|
||||
initCatalog();
|
||||
|
||||
// NOTE: This is usually slower, unless you need all images
|
||||
// TODO: Use as many threads as there are CPU cores? :-)
|
||||
if (mLoadEagerly) {
|
||||
for (int i = 0; i < mThumbnails.length; i++) {
|
||||
initReader(i);
|
||||
ImageReader reader = mReader;
|
||||
// TODO: If stream was detached, we could probably create a
|
||||
// new reader, then fire this off in a separate thread...
|
||||
mThumbnails[i] = reader.read(0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initCatalog() throws IOException {
|
||||
if (mCatalog == null) {
|
||||
Entry catalog = mRoot.getChildEntry("Catalog");
|
||||
|
||||
if (catalog.length() <= 16L) {
|
||||
// TODO: Throw exception? Return empty catalog?
|
||||
}
|
||||
|
||||
mCatalog = Catalog.read(catalog.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumImages(boolean pAllowSearch) throws IOException {
|
||||
if (pAllowSearch) {
|
||||
init();
|
||||
}
|
||||
|
||||
return mCatalog != null ? mCatalog.getThumbnailCount() : super.getNumImages(false);
|
||||
}
|
||||
|
||||
public int getWidth(int pIndex) throws IOException {
|
||||
init(pIndex);
|
||||
|
||||
BufferedImage image = mThumbnails[pIndex];
|
||||
return image != null ? image.getWidth() : mReader.getWidth(0);
|
||||
}
|
||||
|
||||
public int getHeight(int pIndex) throws IOException {
|
||||
init(pIndex);
|
||||
|
||||
BufferedImage image = mThumbnails[pIndex];
|
||||
return image != null ? image.getHeight() : mReader.getHeight(0);
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(int pIndex) throws IOException {
|
||||
init(pIndex);
|
||||
initReader(pIndex);
|
||||
return mReader.getImageTypes(0);
|
||||
}
|
||||
|
||||
public boolean isPresent(final String pFileName) {
|
||||
try {
|
||||
init();
|
||||
}
|
||||
catch (IOException e) {
|
||||
resetMembers();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Rethink this...
|
||||
// Seems to be up to Windows and the installed programs what formats
|
||||
// are supported...
|
||||
// Some thumbs are just icons, and it might be better to use ImageIO to create thumbs for these... :-/
|
||||
// At least this seems fine for now
|
||||
String extension = FileUtil.getExtension(pFileName);
|
||||
if (StringUtil.isEmpty(extension)) {
|
||||
return false;
|
||||
}
|
||||
extension = extension.toLowerCase();
|
||||
|
||||
return !"psd".equals(extension) && !"svg".equals(extension) && mCatalog != null && mCatalog.getIndex(pFileName) != -1;
|
||||
}
|
||||
|
||||
/// Test code below
|
||||
|
||||
public static void main(String[] pArgs) throws IOException {
|
||||
ThumbsDBImageReader reader = new ThumbsDBImageReader();
|
||||
reader.setInput(ImageIO.createImageInputStream(new File(pArgs[0])));
|
||||
// reader.setLoadEagerly(true);
|
||||
|
||||
if (pArgs.length > 1) {
|
||||
long start = System.currentTimeMillis();
|
||||
reader.init();
|
||||
for (Catalog.CatalogItem item : reader.mCatalog) {
|
||||
reader.read(item.getName(), null);
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Time: " + (end - start) + " ms");
|
||||
}
|
||||
else {
|
||||
JFrame frame = createWindow(pArgs[0]);
|
||||
JPanel panel = new JPanel();
|
||||
panel.setBackground(Color.WHITE);
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
reader.init();
|
||||
for (Catalog.CatalogItem item : reader.mCatalog) {
|
||||
addImage(panel, reader, reader.mCatalog.getIndex(item.getName()), item.getName());
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Time: " + (end - start) + " ms");
|
||||
|
||||
frame.getContentPane().add(new JScrollPane(panel));
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static JFrame createWindow(final String pTitle) {
|
||||
JFrame frame = new JFrame(pTitle);
|
||||
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed(WindowEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
private static void addImage(Container pParent, ImageReader pReader, int pImageNo, String pName) throws IOException {
|
||||
final JLabel label = new JLabel();
|
||||
final BufferedImage image = pReader.read(pImageNo);
|
||||
label.setIcon(new Icon() {
|
||||
private static final int SIZE = 110;
|
||||
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setColor(Color.DARK_GRAY);
|
||||
g.fillRoundRect(x, y, SIZE, SIZE, 10, 10);
|
||||
g.drawImage(image, (SIZE - image.getWidth()) / 2 + x, (SIZE - image.getHeight()) / 2 + y, null);
|
||||
}
|
||||
|
||||
public int getIconWidth() {
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
public int getIconHeight() {
|
||||
return SIZE;
|
||||
}
|
||||
});
|
||||
label.setText("" + image.getWidth() + "x" + image.getHeight() + ": " + pName);
|
||||
label.setToolTipText(image.toString());
|
||||
pParent.add(label);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.thumbsdb;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.IIORegistry;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* ThumbsDBImageReaderSpi
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: ThumbsDBImageReaderSpi.java,v 1.0 28.feb.2006 19:21:05 haku Exp$
|
||||
*/
|
||||
public class ThumbsDBImageReaderSpi extends ImageReaderSpi {
|
||||
private ImageReaderSpi mJPEGProvider;
|
||||
|
||||
/**
|
||||
* Creates a {@code ThumbsDBImageReaderSpi}.
|
||||
*/
|
||||
public ThumbsDBImageReaderSpi() {
|
||||
this(IIOUtil.getProviderInfo(ThumbsDBImageReaderSpi.class));
|
||||
}
|
||||
|
||||
private ThumbsDBImageReaderSpi(final ProviderInfo pProviderInfo) {
|
||||
super(
|
||||
pProviderInfo.getVendorName(),
|
||||
pProviderInfo.getVersion(),
|
||||
new String[]{"thumbs", "THUMBS", "Thumbs DB"},
|
||||
new String[]{"db"},
|
||||
new String[]{"image/x-thumbs-db", "application/octet-stream"}, // TODO: Check IANA et al...
|
||||
ThumbsDBImageReader.class.getName(),
|
||||
STANDARD_INPUT_TYPE,
|
||||
null,
|
||||
true, null, null, null, null,
|
||||
true, null, null, null, null
|
||||
);
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
||||
}
|
||||
|
||||
public boolean canDecode(ImageInputStream pInput) throws IOException {
|
||||
maybeInitJPEGProvider();
|
||||
// If this is a OLE 2 CompoundDocument, we could try...
|
||||
// TODO: How do we know it's thumbs.db format (structure), without reading quite a lot?
|
||||
return mJPEGProvider != null && CompoundDocument.canRead(pInput);
|
||||
}
|
||||
|
||||
public ImageReader createReaderInstance(Object extension) throws IOException {
|
||||
return new ThumbsDBImageReader(this);
|
||||
}
|
||||
|
||||
private void maybeInitJPEGProvider() {
|
||||
// NOTE: Can't do this from constructor, as ImageIO itself is not initialized yet,
|
||||
// and the lookup below will produce a NPE..
|
||||
|
||||
// TODO: A better approach...
|
||||
// - Could have a list with known working JPEG decoders?
|
||||
// - System property?
|
||||
// - Class path lookup of properties file with reader?
|
||||
// This way we could deregister immediately
|
||||
|
||||
if (mJPEGProvider == null) {
|
||||
ImageReaderSpi provider = null;
|
||||
try {
|
||||
Iterator<ImageReaderSpi> providers = getJPEGProviders();
|
||||
|
||||
while (providers.hasNext()) {
|
||||
provider = providers.next();
|
||||
|
||||
// Prefer the one we know
|
||||
if ("Sun Microsystems, Inc.".equals(provider.getVendorName())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
// It's pretty safe to assume there's always a JPEG reader out there
|
||||
// In any case, we deregister the provider if there isn't one
|
||||
IIORegistry.getDefaultInstance().deregisterServiceProvider(this, ImageReaderSpi.class);
|
||||
}
|
||||
mJPEGProvider = provider;
|
||||
}
|
||||
}
|
||||
|
||||
private Iterator<ImageReaderSpi> getJPEGProviders() {
|
||||
return IIORegistry.getDefaultInstance().getServiceProviders(
|
||||
ImageReaderSpi.class,
|
||||
new ServiceRegistry.Filter() {
|
||||
public boolean filter(Object provider) {
|
||||
if (provider instanceof ImageReaderSpi) {
|
||||
ImageReaderSpi spi = (ImageReaderSpi) provider;
|
||||
for (String format : spi.getFormatNames()) {
|
||||
if ("JPEG".equals(format)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code ImageReader} that can read JPEG images.
|
||||
*
|
||||
* @return a new {@code ImageReader} that can read JPEG images.
|
||||
* @throws IllegalStateException if no JPEG provider was found
|
||||
* @throws Error if the reader can't be instantiated
|
||||
*/
|
||||
ImageReader createJPEGReader() {
|
||||
maybeInitJPEGProvider();
|
||||
if (mJPEGProvider == null) {
|
||||
throw new IllegalStateException("No suitable JPEG reader provider found");
|
||||
}
|
||||
|
||||
try {
|
||||
return mJPEGProvider.createReaderInstance();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// NOTE: The default Sun version never throws IOException here
|
||||
throw new Error("Could not create JPEG reader: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription(Locale locale) {
|
||||
return "Microsoft Windows Thumbs DB (Thumbs.db) image reader";
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||
// System.out.println("ThumbsDBImageReaderSpi.onRegistration");
|
||||
// maybeInitJPEGProvider();
|
||||
// if (mJPEGProvider == null) {
|
||||
// System.out.println("Deregistering");
|
||||
// registry.deregisterServiceProvider(this, ImageReaderSpi.class);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
com.twelvemonkeys.imageio.plugins.thumbsdb.ThumbsDBImageReaderSpi
|
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.thumbsdb;
|
||||
|
||||
import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
|
||||
import com.twelvemonkeys.io.ole2.CompoundDocument;
|
||||
import com.twelvemonkeys.io.ole2.Entry;
|
||||
import com.twelvemonkeys.lang.SystemUtil;
|
||||
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ICOImageReaderTestCase
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ICOImageReaderTestCase.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
|
||||
*/
|
||||
public class ThumbsDBImageReaderTestCase extends ImageReaderAbstractTestCase<ThumbsDBImageReader> {
|
||||
private static final boolean IS_JAVA_6 = SystemUtil.isClassAvailable("java.util.Deque");
|
||||
|
||||
private ThumbsDBImageReaderSpi mProvider = new ThumbsDBImageReaderSpi();
|
||||
|
||||
protected List<TestData> getTestData() {
|
||||
return Arrays.asList(
|
||||
new TestData(
|
||||
getClassLoaderResource("/thumbsdb/Thumbs.db"),
|
||||
new Dimension(96, 96), new Dimension(96, 96), new Dimension(16, 16),
|
||||
new Dimension(96, 45), new Dimension(63, 96), new Dimension(96, 96),
|
||||
new Dimension(96, 64), new Dimension(96, 96), new Dimension(96, 77)
|
||||
),
|
||||
new TestData(
|
||||
getClassLoaderResource("/thumbsdb/Thumbs-camera.db"),
|
||||
new Dimension(96, 96),
|
||||
new Dimension(64, 96),
|
||||
new Dimension(96, 96),
|
||||
new Dimension(96, 64), new Dimension(64, 96),
|
||||
new Dimension(96, 64), new Dimension(96, 64), new Dimension(96, 64),
|
||||
new Dimension(64, 96), new Dimension(64, 96), new Dimension(64, 96),
|
||||
new Dimension(64, 96), new Dimension(64, 96), new Dimension(64, 96),
|
||||
new Dimension(96, 64),
|
||||
new Dimension(64, 96),
|
||||
new Dimension(96, 64), new Dimension(96, 64), new Dimension(96, 64),
|
||||
new Dimension(64, 96), new Dimension(64, 96),
|
||||
new Dimension(64, 96), new Dimension(64, 96), new Dimension(64, 96)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected ImageReaderSpi createProvider() {
|
||||
return mProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThumbsDBImageReader createReader() {
|
||||
return new ThumbsDBImageReader(mProvider);
|
||||
}
|
||||
|
||||
protected Class<ThumbsDBImageReader> getReaderClass() {
|
||||
return ThumbsDBImageReader.class;
|
||||
}
|
||||
|
||||
protected List<String> getFormatNames() {
|
||||
return Arrays.asList("thumbs");
|
||||
}
|
||||
|
||||
protected List<String> getSuffixes() {
|
||||
return Arrays.asList("db");
|
||||
}
|
||||
|
||||
protected List<String> getMIMETypes() {
|
||||
return Arrays.asList("image/x-thumbs-db");
|
||||
}
|
||||
|
||||
public void testArrayIndexOutOfBoundsBufferedReadBug() throws IOException {
|
||||
ImageInputStream input = new BufferedImageInputStream(new MemoryCacheImageInputStream(getClass().getResourceAsStream("/thumbsdb/Thumbs-camera.db")));
|
||||
input.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||
Entry root = new CompoundDocument(input).getRootEntry();
|
||||
|
||||
Entry child = root.getChildEntry("Catalog");
|
||||
child.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSetDestination() throws IOException {
|
||||
// Known bug in Sun JPEGImageReader before Java 6
|
||||
if (IS_JAVA_6) {
|
||||
super.testSetDestination();
|
||||
}
|
||||
else {
|
||||
System.err.println("WARNING: Test skipped due to known bug in Java 1.5, please test again with Java 6 or later");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSetDestinationType() throws IOException {
|
||||
// Known bug in Sun JPEGImageReader before Java 6
|
||||
if (IS_JAVA_6) {
|
||||
super.testSetDestinationType();
|
||||
}
|
||||
else {
|
||||
System.err.println("WARNING: Test skipped due to known bug in Java 1.5, please test again with Java 6 or later");
|
||||
}
|
||||
}
|
||||
}
|
BIN
imageio/imageio-thumbsdb/src/test/resources/thumbsdb/Thumbs-camera.db
Executable file
BIN
imageio/imageio-thumbsdb/src/test/resources/thumbsdb/Thumbs-camera.db
Executable file
Binary file not shown.
BIN
imageio/imageio-thumbsdb/src/test/resources/thumbsdb/Thumbs.db
Executable file
BIN
imageio/imageio-thumbsdb/src/test/resources/thumbsdb/Thumbs.db
Executable file
Binary file not shown.
14
imageio/imageio-thumbsdb/todo.txt
Executable file
14
imageio/imageio-thumbsdb/todo.txt
Executable file
@@ -0,0 +1,14 @@
|
||||
- Listeners
|
||||
|
||||
- Expose one of the methods below:
|
||||
- String getName(int pIndex)
|
||||
- String[] getNames()
|
||||
- Catalog getCatalog()
|
||||
|
||||
- Make it multi-threaded? Or at least support multi-threaded reading
|
||||
|
||||
- There seems to be different versions of the Thumbs.db:
|
||||
- http://vinetto.sourceforge.net/docs.html
|
||||
- We probably want to support all of these
|
||||
|
||||
DONE:
|
Reference in New Issue
Block a user