Java print - page - java

My application allows the user to print the screen content which is made of several Swing controls (images, texts, etc.) - the printed panel it self is long (several pages) and the width about 600pixels.
Since I know exactly each page layout (I put the exact number of images and components) on each page (the total number of images is dynamic), I can calculate exactly how many pages I will need for the print.
I've implemented the Printable interface as follows:
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK); //set default foreground color to black
RepaintManager.currentManager(this).setDoubleBufferingEnabled(false);
Dimension d = this.getSize(); //get size of document
double panelWidth = d.width; //width in pixels
double panelHeight = d.height; //height in pixels
double pageHeight = pf.getImageableHeight(); //height of printer page
double pageWidth = pf.getImageableWidth(); //width of printer page
double scale = pageHeight / panelHeight;
int totalNumPages = (int) Math.ceil(scale * panelWidth / pageWidth);
if (pageIndex >= totalNumPages) {
return Printable.NO_SUCH_PAGE;
}
g2.translate(pf.getImageableX(), pf.getImageableY());
g2.translate(0f, -pageIndex * pageHeight);
g2.scale(scale, scale);
this.paint(g2);
return Printable.PAGE_EXISTS;
}
It seems that everything works fine.
Since I don't have a printer, I've tested it using a PDF printer and on several clients printer - and the results were good.
However, on one of my user's printer - it seems that something in not working with the calculation, since it breaks the page in the middle of the images.
Is there a more elegant way to do these calculations ?
Can I add instead a "page break" notification somewhere ?
Thanks

In the past I have found that trying to implement the printable interface myself has caused formatting issues such as you are experiencing. One thing I have done in the past that greatly reduced the effort on my part, and worked well, was using JasperReports to manage this. You could create a jrxml definition that has one image/page, and then just pass the images into the jasperreport. From here you can use the JasperPrint object and send this directly to the printer. This has worked well for me. In addition it has several benefits with the exports already build in to jasper reports such as pdf if needed.

The code itself looks ok, especially considering it works for the PDF printer. I just have some ideas for debugging:
1) Have you checked the printer settings for the user's printer? Maybe the page size is not set correctly.
2) Any way you could hook up your development machine to that printer and debug it?
3) If not, you could add logging to tell you the pg.getImageableWidth and pg.getImageableHeight and other information throughout the calculation to see where it's wrong.

Related

Image Rendering in java throws Out of memory error (using pdfbox)

I was trying to render an image and I was getting out of memory error in this line.
try{
BufferedImage image = pdfRenderer.renderImageWithDPI(page-1, 300,ImageType.GRAY);
ImageIOUtil.writeImage(image,"G:/Trial/tempImg.png", 300);
int bpp = image.getColorModel().getPixelSize();
int bytespp = bpp / 8;
int bytespl = (int) Math.ceil(image.getWidth() * bpp / 8.0);
int height = image.getHeight();
int width = image.getWidth();
TessAPI1.TessBaseAPISetImage(handle, ImageIOHelper.convertImageData(image), width, height, bytespp, bytespl);
TessAPI1.TessBaseAPISetPageSegMode(handle, TessPageSegMode.PSM_AUTO);
//codes
}
finally
{
//some code so that this function could be called again with next pdf
//some code to release resources
}
In this code segment first I am rendering a particular page from a pdf document to BufferedImage and then I am converting the bufferedImage to Bytes before providing it to tesseract. It is at this point that I am getting an Out of memory Error.
Normally when you get an out of memory error you get one more message beside it , either out of heap or out of perm. But, here I am getting just an out of memory error. Please explain this.
When I was debugging this code I observed that the code doesn't terminate at the line where I am converting image to byte but rather it goes to finally block (I am using try and finally block for this code segment).
So I put a continue in my finally and voila my code was running perfectly for next set of pdfs.
So my question is how is my program not exiting after the out of memory error(not that I want it to not work) but If memory is really full then how can the code load next set of pdfs.
An insight on this would be really wonderful.
Thanks
P.S - This problem is solved due to that hack and my code is working but I am curious as to why all this is happening.

Java/JSP: How to add WaterMark on Video

