Converting EMF Image from MS Word to BufferedImage - java

I am writing a program that would read text from an image. I have success on JPG/PNG by getting the BufferedImage out of the XWPFPictureData.
public static BufferedImage convertPicDataToBuffImg(XWPFPictureData objPicData) {
byte[] bData = objPicData.getData();
BufferedImage objInBuffImg = ImageIO.read(new ByteArrayInputStream(bData));
...
}
However, when using the same code for EMF picture types, objInBuffImg becomes null. As I read, this is because the type is EMF.
To use the same methods I used, I wanted to convert XWPFPictureData with PictureType Document.PICTURE_TYPE_EMF to BufferedImage.
So basically what I wanted to do is something like the following:
public static BufferedImage convertPicDataToBuffImg(XWPFPictureData objPicData) {
BufferedIMage objInBuffImg = null;
if (objPicData.getPictureType() == Document.PICTURE_TYPE_EMF)) {
// Convert to BufferedImage
} else {
byte[] bData = objPicData.getData();
objInBuffImg = ImageIO.read(new ByteArrayInputStream(bData));
}
...
}
Have been searching and read about Batik but can't exactly figure out how to do what I want to do as stated above.
Any ideas?
Thank you very much in advance for your help!

Related

iText 7 SVG as a background

I'm trying to add a background in a PDF using Scalable Vector Graphics (.svg). Initially the recommended way was to transform the SVG into an Image object and then use scaleToFit to get it to the right size, then add it to the document. This works partially as it transforms the small and scalable SVG into a Bitmap. Next I've made a PdfFormXObject in order to get back the scaling by having it drawn on each page. However, now it does not display anything at all.
ByteArrayInputStream inputStream = new ByteArrayInputStream(backgroundBytes);
PdfFormXObject svg = SvgConverter.convertToXObject(inputStream, pdf);
PdfCanvas canvas = new PdfCanvas(pdf.getFirstPage());
Rectangle rect = new Rectangle(PageSize.A4.getWidth(), PageSize.A4.getHeight());
canvas.addXObject(svg, rect);
How should I be adding SVG backgrounds to iText 7 PDFs? Can this be done properly in the first place? I have not been able to find good code examples.
Update:
Here is the code for converting the SVG to a properly scaled Image. The issue with this is that it works for adding the image, but it adds it as an element so it pushes everything else down.
ByteArrayInputStream inputStream = new ByteArrayInputStream(svgAsBytes);
Image image = SvgConverter.convertToImage(inputStream, pdf);
image.scaleAbsolute(PageSize.A4.getWidth(), PageSize.A4.getHeight());
int totalPages = pdf.getNumberOfPages()+1;
for(int pageNumber = 1; pageNumber < totalPages; pageNumber++ ) {
document.add(image);
}
Hi i have a similar Problem. I am trying to add a SVG image as a table cell background. The problem is that i can not scale the image. Here is my code:
InputStream triangleSteam = this.getClass().getResourceAsStream("/AH-AddressTriangle.svg");
Image triangle = SvgConverter.convertToImage(triangleSteam, pdfDocument);
//triangle.setHeight(UnitValue.createPointValue(127.83f));
//triangle.setWidth(UnitValue.createPointValue(78.63f));
triangle.scaleAbsolute(78.63f, 127.83f);
Cell headerCell_12 = new Cell();
headerCell_12.setBorder(Border.NO_BORDER);
headerCell_12.setPadding(0f);
headerCell_12.setHeight(UnitValue.createPointValue(127.83f));
headerCell_12.setWidth(UnitValue.createPointValue(78.63f));
headerCell_12.setNextRenderer(new ImageBackgroundCellRenderer(headerCell_12, triangle));
headerTable.addCell(headerCell_12);
And here ist the BackgroundCellRenderer I am using:
protected class ImageBackgroundCellRenderer extends CellRenderer {
Image img;
public ImageBackgroundCellRenderer(Cell modelElement, Image img) {
super(modelElement);
this.img = img;
}
#Override
public IRenderer getNextRenderer() {
return new ImageBackgroundCellRenderer((Cell) modelElement, img);
}
#Override
public void draw(DrawContext drawContext) {
try {
img.scaleToFit(getOccupiedAreaBBox().getWidth(), getOccupiedAreaBBox().getHeight());
drawContext.getCanvas().addXObject(img.getXObject(), getOccupiedAreaBBox());
super.draw(drawContext);
} catch(Exception e) {
e.printStackTrace();
}
}
}
The background is added but the image is not scaled (see picture)
Screenshot from Adobe Illustrator
The SVG becomes even bigger that it actually was!
Thank you!

Java ImageIO.read(URL) returning null when it shouldn't

