ImageBuilder.Current.DecodeStream() doesn't resize - imageresizer

I'm passing a memory stream to the ImageBuilder.Current.DecodeStream() method, with some resize settings, but it's not resizing the resulting bitmap.
var bitmapData = Convert.FromBase64String(base64Image.FixBase64ForImage());
var streamBitmap = new MemoryStream(bitmapData);
var bitImage = ImageBuilder.Current.DecodeStream(streamBitmap, settings, "");
FixBase64ForImage() is just an extension method I wrote to remove the data:image/jpg;;base64, from the submitted base64 encoded photo.
I pass a 640x640 square photo to the ImageBuilder.Current.DecodeStream() method, and pass it settings that looks like this
var settings = new ResizeSettings(string.Format("maxwidth={0}&maxheight={1}&format={2}&crop={3}&quality={4}", maxwidth, maxheight,format, crop, quality));
No matter what max width/height I pass it, it always returns the full 640x640 photo (and seems like there is no quality compression as well).
This leads me to believe the resize settings are simply ignored. Is there another way to accomplish the same thing, or am I doing this wrong?

ImageBuilder.Current.DecodeStream does not do any image processing; it is only for decoding an image stream into an image bitmap. It is called by .LoadImage(), among others.
Use the .Build() overloads to perform image processing.

Related

Can't get the size of a local image

I'm trying to get the height of a local image to scale it on React-Native. I tried the following code but I get Failed to get size for image: ../../images/body.png error.
scaleImg(h) {
Image.getSize('../../images/body.png', (width, height) => {
const scaleFactor = height / h
const imageWidth = width / scaleFactor
this.setState({imgWidth: imageWidth, imgHeight: h})
})
}
I'm late to the party, but there's still no answer. For local assets you gotta use Image.resolveAssetSource(require('./path')); instead.
As per the documentation, you can't use Image.getSize on static image resources, which is what your path seems to link to.
static getSize(uri: string, success: function, failure?: function):
Retrieve the width and height (in pixels) of an image prior to
displaying it. This method can fail if the image cannot be found, or
fails to download.
In order to retrieve the image dimensions, the image may first need to
be loaded or downloaded, after which it will be cached. This means
that in principle you could use this method to preload images, however
it is not optimized for that purpose, and may in future be implemented
in a way that does not fully load/download the image data. A proper,
supported way to preload images will be provided as a separate API.
Does not work for static image resources.

How can I draw a text into a buffered image with different font affects in Java 2d?

I am trying to convert Multi-line Text to image but couldn't found a way to draw it with different Font format's is there any way to do it.Thanks in Advance.
What you could do is simply loading an image, and then setting it as the default graphics context, and then drawing text with a Graphics2D object using different fonts. Here's how you could do this :
BufferedImage image = ImageIO.load(new File("test.png"));
Graphics2D g2d = image.createGraphics();
g2d.setFont(new Font("TimesRoman", Font.PLAIN, fontSize));
g2d.drawString("test", posx, posy, etc.)
If you want simply to draw to a blank image and then save it, just create a BufferedImage using the default constructor. Then, to save the image :
File output = new File("test.png");
ImageIO.write(image, "png", output);
If you want to know more about this, here's a link to Oracle's Java2D tutorials : https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
(from where these examples are).

Resizing .tif image with imgscalr