I'm trying to add water mark on image and video. For image i got the solution as below
Image water marking code
Method
static void addWatermarkOnImage(String text, File sourceImageFile, File destImageFile) {
try {
BufferedImage sourceImage = ImageIO.read(sourceImageFile);
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
// initializes necessary graphic properties
AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
g2d.setComposite(alphaChannel);
g2d.setColor(Color.BLUE);
g2d.setFont(new Font("Arial", Font.BOLD, 64));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(text, g2d);
// calculates the coordinate where the String is painted
int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
int centerY = sourceImage.getHeight() / 2;
// paints the textual watermark
g2d.drawString(text, centerX, centerY);
ImageIO.write(sourceImage, "png", destImageFile);
g2d.dispose();
//System.out.println("The tex watermark is added to the image.");
} catch (IOException ex) {
System.err.println(ex);
}
}
Method calling
File sourceImageFile = new File("e:/Test/Watermark/SwingEmailSender.png");
File destImageFile = new File("e:/Test/Watermark/text_watermarked.png");
addTextWatermark("CodeJava", sourceImageFile, destImageFile);
By fallowing above code image WaterMarking is working perfectly for me. In case of video water marking i tried lot of examples in online but nothing was helpful for me. So, kindly any one help me for video water marking in java/jsp
The most common and popular open source tool to put a watermark in a video (or text as in another question that just came up) is probably ffmpeg:
https://ffmpeg.org
ffmpeg can be used in the command line or programatically as part of an application (look at the licensing carefully to make sure it meets your needs if you want to distribute etc).
To use it programatically you can either use the command line tool in a wrapper or use the libraries it is built on directly.
Using the libraries directly (libavcodec, libavutil, libavformat, libavfilter, libavdevice, libswscale and libswresample - see the about page at the link above) should be more efficient and allow greater control etc, but the wrapper approach is still popular as it can be simpler to implement at first and there is a wealth of online info on command line syntax to achieve pretty much anything you might want to do, which you get to leverage with this approach.
The libraries are also c based so you will need some interface (e.g. JNI) to them anyway.
An example of a Java wrapper around ffmpeg is:
https://github.com/bramp/ffmpeg-cli-wrapper
There are many online examples of using the ffmpeg tool to add a watermarking to a video - one example is here but it is worth googling to find the latest ad the syntax does change over time:
https://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/watermarks

Detecting position of crop marks in a scanned document

I am working on a project in which user gives us a scanned copy of a form, and we need to identify various fields within the image.
I have a form like this:
The form has four crop marks/ registration marks at four corners of the page. Now the user is supposed to fill the form and give back a scanned copy of his filled form. The scanned form that we get may have been rotated by some angle. For instance see the rotated form below:
Now to extract the exact fields out of form, i.e. to extract any particular field like Title in the scanned form, we need to have exact coordinates but since our image has been rotated by unknown angle. We are unable to do so.
I read about registration marks and their use to align the page to a standard form.
I tried searching for these registration marks in the image, but since it is rotated we may not find the position of the mark in the rotated image.
I tried searching for the issue and found some questions on SO which although gave some direction but couldn't help much.
This Question gave me reference to LEADTools SDK which has functions to perform this tasks. Unfortunately this SDK is not for JAVA and along with that it's proprietary and not free.
Is there any other open source tools for the same purpose.
Additionally I am open to suggestions about other methods used to align the form.
You could use the coordinates of the markers in the corner of the document. Using the coordinates of the corners of the lines, you could measure the rotation angle of the paper in order to compensate it.
The post below addresses a similar issue:
"Image Processing Edge Detection in Java"
Below an approach to detect the coordinates using Java and Marvin.
output (some noise cause of the JPEG compression):
source code:
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
import marvin.util.MarvinAttributes;
import static marvin.MarvinPluginCollection.*;
public class DocumentMarks {
public DocumentMarks(){
MarvinImage image = MarvinImageIO.loadImage("./res/document.jpg");
thresholding(image, 250);
MarvinAttributes ret = moravec(image.clone(), image, 5, 100000);
image = showCorners(image, ret, 4);
MarvinImageIO.saveImage(image, "./res/document_out.jpg");
}
private static MarvinImage showCorners(MarvinImage image, MarvinAttributes attr, int rectSize){
MarvinImage ret = image.clone();
int[][] cornernessMap = (int[][]) attr.get("cornernessMap");
int rsize=0;
for(int x=0; x<cornernessMap.length; x++){
for(int y=0; y<cornernessMap[0].length; y++){
// Is it a corner?
if(cornernessMap[x][y] > 0){
rsize = Math.min(Math.min(Math.min(x, rectSize), Math.min(cornernessMap.length-x, rectSize)), Math.min(Math.min(y, rectSize), Math.min(cornernessMap[0].length-y, rectSize)));
ret.fillRect(x, y, rsize, rsize, Color.red);
}
}
}
return ret;
}
public static void main(String[] args) {
new DocumentMarks();
System.exit(0);
}
}
I successfully identified crop marks in the scanned document. I've described the approach on my blog here.

