Apache PDFBox Renders Straight Line Crooked in PNG - java

I have a PDF that when I render it to a png it renders a line crooked, or rather with a step in it. This is the PDF and what it should look like: https://drive.google.com/file/d/1E-zucbreD7pVwWc3Z4MNe_lzsP6D9m49/view
Here is the full PNG rendering using PDFBox 2.0.13 and openjdk version 1.8.0_181:
And here is the specific portion of the PNG that has the step:

Excerpt of the page content stream:
q
1 0 0 1 35.761 450.003 cm
0 i
0.75 w
0 0 m
50.923 0 l
S
Q
q
1 0 0 1 86.139 450 cm
0 i
0.75 w
0 0 m
14.9 0 l
S
Q
("cm" is an affine transform, "m" a moveto, "l" a lineto). One can see that the two lines are slightly different, one at 450.003, the other one at 450.
Here's some code that simulates the error by replicating what PDFBox is doing:
BufferedImage bim = new BufferedImage(612, 792, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) bim.getGraphics();
RenderingHints r = new RenderingHints(null);
r.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
r.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
r.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.addRenderingHints(r);
g.translate(0, 792);
g.scale(1, -1);
g.setStroke(new BasicStroke(0.75f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10));
g.setColor(Color.black);
GeneralPath path = new GeneralPath();
path.moveTo(35.761f, 450.003f);
path.lineTo(35.761f + 50.923f, 450.003f);
g.draw(path);
path = new GeneralPath();
path.moveTo(86.139f, 450f);
path.lineTo(86.139f + 14.9f, 450f);
g.draw(path);
g.dispose();
ImageIO.write(bim, "png", new File("...."));
One can get rid of the error by commenting this line:
r.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
This could be done in the source code of PDFBox, or by passing the renderingHints in PDFRenderer.setRenderingHints(). However that one isn't available now, but will be available in 2.0.14 (see issue PDFBOX-4435, try a snapshot). And you can expect the rendering to be of poor quality by not having anti aliasing.
Update:
instead of removing the line mentioned above, add this one:
r.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
Source.

Related

Add spot color (direct tone) to a PDF

Does any one have example code to add a direct tone to a PDF?
It is to a printer production to detect a rectangle to cut up.
this spot color is named « decoupe » and i need it for the rectangle.
I don’t need to modify the CMYK value of the separation.
I need to had a color named "decoupe" to the document and use this color to create a rectangle with this color, the printer detects this color to cut the document to the format. In the PDF document the line should be like that: 14 0 obj [/Separation /decoupe /DeviceCMYK << /Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] /C1 [0.000000 0.000000 0.000000 0.000000] /FunctionType 2 /Domain [0 1] /N 1>>] endobj
This code adds a rectangle to an existing PDF with a spot color. I changed the c1 values to 1 1 1 1 so that something gets visible (yours was 0 0 0 0).
public static void main(String[] args) throws IOException
{
PDDocument doc = PDDocument.load(....);
COSArray array = new COSArray();
array.add(COSName.SEPARATION);
array.add(COSName.getPDFName("decoupe"));
array.add(COSName.DEVICECMYK); // alternate color
COSDictionary fdict = new COSDictionary();
fdict.setInt(COSName.FUNCTION_TYPE, 2);
COSArray range = new COSArray();
range.add(COSInteger.get(0));
range.add(COSInteger.get(1));
range.add(COSInteger.get(0));
range.add(COSInteger.get(1));
range.add(COSInteger.get(0));
range.add(COSInteger.get(1));
range.add(COSInteger.get(0));
range.add(COSInteger.get(1));
COSArray domain = new COSArray();
domain.add(COSInteger.get(0));
domain.add(COSInteger.get(1));
COSArray c0 = new COSArray();
c0.add(COSFloat.get("0"));
c0.add(COSFloat.get("0"));
c0.add(COSFloat.get("0"));
c0.add(COSFloat.get("0"));
COSArray c1 = new COSArray();
c1.add(COSFloat.get("1"));
c1.add(COSFloat.get("1"));
c1.add(COSFloat.get("1"));
c1.add(COSFloat.get("1"));
fdict.setItem(COSName.DOMAIN, domain);
fdict.setItem(COSName.RANGE, range);
fdict.setItem(COSName.C0, c0);
fdict.setItem(COSName.C1, c1);
fdict.setInt(COSName.N, 1);
PDFunctionType2 func = new PDFunctionType2(fdict);
array.add(func); // tint transform
PDColorSpace spotColorSpace = new PDSeparation(array);
PDPage page = doc.getPage(0);
PDPageContentStream cs = new PDPageContentStream(doc, page, AppendMode.APPEND, true, true);
PDColor color = new PDColor(new float[]{0.5f}, spotColorSpace);
cs.setStrokingColor(color);
cs.setLineWidth(10);
cs.addRect(50, 50, 300, 300);
cs.stroke();
cs.close();
doc.save(...);
}
What I used as help: the source code of PDSeparation.java, and the CreateGradientShadingPDF.java example from the source code download, that one has a type 2 function that I could easily copy and modify.

