I am using the wonderful twelve monkeys library to create TIFF files, but I am having a problem setting the image resolution units to inches. I have spent 2 days researching both Google and the twelve monkeys source code, without success. I am hoping that someone else knows how to solve this. This is the simplified code:
final BufferedImage bufferedImage = someImage;
final int dpi = 300;
final String filePath = someFilePath;
final ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
final ImageOutputStream output = ImageIO.createImageOutputStream(buffer);
writer.setOutput(output);
final double resolution = dpi / 10.0; // --- This is a hack (possibly a MM/CM conversion)
final String standardFormat = IIOMetadataFormatImpl.standardMetadataFormatName;
final IIOMetadata metadata = writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(bufferedImage),null);
final IIOMetadataNode customMetadata = new IIOMetadataNode(standardFormat);
final IIOMetadataNode dimensionMetadataNode = new IIOMetadataNode("Dimension");
customMetadata.appendChild(dimensionMetadataNode);
final IIOMetadataNode horizontalMetadataNode = new IIOMetadataNode("HorizontalPixelSize");
dimensionMetadataNode.appendChild(horizontalMetadataNode);
horizontalMetadataNode.setAttribute("value",String.valueOf(resolution));
final IIOMetadataNode verticalMetadataNode = new IIOMetadataNode("VerticalPixelSize");
dimensionMetadataNode.appendChild(verticalMetadataNode);
verticalMetadataNode.setAttribute("value",String.valueOf(resolution));
metadata.mergeTree(standardFormat,customMetadata);
final IIOImage iioImage = new IIOImage(bufferedImage,null,metadata);
writer.write(null,iioImage,params);
final File file = new File(filePath);
final FileOutputStream fos = new FileOutputStream(file);
buffer.writeTo( fos );
This code creates a TIFF file which ImageMagick reports as:
Resolution: 300x300
Print size: 8.26667x11.6933
Units: PixelsPerCentimeter
And yet com.twelvemonkeys.imageio.plugins.tiff.TIFFBaseline states:
int RESOLUTION_UNIT_NONE = 1;
int RESOLUTION_UNIT_DPI = 2; // Default
int RESOLUTION_UNIT_CENTIMETER = 3;
I know that I could exec ImageMagick from Java to set the required resolution units, but that is something of a hack and it would be much better to simply generate Tiff file data with the correct resolution unit from my Java code.
If my question is foolish (or I have been stupid), I apologise in advance. I would welcome any help. Thank-you.
Related
i try to write a java program, which converts the pptx to jpeg images. There are many options (e.g., aspose, groupdocs, cloudmersive). But they are limited (either generating images in the evaluation mode or limited by the number of API calls); i prefer an open source library and up till now, i have known 2 libreries which are Apache POI and Docx4j. By using the Apache POI, i was able to implement the conversion PPTX-JPEG; however, the generated images' quality is low even the rendering parameters were set.
// create an empty presentation
public static void Pptx_Img(String slidePath, String outputDir, String fileName) throws Exception {
// create an empty presentation
File file = new File(slidePath);
FileInputStream in = new FileInputStream(file);
XMLSlideShow ppt = new XMLSlideShow(in);
// get the dimension and size of the slide
Dimension pgsize = ppt.getPageSize();
List<XSLFSlide> slides = ppt.getSlides();
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
BufferedImage img = null;
outputDir = outputDir + "\\apache\\pptx\\" + fileName;
Apache.createDirIfNotExists(outputDir);
for (int i = 0; i < 10; i++) {
img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setRenderingHint(Drawable.BUFFERED_IMAGE, new WeakReference<>(img));
// clear area
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
// draw the images
slides.get(i).draw(graphics);
FileOutputStream out = new FileOutputStream(outputDir + "\\slide_" + i + ".jpg");
/*
// specifies where the jpg image has to be written
final ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
writer.setOutput(ImageIO.createImageOutputStream(out));
// writes the file with given compression level
writer.write(null, new IIOImage(img, null, null), jpegParams);
*/
ImageIO.write(img, "jpeg", out);
ppt.write(out);
graphics.dispose();
out.close();
img.flush();
}
System.out.println("Images successfully created");
in.close();
ppt.close();
}
Comparison between the original slide and the generated images
I also came up with another indirect way, which converts pptx-pdf-jpeg (because i have the implementation for conversion pdf-jpeg and the conversion can actually maintain the image quality). But i couldnt find any open source libs which can do the conversion pptx-jpeg. For Apache POI, it can convert pptx-pdf but the mechanism is just similar to pptx-jpeg: writes the Graphic2D-instance to pdf instead of jpeg, which basically does not improve the rendering quality.
Added: Regarding to the comparison, the wrong rendering is also another issue !
I am using azure web job to save thumb of an image and this is code for doing this
ImageProcessor.Imaging.Formats.FormatBase f;
f = new ImageProcessor.Imaging.Formats.JpegFormat();
Size size = new Size(200, 200);
using (WebClient client = new WebClient())
{
MemoryStream stream = new MemoryStream(client.DownloadData(input));
MemoryStream stream2 = new MemoryStream();
int quality = 110;
do
{
quality = quality - 10;
using (ImageFactory factory = new ImageFactory(false))
{
factory.Load(stream)
.Format(f)
.Resize(size)
//.BackgroundColor(Color.White)
.Quality(quality)
.Save(stream2);
}
} while (stream2.Length > stream.Length || stream2.Length ==100000);
When i add message to queue with this image for example,
job should give me thumb image 200 * 200 but there is trailing black area in top and bottom of resulted image like this which shouldn't be done
Why this is done ???
You're trying to fit a rectangle into a square.
From http://imageprocessor.org/imageprocessor/imagefactory/resize/:
Resize
Resizes the current image to the given dimensions. If EXIF metadata is to be preserved the information contained within will also be updated to match.
public ImageFactory Resize(Size size)
Parameters
size:
The System.Drawing.Size containing the width and height to set the image to.
Passing a 0 for either dimension will omit that dimension.
So, pass in 0 as height to maintain aspect ratio,
Size size = new Size(200, 0);
or use one of the other resize modes: Crop/Min/Max/Stretch
I am trying to build a rather crude tool that converts a ppt/pptx file to a HTML format.
I have found out that, unfortunately, apache poi does not provide a unified programming model for working with power point files and code has to be written for parsing each format.
I feel that the pptx file support is much more limited than the ppt support.
One problem I'm facing is getting information regarding the background (color, pattern, background image) of a pptx slide.
I find the XSLFBackground (pptx api) class to be much more limited than its corresponding Background class (ppt api).
Has anyone managed to get get information regarding the background of a pptx slide using apache poi ?
Also can someone please point me to some good resources on this subject. I find the apache poi javadoc almost unusable and the examples on the poi website only cover basic functionality.
Best regards, Sergiu
The content of the background element is described in the Office Open Schema - check the zip-link at the bottom and the pml-slide.xsd inside.
With the schema in the hand you will understand the XML beans below the usermodel interface.
For a starter, here is an example of reading a background image and also of exporting the slides to pngs (maybe useful for your html export?):
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import org.apache.poi.xslf.usermodel.*;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
public class PptxBackground {
public static void main(String[] args) throws Exception {
// sorry for the content, but it was one of the first non-commercial google matches ...
URL url = new URL("http://newkilpatrickblog.typepad.com/files/sunday_june_03_2012_trinity_and_majesty_communion.pptx");
InputStream is = url.openStream();
XMLSlideShow ss = new XMLSlideShow(is);
is.close();
XSLFSlide sld = ss.getSlides()[0];
XSLFBackground bg = sld.getBackground();
CTBackground xmlBg = (CTBackground)bg.getXmlObject();
String relId = xmlBg.getBgPr().getBlipFill().getBlip().getEmbed();
XSLFPictureData pic = (XSLFPictureData)sld.getRelationById(relId);
String filename = pic.getFileName();
byte fileBytes[] = pic.getData();
/***** or convert the slides to images ****/
double zoom = 2; // magnify it by 2
AffineTransform at = new AffineTransform();
at.setToScale(zoom, zoom);
Dimension pgsize = ss.getPageSize();
XSLFSlide slides[] = ss.getSlides();
for (int i = 0; i < slides.length; i++) {
BufferedImage img = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setTransform(at);
graphics.setPaint(Color.white);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
slides[i].draw(graphics);
FileOutputStream out = new FileOutputStream("slide-" + (i+1) + ".png");
javax.imageio.ImageIO.write(img, "png", out);
out.close();
}
}
}
Am into an J2ME project right now where I need to select an image and write this image to a particular folder say somewhere in memory card with a desired file name. Am able to select image and display it but when trying to save it am having trouble. When I try to save, an image file is created but its size is 0.0 kb and when I click on the image it says "File Format not supported"
This is my code
fileCon = (FileConnection)Connector.open(path+"Contacts/contactImages/"+FIRST_NAME+".png",Connector.READ_WRITE);
if(!fileCon.exists())
{
fileCon.create();
}
int h = contactImage.getHeight();
int w = contactImage.getWidth();
int[] size = new int[w*h];
contactImage.getRGB(size, 0, w, 0, 0, w, h);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (int i = 0; i < size.length; i++)
{
dos.writeInt(size[i]);
}
But you are writing pixel data into (in-memory) ByteArrayOutputStream, and not a file stream. Shouldn't there be something like
DataOutputStream dos = fileCon.openDataOutputStream();
And of course output stream should be closed to make sure all data is flushed.
Another thing is that you are saving raw ARGB data and not encoded PNG image, so .png extension may confuse some image viewers. Perhaps .bmp would be better.
I'm trying to create a new PDF file using iText, and the new file should be composed of pages that are generated from an area within an SVG file (tile). And each generated page needs to have a 'drawing border' superimposed upon it, so that it appears as the top layer of each generated page. I think the superimposing can be achieved with the iText stamper, but examples I see work only with an existing PDF, which I don't have as I want to do all this on-the-fly to reduce the time required to generate the resulting PDF. I have a one page PDF file that represents the PDF layer to superimpose upon each page generated in the PDF.
I found an example on the net that divides the SVG canvas into tiles and creates separate PDF files from each tile. However, creating intermediate PDF files wastes time, as I need to read them in again to create the file I am trying to create (with the superimposed layer for each page).
I don't want to dump loads of code here, but here is the code sample that I used to generate one page PDF files for each SVG tile:
http://people.apache.org/~clay/batik/rasterizerTutorial.pdf (see page 5: SaveAsJPEGTiles.java)
As I am an iText newbie, maybe someone here has achieved something similar, or knows how to do this?
Thanks.
I'm using a ByteArrayOutputStream instead of the FileOutputStream, but when I try to combine this with iText's Document type, I keep getting an exception saying no pages in document - see code below. I think I need to add the ByteArrayOutputStream for each tile to the iText document so that it creates a new page for each tile, but I can't see how to do that from the iText API. Here's my code so far, but doesn't quite work:
package examples.aoi;
import java.io.*;
import java.awt.*;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.fop.svg.PDFTranscoder;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
public class FromCanvasToPDFPages {
PDFTranscoder trans = new PDFTranscoder();
public FromCanvasToPDFPages() {
}
public void tile(TranscoderInput input, TranscoderOutput output, Rectangle aoi) throws Exception {
trans.addTranscodingHint(PDFTranscoder.KEY_WIDTH, new Float(aoi.width));
trans.addTranscodingHint(PDFTranscoder.KEY_HEIGHT, new Float(aoi.height));
trans.addTranscodingHint(PDFTranscoder.KEY_AOI, aoi);
trans.transcode(input, output);
}
public static void main(String [] args) throws Exception {
FromCanvasToPDFPages p = new FromCanvasToPDFPages();
String in = "C:\\Documents and Settings/krell/My Documents/1.svg";
String svgURI = new File(in).toURL().toString();
TranscoderInput input = new TranscoderInput(svgURI);
String outputFilename = "canvasPages.pdf";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(baos);
int A4_landscape_width = 1103; // use proper dimensions from class when found
int A4_landscape_height = 780; // use proper dimensions from class when found
int documentWidth = 3309; // read this directly from canvas file (svg)
int documentHeight = 1560; // read this directly from canvas file (svg)
int columns = documentWidth / A4_landscape_width;
int rows = documentHeight / A4_landscape_height;
int tile_width = A4_landscape_width;
int tile_height = A4_landscape_height;
System.err.println(">>> Canvas document width = "+documentWidth);
System.err.println(">>> Canvas document height = "+documentHeight);
System.err.println(">>> A4 width = "+A4_landscape_width);
System.err.println(">>> A4 height = "+A4_landscape_height);
System.err.println(">>> canvas columns = "+columns);
System.err.println(">>> canvas rows = "+rows);
System.err.println(">>> tile_width = "+tile_width);
System.err.println(">>> tile_height = "+tile_height);
// Create A4 document to write tile data into
Document document = new Document(PageSize.A4_LANDSCAPE, 10, 10, 10, 10);
PdfWriter writer = PdfWriter.getInstance(document, baos);
// open the document
document.open();
// now process each tile, row by row, column by column until done
for (int row = 0; row < rows; row++) {
for (int column = 0; column < columns; column++) {
// get tile coordinates
Rectangle tile = new Rectangle(column*tile_width, row*tile_height, (column+1)*tile_width, (row+1)*tile_height);
p.tile(input, output, tile);
}
}
// now write the baos to disk:
OutputStream fileOutputStream = new FileOutputStream(outputFilename);
baos.writeTo(fileOutputStream);
// close stuff
fileOutputStream.flush();
fileOutputStream.close();
document.close();
baos.close();
System.exit(0);
}
}