Why does this image look so bad after being scaled down in Java?

Here is the original image: http://rank.my/public/images/uploaded/orig-4193395691714613396.png
And here it is scaled down to 300x225:
http://rank.my/public/images/uploaded/norm-4193395691714613396.png
And here it is scaled down to 150x112:
http://rank.my/public/images/uploaded/small-4193395691714613396.png
As you can see, 300x225 looks pretty bad, and 150x112 looks awful. Here is the code I'm using to scale down the image:
private static BufferedImage createResizedCopy(final BufferedImage source, final int destWidth,
final int destHeight) {
final BufferedImage resized = new BufferedImage(destWidth, destHeight, source.getType());
final Graphics2D bg = resized.createGraphics();
bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
bg.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final float sx = (float) destWidth / source.getWidth();
final float sy = (float) destHeight / source.getHeight();
bg.scale(sx, sy);
bg.drawImage(source, 0, 0, null);
bg.dispose();
return resized;
}
What am I doing wrong here? The image scaling doesn't have to be especially fast, quality is definitely a priority over speed. Am I using the wrong technique?
There are three ways to fix the downscaling problem. First is to do it in multiple steps, with no more than a 75% reduction in each step. The second is to blur the image before resizing; the more it shrinks, the more you'll have to blur. The third way is to use a method that filters using more than the 2x2 to 4x4 pixel blocks used by a naive bilinear or bicubic interpolation method. As the shrink factor grows larger, so should the pixel block used by the filter, otherwise you get aliasing artifacts as you've seen here.
I've never used these libraries so I feel unqualified to answer, but I can't help but pass along these links I found that I think may be useful. Hopefully this will help.
http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
http://www.componenthouse.com/article-20
JAI is pretty frustrating. I still wonder why, no matter what settings you do, it never matches the speed, quality and simplicity of ImageMagick. I prefer to use ImageMagick wherever I can.
The code below is what gives me best result for image scaling. Please note that I have used RenderingHints.VALUE_RENDER_QUALITY and SubsampleAverage and not RenderingHints.VALUE_INTERPOLATION_BICUBIC.
I have wrapped up JAI processing in a small block and always use it to scale down. The same code does not give good result when you scale-up -- a different setting applies for that. I have not tried with PNG, JPEG is what I worked with.
Hope this helps
//Set-up and load file
PlanarImage image = JAI.create("fileload", absPath);
RenderingHints quality = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
Properties p = new Properties(System.getProperties());
p.put("com.sun.media.jai.disableMediaLib", "true");
System.setProperties(p);
//Setup the processes
ParameterBlock pb = new ParameterBlock()
.addSource(image)
.add(scaleX) //scaleX = (double)1.0*finalX/origX
.add(scaleY); //scaleY = (double)1.0*finalY/origY
RenderedOp tempProcessingFile = JAI.create("SubsampleAverage", pb, quality);
//Save the file
FileOutputStream fout = new FileOutputStream(file);
JPEGEncodeParam encodeParam = new JPEGEncodeParam();
encodeParam.setQuality(0.92f); //My experience is anything below 0.92f gives bad result
ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", fout, encodeParam);
encoder.encode(tempProcessingFile.getAsBufferedImage());
Also, the articles that helped me are.
https://jaistuff.dev.java.net/docs/jaitutorial.pdf
http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
http://forums.sun.com/thread.jspa?threadID=5332078 Looks like after Oracle acquisition they have washed away the forum posts. This was an extra-ordinary discussion over JAI performance and quality. I still had it bookmarked.
http://www.digitalsanctuary.com/tech-blog/java/how-to-resize-uploaded-images-using-java-better-way.html
(The links above are from my bookmark, edit them if you find they are dead)

