Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImageIO write support #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ Download and run "ant". The jar "target/jj2000.jar" contains the API code, the "

ImageIO support
---------------
The Jar supplies an ImageIO reader implementation, so reading is as simple as `javax.imageio.ImageIO.read(new File("input.jp2"))`
(thanks to @keinhaar for the PR). The reader doesn't support metadata.
The Jar supplies an ImageIO support, so reading is as simple as

There is currently no ImageIO writer support.
`javax.imageio.ImageIO.read(new File("input.jp2"))`

and for writing

`ImageIO.write(image, "JPEG2000", new File("image.jp2"));`

(thanks to @keinhaar for the PR). Both, reader and writer, do not support metadata.

How to read a JP2 or JPX image
------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public String[] getFileSuffixes()
@Override
public String getDescription(Locale locale)
{
return "JPEG2000 ImageIO Support";
return "JPEG2000 ImageIO Reader Support";
}

}
52 changes: 52 additions & 0 deletions src/main/java/com/github/jpeg2000/imageio/ImageWriterImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.github.jpeg2000.imageio;

import java.io.IOException;
import java.util.Locale;

import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;

/**
* JPEG2000 ImageIO Writer SPI.
*/
public class ImageWriterImpl extends ImageWriterSpi
{
@Override
public Class[] getOutputTypes()
{
return new Class[] {ImageOutputStream.class};
}

@Override
public ImageWriter createWriterInstance(Object extension) throws IOException
{
return new JPEG2000Writer(this);
}

@Override
public String[] getFormatNames()
{
return new String[] {"jpeg2000", "JPEG2000"};
}

@Override
public String[] getFileSuffixes()
{
return new String[] {"jp2", "j2k"};
}

@Override
public String getDescription(Locale locale)
{
return "JPEG2000 ImageIO Writer Support";
}

@Override
public boolean canEncodeImage(ImageTypeSpecifier type)
{
return true;
}

}
128 changes: 128 additions & 0 deletions src/main/java/com/github/jpeg2000/imageio/JPEG2000Writer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.github.jpeg2000.imageio;

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;

import javax.imageio.IIOImage;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;

import com.github.jpeg2000.J2KWriter;

public class JPEG2000Writer extends ImageWriter
{
public JPEG2000Writer(ImageWriterImpl imageWriterImpl)
{
super(imageWriterImpl);
}

@Override
public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param)
{
return null;
}

@Override
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param)
{
return null;
}

@Override
public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param)
{
return null;
}

@Override
public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param)
{
return null;
}

@Override
public void write(IIOMetadata streamMetadata, IIOImage iioimage, ImageWriteParam param) throws IOException
{
//We can savely cast here, because the setOutput does not accept anything else.
ImageOutputStream stream = (ImageOutputStream) getOutput();
RenderedImage image = iioimage.getRenderedImage();
BufferedImage bimage = null;
if(image instanceof BufferedImage)
{
bimage = (BufferedImage) image;
}
else
{
bimage = convertToBufferedImage(image);
}
J2KWriter writer = new J2KWriter();
writer.setCompressionRatio(15, false);
writer.setSource(bimage, 128);
writer.write(new Output(stream));
}

/**
* Translate between OutputStream and ImageOutputStream
*/
class Output extends OutputStream
{
private ImageOutputStream stream;

public Output(ImageOutputStream stream)
{
this.stream = stream;
}

@Override
public void write(int b) throws IOException
{
stream.write(b);
}

@Override
public void write(byte[] b, int off, int len) throws IOException
{
stream.write(b, off, len);
}

@Override
public void close() throws IOException
{
stream.close();
}
}

/**
* Convert any other RenderedImage to BufferedImage
* @param img
* @return
*/
private BufferedImage convertToBufferedImage(RenderedImage img)
{
ColorModel cm = img.getColorModel();
int width = img.getWidth();
int height = img.getHeight();
WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
Hashtable properties = new Hashtable();
String[] keys = img.getPropertyNames();
if(keys != null)
{
for(String key : keys)
{
properties.put(key, img.getProperty(key));
}
}
BufferedImage bimage = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
img.copyData(raster);
return bimage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.github.jpeg2000.imageio.ImageWriterImpl