Custom decoders for PNG files - imagesharp

I've donwloaded an image from user manual (see attachment) and need to transform it. When I tried to load it via following code, I got the exception: "Image cannot be loaded. Available decoders:\r\n - JPEG : JpegDecoder\r\n - PNG : PngDecoder\r\n - GIF : GifDecoder\r\n - BMP : BmpDecoder\r\n".
Is it possible to apply custom decoder and where can I found them?
using (var originalImage = new MemoryStream(...))
using (var image = Image.Load<Rgba32>(originalImage))
{
}

The linked image can be decoded using ImageSharp. As #tocsoft says in the comments it likely you forgot to reset your input stream position.
Here's the two images. The second we've loaded and flipped vertically using the following code:
using (var image = Image.Load(Path.Combine(inPath, "-7bH2hfA.png")))
{
image.Mutate(x => x.Flip(FlipMode.Vertical));
image.Save(Path.Combine(outPath, "-7bH2hfA-flipped.png"));
}
Your input image:
Our flipped output image:
EDIT
When I originally tested the image I used r-click save which gave me a valid png. I have since used the direct download from Dropbox which yields the original file.
It's not a png! It is, in fact, a webp file.

Related

Writing Comments (metadata) within image file using R

I would like to add parameter information to the plots that we make as part of our research project. I know that png has a text block for adding comments. (I am not a png expert, but I think it uses the tEXt block.) Using Gimp, under image properties, you can add a comment that can be read by other software (e.g. by the "inspector" in mac preview. I'm sure there is a windows equivalent). We make our images with ggsave. I did not see any arguments to ggsave that allows us to write to the "comment" block of a png file. I've tried using png::readPNG, and png::writePNG functions
im <- readPNG("test1.png",native=FALSE,info=TRUE)
md <- c(comment=paste0(date=date(),machine=Sys.info()['nodename']))
writePNG(image=im,target="test1_md1.png",text=md,metadata = md)
im2 <- readPNG("test1_md1.png",native=FALSE,info=TRUE)
attr(img2, "info")
I can open the new png file, it looks just like the old one. However, the comment block is not filled. As you can see, the data is written in the file, but neither gimp nor preview can read it. Is there a way to write the metadata in the comment block so that preview and gimp can read it correctly?
Thank you
update: ok, png::writePNG does actually write into the tEXt block, however neither gimp nor preview read the text block. I wrote a simple java program that reads the blocks.
IHDR null javax.imageio.metadata.IIONamedNodeMap#133314b
width = 2580 height = 1800 bitDepth = 8 colorType = RGBAlpha compressionMethod = deflate filterMethod = adaptive interlaceMethod = none
tEXt null javax.imageio.metadata.IIONamedNodeMap#b1bc7ed
tEXtEntry null javax.imageio.metadata.IIONamedNodeMap#7cd84586
keyword = date value = Tue Dec 4 12:55:45 2018
tEXtEntry null javax.imageio.metadata.IIONamedNodeMap#30dae81
keyword = machine.nodename value = mycomputer.xyz.org
Is there a separate comment block somewhere? That is the block I want to write to.
update 2: It appears that gimp/preview read the iTXt block. So the question becomes can I write to the iTXt block from R.

Converting Docx to image using Docx4j and PdfBox causes OutOfMemoryError

I'm converting the first page of a docx file to an image in twoo steps using dox4j and pdfbox but I'm currently getting an OutOfMemoryError every time.
I've been able to determine that the exception is thrown on the very last step of this process, while the convertToImage method is being called, however I've been using the second step of this method to convert pdfs for some time now without issue so I am at a loss as to what might be the cause unless perhaps dox4j is encoding the pdf is a way which I have not yet tested or is corrupt.
I've tried replacing the ByteArrayOutputStream with a FileOutputStream and the pdf seems to render correctly is not any larger than I would expect.
This is the code I am using:
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(file);
org.docx4j.convert.out.pdf.PdfConversion c = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(wordMLPackage);
((org.docx4j.convert.out.pdf.viaXSLFO.Conversion)c).setSaveFO(File.createTempFile("fonts", ".fo"));
ByteArrayOutputStream os = new ByteArrayOutputStream();
c.output(os, new PdfSettings());
byte[] bytes = os.toByteArray();
os.close();
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
PDDocument document = PDDocument.load(is);
PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 96);
is.close();
document.close();
Edit
To give more context on this situation, this code is being run in a grails web-application. I have tried several different variants of this code, including nulling out everything once no longer needed, using FileInputStream and FileOutputStream to try to conserve more physical memory and inspect the output of docx4j and pdfbox, each of which seem to work correctly.
I'm using docx4j 2.8.1 and pdfbox 0.7.3, I have also tried pdf-renderer but I still get an OutOfMemoryError. My suspicions are that docx4j is using too much memory but does not produce the error until the pdf to image conversion.
I would gladly except an alternate way of converting a docx file to a pdf or directly to an image as an answer, however I am currently trying to replace jodconverter which has been problematic to run on a server.
I'm part of XDocreport team.
We recently develop a little webapp deployed on cloudbees (http://xdocreport-converter.opensagres.cloudbees.net/) that shows the behaviour converters.
You can easily compare the behaviour and the performances of docx4j and xdocreport for PDF and Html convertion.
Source code can be found here :
https://github.com/pascalleclercq/xdocreport-demo (REST-Service-Converter-WebApplication subfolder).
and here :
https://github.com/pascalleclercq/xdocreport/blob/master/remoting/fr.opensagres.xdocreport.remoting.converter.server/src/main/java/fr/opensagres/xdocreport/remoting/converter/server/ConverterResourceImpl.java
The firsts numbers I get is that Xdocreport is roughly 10 time faster for generating a PDF than Docx4J.
Feedback is welcome.
Glorious success at last! I replaced docx4j with XDocReport and the document converts to a PDF in no time at all. However there seems to be some issues with some documents but I would expect this is due to the OS that they were created on and may be solved by using:
PDFViaITextOptions options = PDFViaITextOptions.create().fontEncoding("windows-1250");
Using the approiate OS instead of just:
PDFViaITextOptions options = PDFViaITextOptions.create();
Which defaults to the current OS.
This is the code I now use to convert from DOCX to PDF:
FileInputStream in = new FileInputStream(file);
XWPFDocument document = new XWPFDocument(in);
PDFViaITextOptions options = PDFViaITextOptions.create();
ByteArrayOutputStream out = new ByteArrayOutputStream();
XWPF2PDFViaITextConverter.getInstance().convert(document, out, options);
byte[] bytes = out.toByteArray();
out.close();
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
PDDocument document = PDDocument.load(is);
PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 96);
is.close();
document.close();
return image;