How can I resize an image using Java?

I need to resize PNG, JPEG and GIF files. How can I do this using Java?
FWIW I just released (Apache 2, hosted on GitHub) a simple image-scaling library for Java called imgscalr (available on Maven central).
The library implements a few different approaches to image-scaling (including Chris Campbell's incremental approach with a few minor enhancements) and will either pick the most optimal approach for you if you ask it to, or give you the fastest or best looking (if you ask for that).
Usage is dead-simple, just a bunch of static methods. The simplest use-case is:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
All operations maintain the image's original proportions, so in this case you are asking imgscalr to resize your image within a bounds of 200 pixels wide and 200 pixels tall and by default it will automatically select the best-looking and fastest approach for that since it wasn't specified.
I realize on the outset this looks like self-promotion (it is), but I spent my fair share of time googling this exact same subject and kept coming up with different results/approaches/thoughts/suggestions and decided to sit down and write a simple implementation that would address that 80-85% use-cases where you have an image and probably want a thumbnail for it -- either as fast as possible or as good-looking as possible (for those that have tried, you'll notice doing a Graphics.drawImage even with BICUBIC interpolation to a small enough image, it still looks like garbage).
After loading the image you can try:
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
Thumbnailator is an open-source image resizing library for Java with a fluent interface, distributed under the MIT license.
I wrote this library because making high-quality thumbnails in Java can be surprisingly difficult, and the resulting code could be pretty messy. With Thumbnailator, it's possible to express fairly complicated tasks using a simple fluent API.
A simple example
For a simple example, taking a image and resizing it to 100 x 100 (preserving the aspect ratio of the original image), and saving it to an file can achieved in a single statement:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
An advanced example
Performing complex resizing tasks is simplified with Thumbnailator's fluent interface.
Let's suppose we want to do the following:
take the images in a directory and,
resize them to 100 x 100, with the aspect ratio of the original image,
save them all to JPEGs with quality settings of 0.85,
where the file names are taken from the original with thumbnail. appended to the beginning
Translated to Thumbnailator, we'd be able to perform the above with the following:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
A note about image quality and speed
This library also uses the progressive bilinear scaling method highlighted in Filthy Rich Clients by Chet Haase and Romain Guy in order to generate high-quality thumbnails while ensuring acceptable runtime performance.
You don't need a library to do this. You can do it with Java itself.
Chris Campbell has an excellent and detailed write-up on scaling images - see this article.
Chet Haase and Romain Guy also have a detailed and very informative write-up of image scaling in their book, Filthy Rich Clients.
Java Advanced Imaging is now open source, and provides the operations you need.
If you are dealing with large images or want a nice looking result it's not a trivial task in java. Simply doing it via a rescale op via Graphics2D will not create a high quality thumbnail. You can do it using JAI, but it requires more work than you would imagine to get something that looks good and JAI has a nasty habit of blowing our your JVM with OutOfMemory errors.
I suggest using ImageMagick as an external executable if you can get away with it. Its simple to use and it does the job right so that you don't have to.
If, having imagemagick installed on your maschine is an option, I recommend im4java. It is a very thin abstraction layer upon the command line interface, but does its job very well.
The Java API does not provide a standard scaling feature for images and downgrading image quality.
Because of this I tried to use cvResize from JavaCV but it seems to cause problems.
I found a good library for image scaling: simply add the dependency for "java-image-scaling" in your pom.xml.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
In the maven repository you will get the recent version for this.
Ex. In your java program
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
You could try to use GraphicsMagick Image Processing System with im4java as a comand-line interface for Java.
There are a lot of advantages of GraphicsMagick, but one for all:
GM is used to process billions of
files at the world's largest photo
sites (e.g. Flickr and Etsy).
Image Magick has been mentioned. There is a JNI front end project called JMagick. It's not a particularly stable project (and Image Magick itself has been known to change a lot and even break compatibility). That said, we've had good experience using JMagick and a compatible version of Image Magick in a production environment to perform scaling at a high throughput, low latency rate. Speed was substantially better then with an all Java graphics library that we previously tried.
http://www.jmagick.org/index.html
Simply use Burkhard's answer but add this line after creating the graphics:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
You could also set the value to BICUBIC, it will produce a better quality image but is a more expensive operation. There are other rendering hints you can set but I have found that interpolation produces the most notable effect.
Keep in mind if you want to zoom in in a lot, java code most likely will be very slow. I find larger images start to produce lag around 300% zoom even with all rendering hints set to optimize for speed over quality.
You can use Marvin (pure Java image processing framework) for this kind of operation:
http://marvinproject.sourceforge.net
Scale plug-in:
http://marvinproject.sourceforge.net/en/plugins/scale.html
It turns out that writing a performant scaler is not trivial. I did it once for an open source project: ImageScaler.
In principle 'java.awt.Image#getScaledInstance(int, int, int)' would do the job as well, but there is a nasty bug with this - refer to my link for details.
I have developed a solution with the freely available classes ( AnimatedGifEncoder, GifDecoder, and LWZEncoder) available for handling GIF Animation.
You can download the jgifcode jar and run the GifImageUtil class.
Link: http://www.jgifcode.com
you can use following popular product: thumbnailator
If you dont want to import imgScalr like #Riyad Kalla answer above which i tested too works fine, you can do this
taken from Peter Walser answer #Peter Walser on another issue though:
/**
* utility method to get an icon from the resources of this class
* #param name the name of the icon
* #return the icon, or null if the icon wasn't found.
*/
public Icon getIcon(String name) {
Icon icon = null;
URL url = null;
ImageIcon imgicon = null;
BufferedImage scaledImage = null;
try {
url = getClass().getResource(name);
icon = new ImageIcon(url);
if (icon == null) {
System.out.println("Couldn't find " + url);
}
BufferedImage bi = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon = new ImageIcon(scaledImage);
} catch (Exception e) {
System.out.println("Couldn't find " + getClass().getName() + "/" + name);
e.printStackTrace();
}
return imgicon;
}
public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
float scaleX = (float) areaWidth / image.getWidth();
float scaleY = (float) areaHeight / image.getHeight();
float scale = Math.min(scaleX, scaleY);
int w = Math.round(image.getWidth() * scale);
int h = Math.round(image.getHeight() * scale);
int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
boolean scaleDown = scale < 1;
if (scaleDown) {
// multi-pass bilinear div 2
int currentW = image.getWidth();
int currentH = image.getHeight();
BufferedImage resized = image;
while (currentW > w || currentH > h) {
currentW = Math.max(w, currentW / 2);
currentH = Math.max(h, currentH / 2);
BufferedImage temp = new BufferedImage(currentW, currentH, type);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized, 0, 0, currentW, currentH, null);
g2.dispose();
resized = temp;
}
return resized;
} else {
Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image, 0, 0, w, h, null);
g2.dispose();
return resized;
}
}
Try this folowing method :
ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);
you can also use
Process p = Runtime.getRuntime().exec("convert " + origPath + " -resize 75% -quality 70 " + largePath + "");
p.waitFor();
Design jLabel first:
JLabel label1 = new JLabel("");
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setBounds(628, 28, 169, 125);
frame1.getContentPane().add(label1); //frame1 = "Jframe name"
Then you can code below code(add your own height and width):
ImageIcon imageIcon1 = new ImageIcon(new ImageIcon("add location url").getImage().getScaledInstance(100, 100, Image.SCALE_DEFAULT)); //100, 100 add your own size
label1.setIcon(imageIcon1);

Categories

Resources