Java JRE built-in image for testing purposes

Is there an image within the JRE that can be used for testing purposes? I'm looking for either an Image, BufferImage or Icon object. I did find a PNG file in the JRE path that I am currently using but looking to see what others have found or are using.
Try the following. This code will generate a test image of any resolution. It does not use a built-in image but I think this will work best for you. Tweak as necessary to meet your needs.
static private Image createTestImage(final int resolution) {
final Image image = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_ARGB);
final Graphics g = image.getGraphics();
final int points = (resolution * 72) / 96;
g.setColor(new Color(.42f, .42f, 1.0f, .5242f));
g.setFont(new Font("Dialog", Font.BOLD, points));
g.drawString("!X!", 2, points);
g.setColor(Color.BLACK);
g.drawOval(0, 0, image.getWidth(null) - 1, image.getHeight(null) - 1);
g.drawOval(11, 11, image.getWidth(null) - 23, image.getHeight(null) - 23);
g.drawOval(22, 22, image.getWidth(null) - 45, image.getHeight(null) - 45);
return image;
}
Using
Image image = createTestImage(1024);
Produces a hi res image like:
Using
Image image = createTestImage(64);
Produces a lo res image like:
Depending on the OS, there are a number of image files bundled with the JRE...
There are images in C:\Program Files\Java\jre7\lib\images\cursors on Windows, and on Linux I found:
denis#laptop:~/Programs/jdk1.7.0_11/jre$ find | grep png
./lib/deploy/mixcode_s.png
./lib/images/icons/sun-java.png
./lib/images/icons/sun-java_HighContrast.png
./lib/images/icons/sun-java_HighContrastInverse.png
./lib/images/icons/sun-java_LowContrast.png
... (many others) ...

Load image of size greater than 2880 in Bitmap

I am using bitmap to load the image, if the image size is more than 2880 h/w I am getting an error.
BitmapData src = new BitmapData(canvasToPrint.width,canvasToPrint.height)(canvasToPrint.width, canvasToPrint.height);
src.draw(_designArea); // -- encode the jpg
var quality:int = 115;
var jpg:JPEGEncoder = new JPEGEncoder(quality);
var byteArray:ByteArray = jpg.encode(src);
if canvasToPrint.width > 2880 or canvasToPrint.width > 2880 I will get below error at line 1
Error : invalid Bitmap
To over come the above issue I have used bitmapdataunlimited class, as mentioned in the below link.
http://blog.formatlos.de/2008/05/28/bitmapdataunlimited/comment-page-2/#comment-4870
But it only works fine for 4096 pixel of height and width, guide me if any alternative solution is there to create huge bitmap.
If makes a difference which FlashPlayer you are targetting:
versions VS maximum bitmapsize
flashplayer -9 : 2880x2880 px
flashplayer 10 : 4096x4096 px
flashplayer 11 : unlimited
http://www.bit-101.com/blog/?p=2067
Try this