Resizing gif image causes loss of quality

I'm using Graphics.DrawImage() to resize images in my ASP.NET application.
This is working fine with all image formats, except gif.
Here is my original image:
When I resize to 300px it returns:
The code I'm using is:
Dim postedFile as new Bitmap("flower.gif")
Dim bmpOut As System.Drawing.Bitmap
Dim Format As ImageFormat = postedFile.RawFormat
bmpOut = New Bitmap(width, height)
Dim g As Graphics = Graphics.FromImage(bmpOut)
g.InterpolationMode = InterpolationMode.High
g.DrawImage(postedFile, 0, 0, width, height)
postedFile.Dispose()
Return bmpOut
bmpOut.Dispose()
I've also tried using all of the InterpolationMode's available, including InterpolationMode.HighQualityBicubic, but the image quality is still just as poor.
Why is this happening, and how can I prevent the image quality loss?
The problem is not in the resizing code you posted. I ran using the large image you posted and the result looks great. Your problem arises when you save your newly created 24 bits-per-pixel image to a new gif - with is 8bpp. You have basically two options:
Implement code to produce an optimized color palette for the new gif
(or maybe just use the palette from the original image)
Save to .png instead - which is a completely superior format
If you are saving the resized picture as .gif, I see no reason why this can't happen in the saved .gif. .gif's are limited to 256 colors (unless some hacks are done) and your resized imaged after all the manipulations may have well more than 256. Also, I wouldn't be surprised to find out that whatever routine you're using to convert images to .gif's isn't very concerned about quality.
This is not about interpolation, it is because ColorPalette is not set for target image. You have to quantize. See example at http://glennjones.net/2005/10/high-quality-dynamically-resized-images-with-dot-net/