I am trying to resize a .tif image and then display it on the browser by converting it to a base64 string. Since ImageIo doesn't support TIF images by default, i have added imageio_alpha-1.1.jar(got it here - http://www.findjar.com/jar/geoserver/jai/jars/jai_imageio-1.1-alpha.jar.html). Now ImageIO is able to register the plugin, which i checked by doing this
String[] writerNames = ImageIO.getWriterFormatNames();
writerNames has TIF in it, this means ImageIO has registered the plugin.
I am resizing the image like this
Map resizeImage(BufferedImage imageData, int width, int height, String imageFormat){
BufferedImage thumbnail = Scalr.resize(imageData, Scalr.Method.SPEED, Scalr.Mode.FIT_EXACT ,
width, height, Scalr.OP_ANTIALIAS);
String[] writerNames = ImageIO.getWriterFormatNames();
ByteArrayOutputStream baos = new ByteArrayOutputStream()
ImageIO.write(thumbnail, imageFormat, baos)
baos.flush()
byte[] imageBytes = baos.toByteArray()
baos.close()
return [imageBytes:imageBytes, imageFormat:imageFormat]
}
String encodeImageToBase64(byte[] imageData){
return Base64.encodeBase64String(imageData)
}
BufferedImage getBufferedImage(byte[] imageData){
ByteArrayInputStream bais = new ByteArrayInputStream(imageData)
BufferedImage bImageFromConvert = ImageIO.read(bais)
bais.close()
return bImageFromConvert
}
String resizeToDimensions(byte[] imageData, String imageFormat, int width, int height){
def bimg = getBufferedImage(imageData)
Map resizedImageData = resizeImage(bimg, width, height, imageFormat)
return encodeImageToBase64(resizedImageData.imageBytes)
}
now i am displaying the image like this
< img src = "data:image/tif;base64,TU0AKgAAAAgADAEAAAMAAA...." /> with this i get failed to load url message(on hovering)
as far as i know the base64 string usually starts with /9j/(may be i am wrong). when i am appending /9j/. I get an error - "image corrupt or truncated". I am not able to figure out the problem here, please help.
At first glance your use of the Data URI format looks correct -- try and narrow down exactly where the failure is.
I would recommend:
In your method where you return the string to the front end, I would recommend printing the entire thing out to the console to get the raw data in Data URI format.
Take the Data URI string, create a sample HTML file with the hard-coded value in it, try and load it... does the image display? If so, great, then your problem is with how you are streaming that back to the front end or how you are trying to load it. (Likely a JavaScript/DOM issue)
If that doesn't work, try and chop the Base64 section out of the example and save it into an example TXT file. In your Java code, load it, decode it and try and create an image out of it and write it back out to a TIFF -- if that didn't work, then there is something wrong with your Base64 handling and the encoding is invalid most likely.
Getting that far should answer most of the questions.
Actually now that I think about it, try and use ImageIO to read the image into a BufferedImage, then process it with imgscalr, then immediately call ImageIO.write and try and write it out to a new TIF someplace else and make sure the ImageIO decoding/encoding process is working correctly.
Hope that helps!

PDF lossy compression