Okay so I have spent about 15 hours trying to figure this out. I am working on this program that gets exported to a non-runnable jar file. The issue is I am trying to load an image in the jar and set it to a variable.
I HAVE looked at other posts and I think I have tried everything I could find but nothing seems to work.
I am not asking how to FIND the image as I can get the URL of the image, but then ImageIO.read(URL) is not throwing any exception, but returning null. The image is a .png which I have heard is compatible with ImageIO.read(). I am using an API so that is what the log() lines are.
Any help is appreciated. Thank you!
My Project:
Project
->src
-->package
--->Main.java
--->paint.png
My Code:
In my main method:
(mainPaint is a private Image)
mainPaint = getImage("paint.png");
The method:
private Image getImage(String fileName) {
URL url = getClass().getResource(fileName);
BufferedImage image = null;
log(url.toString()); // To make sure I have the correct file
// returning jar:file:/C:/Users/Me/MyJar.jar!/package/paint.png
try {
image = ImageIO.read(url);
} catch (IOException e1) {
log("Error converting url to image.");
// This is not happening
}
if (image == null) {
log("Image is null.");
// This is happening
}
return image;
}
Is the URL invalid? Am I just missing something? I'm just trying to save the local image in the jar as an Image object, I feel like this is way too difficult for what I am trying to do.
EDIT:
I also just tried making mainPaint a BufferedImage and using:
Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource(fileName));
if(image == null) {
log("Image is null");
}
log("Height: " + image.getHeight(null));
log("Width: " + image.getWidth(null));
BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(image, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
The height and width of the image are returning -1?
ImageIO.read() will not load SVG files, so if your images are in SVG formate you will need to add plugins to it to support SVG
Here is another SO post that explain where you can do that.
ImageIO.read() will load only GIF, PNG, JPEG, BMP, and WBMP image types.
Any other image type will return null without error.
It could answer to your question .

Change in color while using ImageIO.read()

I am trying to read images from external directory and for that I am using
bufferedImage image=ImageIO.read(new File(imagefile));
jlabel.seticon(new imageicon(image));
and getting a drastic change in colors. I tried many other things like:
bufferedImage image=ImageIO.read(new File(imagefile));
bufferedImage img=new bufferedImage(image.getWidth(),image.getHeight(),bufferedImage.TYPE_INT_RGB);
and I tried:
img.setData(image.getData();
jlabel.seticon(new imageicon(image));
and I tried:
Iterator readers = ImageIO.getImageReadersByFormatName("JPEG");
ImageReader reader = null;
while(readers.hasNext()) {
reader = (ImageReader)readers.next();
if(reader.canReadRaster()) {
break;
}
}
ImageInputStream input = ImageIO.createImageInputStream(f);
reader.setInput(input);
Raster raster = reader.readRaster(0, null);
BufferedImage bi = new BufferedImage(raster.getWidth(), raster.getHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
bi.getRaster().setRect(raster);
but result are still same
http://i.stack.imgur.com/jNVm0.jpg
Here is an example of the issue:
The minimal code for viewing is:
bufferedImage image=ImageIO.read(new File(imagefile));
jlabel.seticon(new imageicon(image));
lbitem.setIcon(im);
and for storing
File f = new File(s);
long size=f.length();
FileInputStream fis1=new FileInputStream(f);
FileOutputStream fos2=new FileOutputStream("src/image/"+tfpn.getText()+".jpg");
byte b[]=new byte[1000];
int r=0;
long count=0;
while(true)
{
r=fis1.read(b,0,1000);
fos2.write(b,0,1000);
count = count+r;
if(count==size)
break;
System.out.println(count);
}
What could be causing the bad colors?
This problem is cause by a mismatch between reading/writing (creating/using) an image
that contains alpha (transparency) but you are expecting it to contain no alpha (or the inverse).
For example, if your image is BufferedImage.TYPE_4BYTE_ABGR and you output it
to a file type that does not support alpha (transparency) , or you writer does not
support alpha, it will look like your sample after reading and displaying it.
Use type PNG (supports alpha channel) not JPG (does not support alpha channel)

Can I tell what the file type of a BufferedImage originally was?

In my code, I have a BufferedImage that was loaded with the ImageIO class like so:
BufferedImage image = ImageIO.read(new File (filePath);
Later on, I want to save it to a byte array, but the ImageIO.write method requires me to pick either a GIF, PNG, or JPG format to write my image as (as described in the tutorial here).
I want to pick the same file type as the original image. If the image was originally a GIF, I don't want the extra overhead of saving it as a PNG. But if the image was originally a PNG, I don't want to lose translucency and such by saving it as a JPG or GIF. Is there a way that I can determine from the BufferedImage what the original file format was?
I'm aware that I could simply parse the file path when I load the image to find the extension and just save it for later, but I'd ideally like a way to do it straight from the BufferedImage.
As #JarrodRoberson says, the BufferedImage has no "format" (i.e. no file format, it does have one of several pixel formats, or pixel "layouts"). I don't know Apache Tika, but I guess his solution would also work.
However, if you prefer using only ImageIO and not adding new dependencies to your project, you could write something like:
ImageInputStream input = ImageIO.createImageInputStream(new File(filePath));
try {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(input);
BufferedImage image = reader.read(0); // Read the same image as ImageIO.read
// Do stuff with image...
// When done, either (1):
String format = reader.getFormatName(); // Get the format name for use later
if (!ImageIO.write(image, format, outputFileOrStream)) {
// ...handle not written
}
// (case 1 done)
// ...or (2):
ImageWriter writer = ImageIO.getImageWriter(reader); // Get best suitable writer
try {
ImageOutputStream output = ImageIO.createImageOutputStream(outputFileOrStream);
try {
writer.setOutput(output);
writer.write(image);
}
finally {
output.close();
}
}
finally {
writer.dispose();
}
// (case 2 done)
}
finally {
reader.dispose();
}
}
}
finally {
input.close();
}
BufferedImage does not have a "format"
Once the bytes have been translated into a BufferedImage the format of the source file is completely lost, the contents represent a raw byte array of the pixel information nothing more.
Solution
You should use the Tika library to determine the format from the original byte stream before the BufferedImage is created and not rely on file extensions which can be inaccurate.
One could encapsulate the BufferedImage and related data in class instance(s) like so:
final public class TGImage
{
public String naam;
public String filename;
public String extension;
public int layerIndex;
public Double scaleX;
public Double scaleY;
public Double rotation;
public String status;
public boolean excluded;
public BufferedImage image;
public ArrayList<String> history = new ArrayList<>(5);
public TGImage()
{
naam = "noname";
filename = "";
extension ="";
image = null;
scaleX = 0.0;
scaleY = 0.0;
rotation = 0.0;
status = "OK";
excluded = false;
layerIndex = 0;
addHistory("Created");
}
final public void addHistory(String str)
{
history.add(TGUtil.getCurrentTimeStampAsString() + " " + str);
}
}
and then use it like this:
public TGImage loadImage()
{
TGImage imgdat = new TGImage();
final JFileChooser fc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image Files", "jpg", "png", "gif", "tif");
fc.setFileFilter(filter);
fc.setCurrentDirectory(new File(System.getProperty("user.home")));
int result = fc.showOpenDialog(this); // show file chooser
if (result == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
System.out.println("Selected file extension is " + TGUtil.getFileExtension(file));
if (TGUtil.isAnImageFile(file))
{
//System.out.println("This is an Image File.");
try
{
imgdat.image = ImageIO.read(file);
imgdat.filename = file.getName();
imgdat.extension = TGUtil.getFileExtension(file);
info("image has been loaded from file:" + imgdat.filename);
} catch (IOException ex)
{
Logger.getLogger(TGImgPanel.class.getName()).log(Level.SEVERE, null, ex);
imgdat.image = null;
info("File not loaded IOexception: img is null");
}
} else
{
imgdat = null;
info("File not loaded: The requested file is not an image File.");
}
}
return imgdat;
}
Then you have everything relevant together in TGImage instance(s).
and perhaps use it in an imagelist like so:
ArrayList<TGImage> images = new ArrayList<>(5);

BufferedImage get resized with different colors

I am resizing many jpeg images using Apache Sanselan which also deals with CMYK colors.
I have a problem when trying to convert jpeg images that has an alpha channel... when doing it the result is an image with different colors, and i guess that java somehow handles these type of images as a different color format.
As i said, the RGB resizing works fine as well as CMYK. ARGB images turn out with different colors.
An example:
Any suggestions? Can i force somehow ignore the alpha channel and handle the image as an RGB image? or convert it to be an RGB image without losing the real colors?
The code that handles this image is:
ImageInputStream stream = ImageIO.createImageInputStream(file);
Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
while (iter.hasNext()) {
ImageReader reader = iter.next();
reader.setInput(stream);
BufferedImage image = null;
ICC_Profile profile = null;
try {
image = reader.read(0);
} catch (IIOException e) {
... (CMYK conversion if needed)
}
return image;
}
return null;
Thanks in advance
I found a good solution here (first solution worked great):
problem using ImageIO.write jpg file
Edit:
There is a new open source library which supports CMYK processing.
All you need to do is to add the dependency to your project and a new reader will be added to the list of readers (while the known JPEGImageReader can't deal with CMYK).
You will probably want to iterate over these readers and read the image using the first reader which doesn't throw exception.
This package is a release candidate, but i am using it and it solved a huge problem that we had hard time dealing with.
http://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-jpeg/3.0-rc5
You can do the iteration this way to get the BufferedImage, and after you got that, the rest is easy (you can use any existing image converting package to save it as another format):
try (ImageInputStream input = ImageIO.createImageInputStream(source)) {
// Find potential readers
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
// For each reader: try to read
while (readers != null && readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(input);
BufferedImage image = reader.read(0);
return image;
} catch (IIOException e) {
// Try next reader, ignore.
} catch (Exception e) {
// Unexpected exception. do not continue
throw e;
} finally {
// Close reader resources
reader.dispose();
}
}
// Couldn't resize with any of the readers
throw new IIOException("Unable to resize image");
}

Categories