Working with Bitmap? Giving error?

In web application, i am using Bitmap for finding the width and hight of the image. When i write the code it is giving error: Parameter is not a valid.
Bitmap bmp = new Bitmap(Server.MapPath("./Images/" + ds.Tables[0].Rows[0]["image"].ToString()));
I am getting error can you help me. Thank you.
Error says that the image you are saving has invalid image data (state) or the filename which is used to save image is already is in used.
Probably you just need to use this
System.Drawing.Image bmp = System.Drawing.Image.FromFile(Server.MapPath("YourPathHere"));

iTextSharp renders image with poor quality in PDF

I'm using iTextSharp to print a PDF document. Everything goes ok until I have to print the company logo in it.
First I noticed that the logo had poor quality, but after testing with several images, I realize that was the iTextSharp rendering it poorly.
The test I did to say this was to print the PDF using my code and then edit the document with Acrobat 8.0 and I drew an image. Then printed the two documents and saw the noticeable difference.
My question is that if anyone know if this can be due to a scaling problem where I'm failing to tell iTextSharp how it must render the image or is an iTextSharp limitation.
The code to render the image is the following:
Dim para As Paragraph = New Paragraph
para.Alignment = Image.RIGHT_ALIGN
para.Add(text)
Dim imageFile As String = String.Format("{0}{1}", GetAppSetting("UploadDirectory"), myCompany.LogoUrl)
Dim thisImage As Image = Image.GetInstance(imageFile)
thisImage.Alignment = Image.LEFT_ALIGN
para.Add(thisImage)
The printed images are the following:
alt text http://img710.imageshack.us/img710/4199/sshot2y.png
Image printed directly with iTextSharp
alt text http://img231.imageshack.us/img231/3610/sshot1z.png
Image edited and printed with Acrobat 8
EDIT:
These logo images are loaded from an Upload page where the user uploades whatever the logo image he wants, and I was scaling that image using the following code:
Dim graph As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(newImage)
graph.CompositingMode = Drawing.Drawing2D.CompositingMode.SourceOver
graph.CompositingQuality = Drawing.Drawing2D.CompositingQuality.HighQuality
graph.InterpolationMode = Drawing.Drawing2D.InterpolationMode.Bicubic
graph.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality
graph.PixelOffsetMode = Drawing.Drawing2D.PixelOffsetMode.HighQuality
graph.DrawImage(newImage, 0, 0, newWidth, newHeight)
graph.Dispose()
graph = Nothing
This was causing to lose info from the original image, so when printed in the pdf, that lose of info was very noticeable because, somehow, iTextSharp was drawing bigger than it was, no matter the scaling I put in there.
So I tried to store the image as it was originally, preventing the user to not upload images bigger than 200K and resizing the image so I could mantain the aspect ratio, and using that resizing with the iTextSharp Image object before it was printed.
This solved my problem of the image being printed with poor quality for these bigger images but caused the pdf document to have a page break or just not fit in the page, weird thing because the picture looks good in size but it behaves like it was bigger.
This is a screen capture of the new image:
alt text http://img38.imageshack.us/img38/5756/sshot3tc.png
EDIT 2:
When inspecting the iTextSharp Image that is sent to be printed, it shows no changes after the scaling using ScaleAbsolute, that's why the page breaks. But is shown correctly, like the image was successfully scaled, but the background "paper" wasn't.
The code used so far is the following:
Dim imageFile As String = String.Format("{0}{1}", GetAppSetting("UploadDirectory"), myCompany.LogoUrl)
Dim thisImage As Image = Image.GetInstance(imageFile)
thisImage.Alignment = Image.LEFT_ALIGN
Dim newWidth As Integer = myCompany.LogoWidth
Dim newHeight As Integer = myCompany.LogoHeight
ResizeImageToMaxValues(newWidth, newHeight)
thisImage.ScaleAbsolute(newWidth, newHeight)
para.Add(thisImage)
pdf.PdfDocument.Add(para)
The method ResizeImage() do the resizing of the width and height respecting the aspect ratio and keeping in a max width and a max height limits.
Please let me know if I need to provide more info. Thanks
Apart from the printer issue (See above), the 3 X tip by Your Friend was the final solution.
So, to rephrase, if you want the image to be 100 X 100 on the PDF, then make sure that your image is 300px X 300px or larger.
I try to also use 300dpi images and I have not tested with lower quality images.
This is my image adding code:
try
{
string uri = Environment.CurrentDirectory + "/" + "pdfwithimage_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";
string strImgJpg = Environment.CurrentDirectory + "/HeaderImage.jpg";
Image imgJpg = Image.GetInstance(System.Drawing.Image.FromFile(strImgJpg), new BaseColor(System.Drawing.Color.White));
using (Document pdf = new Document(PageSize.A4, 20, 20, 20, 20))
{
if (pdf == null)
{
throw new NullReferenceException("PDF has not been instanciated");
}
if (File.Exists(uri))
{
File.Delete(uri);
}
using (PdfWriter pdfwriter = PdfWriter.GetInstance(pdf, new FileStream(uri, FileMode.Create)))
{
pdf.Open();
imgJpg.SetDpi(300, 300);
imgJpg.ScaleToFit(100f, 100f);
pdf.Add(imgJpg);
pdf.Close();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
I also have good experience with iTextSharp rendering very sharp and clear images. I tried both adding the image directly to the document and adding it to a paragraph first. Both give very clear results.
Dim document As Document = New Document(pSize, 20, 20, 20, 20)
PdfWriter.GetInstance(document, New FileStream(myPath & "Test.pdf", FileMode.Create))
document.Open()
Dim png As Image = Image.GetInstance(myPath & "myImageFile.png")
document.Add(png)
Dim pgr As New Paragraph
pgr.Add(png)
document.Add(pgr)
document.Close()
I normally use .png images, but I have had the same success with jpeg, gif, etc.
Are you certain that when you retrieve the image in iTextSharp it is the exact same image that you retrieve when you are in Acrobat? I ask because it is unclear what exaclty is happening in your code:
Dim imageFile As String=String.Format(.....
EDIT
Also, to make sure that the image is displaying at the size you are expecting, save your images at 72dpi. 72 dpi is what iTextSharp uses for everything (images, margins, etc..).
That way, a 100px x 100px image will show up as 100x100 on your pdf document. You won't have to worry about scaling or re-sizing then. Any time that you scale an image (up or down) you run the risk of introducing aliasing artifacts (blurriness).
To make the rendering clear, try to make the image 3 times the original image, then you can apply ScalePercent or ScaleToFit to resize to certain size.
Sample:
Image logo = Image.GetInstance(pdfReportData.CompanyLogoPath);
logo.ScaleToFit(175f, 108f);
document.Add(logo);
The trick is to use larger images and scale them down. If the scale is not set and the image has its natural size, it will be poor quality. If the scale is set down and the image is drawn smaller than its natural size, the quality will be better.
Example of scaling down to 7 percent size (high quality):
var logo = Image.GetInstance(RImages.logo_600_icon, BaseColor.WHITE);
logo.ScalePercent(7);
var cell = new PdfPCell(logo);
cell.Border = 0;
table.AddCell(cell);
That's strange. I get super-crisp images in my pdf files. There are few differences between what I do and what you have. For example I create the image like this:
Image instance = Image.GetInstance(System.Drawing.Image.FromFile(pathToImage), Color.WHITE);
Furthermore, since my image is too big to fit I call:
instance.ScalePercent(90f);
Another difference is that I add the image directly to the Document and not to a Paragraph, although I doubt that that's it.
Edit:
And finally, my images are jpegs.
Hope it helps.
I ran into the same problem. I was able to fix it by turning off compression. My pdf files I'm generating aren't very large so the file size hit wasn't too expensive.
var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, stream);
writer.SetPdfVersion(iTextSharp.text.pdf.PdfWriter.PDF_VERSION_1_7);
writer.CompressionLevel = PdfStream.NO_COMPRESSION;
On my side it ended up being a printer setting!
Changing the graphics to Raster (from Vector) made the images as crisp as they should be, but slowed the system down tremendously.
The second solution (thanks to the FD) was to change the graphics back to Vector, but to set the "Image Processing" to Best.
We are using a RICOH Aficio MP C2050 PCL 6.
Use bigger png images and than with iTextSharp change the size.
logoImage.ScalePercent(24f);

Resources