I'm looking for a library or command-line program that can compress PDFs.
Compression speed and file size are very important.
The PDFs are full of very large print-quality images.
Adobe Acrobat does high-quality, fast compression but does not allow "reduced size pdfs" to be saved through a programmatic interface.
Ghostscript does high-quality compression be takes way too long (minutes).
If a commercial library is an option, you could give Amyuni PDF Creator a try. There is .net version (C#/VB.Net etc) and an ActiveX version (for C++/Delphi/VB/PHP etc).
You can iterate through all the objects of each page, pick those who are images, and reduce their size. You have several possibilities there:
Setting a lower compression rate.
Down-sampling (extracting the image, re-sizing it to a lower
resolution, and putting it back in your file)
Combining the previous two.
Here is how the code would look like for the first option, in C#, using Amyuni PDF Creator .Net:
//open a pdf document
document.Open("c:\\temp\\myfile.pdf","");
IacPage page1 = document.GetPage (1);
Amyuni.PDFCreator.IacAttribute attribute = page1.AttributeByName ("Objects");
// listobj is an array list of graphic objects
System.Collections.ArrayList listobj = (System.Collections.ArrayList) attribute.Value;
foreach ( object pdfObj in listobj )
{
if ((IacObjectType)pdfObj.AttributeByName("ObjectType").Value == IacObjectType.acObjectTypePicture)
{
if ((IacImageCompressionConstants)pdfObj.AttributeByName("Compression").Value == IacImageCompressionConstants.acCompressionJPegMedium)
pdfObj.AttributeByName("Compression").Value = IacImageCompressionConstants.acCompressionJPegLow;
if ((IacImageCompressionConstants)pdfObj.AttributeByName("Compression").Value == IacImageCompressionConstants.acCompressionJPegHigh)
pdfObj.AttributeByName("Compression").Value = IacImageCompressionConstants.acCompressionJPegMedium;
// (...)
}
}
usual disclaimer applies
You might want to try Docotic.Pdf library for your task.
Here is a code that scales all images that have width or height greater or equal to 256. Scaled images are then encoded using JPEG compression with quality set to 65.
public static void RecompressToJpeg(string path, string outputPath)
{
using (PdfDocument doc = new PdfDocument(path))
{
foreach (PdfImage image in doc.Images)
{
// image that is used as mask or image with attached mask are
// not good candidates for recompression
if (!image.IsMask && image.Mask == null && (image.Width >= 256 || image.Height >= 256))
image.Scale(0.5, PdfImageCompression.Jpeg, 65);
}
doc.Save(outputPath);
}
}
You could also just recompress images without changing their sizes using one of the RecompressWithJpeg methods (or one of other RecompressXXX methods).
And images can be resized to specified width and height using one of the ResizeTo methods. Please note that you will need to take aspect ratio into account in the latter case.
Disclaimer: I work for the vendor of the library.

Page by page conversion of PDF into TIFF with proper compression

Problem
There are PDF documents with different type of objects inside. There are simple texts. There can be scanned images that are B&W, and also other images, that are true color. The resolution can be quite high for both (~1789X2711).
I need to convert the PDF into a set of single page TIFF files. There are quite good tools for that. For example Irfanview, ImageMagick. The problem is that I have to define a single compression type for all the pages.
Using JPG for all pages would result in loosing details for B&W images and they would be huge compared to lossless fax compression.
Using lossless fax for all would wanish colors and details of true color images.
Idea
It would be nice to examine the PDF page by page. I could check the content of the page. What kind of images are there inside, and which compression is recommanded for the particular page. I think this can be done with IText, but I don't know exactly, how it should be done. A second thing is that I want to do this analysis without fully reading the PDF file. Is it possible?
Maybe the fastest solution would be to create a list of pages for each compression type with IText analysis, and then to call Irfanview to process the choosen pages with the proper compression.
Any ideas and recommendations are welcome.
UPDATE:
I have now an answer. It does not cover all requirements, and its not freeware. Any opensource ideas? Maybe Java based solutions?
This can be done with DotImage DotPdf from Atalasoft (cue the obligatory "I work there and work on these products"). Here is how I would do this task in C#:
PdfImageSource source = new PdfImageSource(pdfStream);
while (source.HasMoreImages()) {
AtalaImage image = source.AcquireNext();
string fileName = GetNextTiffName();
using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
TiffEncoder encoder = new TiffEncoder();
encoder.Compression = SelectCompression(image.PixelFormat);
image.Save(outStm, encoder, null);
}
source.Release(image);
}
private TiffCompression SelectCompression(PixelFormat pf)
{
switch (pf) {
// 1 bit? use CCITT G4
case PixelFormat.Pixel1bbIndexed: return TiffCompression.Group4FaxEncoding;
// 24 bit? use JPEG
case PixelFormat.Pixel24bppBgr: return TiffCompression.JpegCompression;
// all else, Lzw
default: return TiffCompression.Lzw;
}
}
You can make SelectCompression do pretty much whatever you want. If you select an invalid compression for that pixel format, the encoder will use an appropriate lossless one in its place (for example, if you select CCITT for 24bit color, the encoder will instead use Lzw).
Our PDF decoder knows when a PDF page is just gray and returns a gray image. It does NOT do anything to get you to 1 bit (this is so antialiased text looks good), however you could threshold the gray image and look at the overall differences between it and the gray image to determine if it could go to 1 bit).
Here's how you could do a set of pages:
public void ExtractNPages(Stream pdfStream, params int[] pageIndexes)
{
PdfImageSource source = new PdfImageSource(pdfStream);
for (int i in pageIndexes) {
AtalaImage image = source[i]; // implied Acquire
string fileName = GetNextTiffName();
using (FileStream outStm = new FileStream(fileName, FileMode.Create)) {
TiffEncoder = new TiffEncoder();
encoder.Compression = SelectCompression(image.PixelFormat);
image.Save(outStm, encoder, null);
}
source.Release(image);
}
}
so now you can just do ExtractNPages(stm, 0, 2, 4, 6);