Java A3 printing on Macs coming out at A4 scale

I have an odd problem that seems to be specific to Mac computers. I have a prog that prints the content of an AWT drawing surface to an A3 sheet of paper. On Linux and windows machines the output is OK. Printing from a Mac I get the same dialog with the same preset parameters, the printer prints on an A3 sheet of paper as expected, but for some reason the image is scaled to fit an A4 area. Below are the relevant sections of code:
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat format = new PageFormat();
format.setOrientation(PageFormat.LANDSCAPE);
double margin = 18; // quarter inch
double m2 = margin * 2;
Paper paper = format.getPaper();
paper.setSize(16.54 * 72, 11.69 * 72); // A3 Landscape
paper.setImageableArea(margin, margin, paper.getWidth()-m2, paper.getHeight()-m2);
format.setPaper(paper);
printJob.setPrintable(this, format);
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
attributes.add(MediaSizeName.ISO_A3);
attributes.add(OrientationRequested.LANDSCAPE);
attributes.add(new MediaPrintableArea((int)margin, (int)margin,
(int)(paper.getWidth()-m2), (int)(paper.getHeight()-m2),
MediaPrintableArea.INCH));
if(printJob.printDialog(attributes) ){
try {
printJob.print(attributes);
} catch(PrinterException pe) {
pe.printStackTrace();
}
}
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if(this.componentToBePrinted instanceof PlannerView){
setScale(g2d);
}
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
public void setScale(Graphics2D g2d){
PlannerView planner = (PlannerView)this.componentToBePrinted;
planner.resetZoom();
double scale = 1.0 / planner.getRowLength();
scale *= 4.0;
g2d.scale(scale, scale);
}
Does anyone know what could be causing this?
Cheers.
Try calling
PageFormat newFormat =printJob.pageDialog(format);
before printing, the printer may modify the margins.
At least take a look in the debugger and see what it turns into.
Also note that the Macintosh native printing coordinate systems for landscape is inverted.
So maybe try it with REVERSE_LANDSCAPE instead of LANDSCAPE ( and it might be flipped, but may not get list in translation)
Deal with setImageableArea(), change the values and try. Also apply reverse_landscape for mac.
And set the A3 size: 1190 & 842 not decimal values.

java print api - printing JComponent at 300dpi

please tell me if I am doing something wrong. I want to print barcodes onto labels, so I need high quality printout for these barcodes so I am pushing printer to print in 300dpi. What I've done:
made a big JFrame; width: 2490px, height: 3515px so it represents A4 paper in 1:1 measure (this is A4 paper resolution if print is to be 300dpi)
draw 40 barcode images onto contentPane of that JFrame
setup print attributes so it will print in 300dpi:
PrintRequestAttributeSet aset =
new HashPrintRequestAttributeSet();
PrinterResolution pr =
new PrinterResolution(300,300,PrinterResolution.DPI);
MediaPrintableArea mpa=new MediaPrintableArea(8,21,
210-16, 296-42, MediaPrintableArea.MM);
attribute set is filled with this data:
aset.add( mpa );
aset.add( pr );
aset.add( MediaSizeName.ISO_A4 );
aset.add( new Copies(1) );
aset.add(OrientationRequested.PORTRAIT );
aset.add(PrintQuality.HIGH);
aset.add( Fidelity.FIDELITY_TRUE );
printJob.setPrintable(this);
printJob.print(aset);
this class has print method:
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),pageFormat.getImageableY());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
I need to have 40 barcodes on that A4 sheet, each in size 48.5mm x 25.4mm.
What is printed out on paper is 6 barcodes each doubled in size of 104mm x 46mm (that is in width almost half of page's width) which fulfilled whole paper.
Any idea, what can I do wrong?
Your resolution is probably being set to 72 dpi which has the effect of increasing the size of the image.

Categories