Home » Archived » BIRT » Bad dynamic image quality in PDF
Bad dynamic image quality in PDF [message #666227] |
Tue, 19 April 2011 14:19 |
Jan Krakora Messages: 477 Registered: December 2009 Location: Prague |
Senior Member |
|
|
Hi,
I use a table in my report containing an dynamic image. The table is bounded to a scripted data set. Using the fetch() method on ScriptedDataSetEventAdapter I contribute byte[] data of my image to the Image in the report. The problem is that the image looks somewhat blurred in PDF report.
I use this render options:
renderOption.setOutputFormat(RenderOption.OUTPUT_FORMAT_PDF);
renderOption.setOutputFileName(filePath);
where filePath is path to created PDF report.
Image in the table has set no size and its property 'fit to container' is set to false. The table has also no size, only a 10 points margin on left and right.
Any advice?
[Updated on: Tue, 19 April 2011 14:21] Report message to a moderator
|
|
|
Re: Bad dynamic image quality in PDF [message #666335 is a reply to message #666227] |
Wed, 20 April 2011 02:05 |
|
You can set the dpi for a report, but you can also set it as a pdf
render option:
PDFRenderOption options = new PDFRenderOption();
options.setOption(IPDFRenderOption.PDF_HYPHENATION, true);
options.setOption(IPDFRenderOption.PDF_TEXT_WRAPPING, true);
options.setOption(IPDFRenderOption.PAGE_OVERFLOW,
IPDFRenderOption.FIT_TO_PAGE_SIZE);
options.setOption(IPDFRenderOption.DPI, 300);
options.setSupportedImageFormats("PNG;GIF;JPG;BMP;SWF;SVG");
options.setOutputFileName("output/resample/svgtest.pdf");
options.setOutputFormat("pdf");
Look at the DPI entry. Also not that I have included SVG in the
setSupportedImageFormats method. This makes a bigger PDF but the charts
with SVG will be better. Take a look at this post for chart resolution.
http://www.eclipse.org/forums/index.php?t=msg&&th=11 8630&goto=361284#msg_361284
Jason
On 4/19/2011 10:19 AM, Behnil wrote:
> Hi,
>
> I use a table in my report containing an dynamic image. The table is
> bounded to a scripted data set. Using the fetch() method on
> ScriptedDataSetEventAdapter I contribute byte[] data of my image to the
> Image in the report. The problem is that the image looks somewhat
> blurred in PDF report.
>
> I use this render options:
>
> renderOption.setOutputFormat(RenderOption.OUTPUT_FORMAT_PDF) ;
> renderOption.setOutputFileName(filePath);
>
> where filePath is path to created PDF report.
>
> Image in the table has set no size and its property 'fit to container'
> is set to false. The table has also no size, only a 10 points margin on
> left and right.
>
> Any advice?
|
|
| | | | | |
Re: Bad dynamic image quality in PDF [message #666691 is a reply to message #666537] |
Thu, 21 April 2011 16:20 |
Jan Krakora Messages: 477 Registered: December 2009 Location: Prague |
Senior Member |
|
|
Yes, I have. But the same problem with the PDF report remained unresolved there.
In fact, the best solution would be to insert an SVG image to the PDF output. But unfortunately BIRT does it badly since it ignores translucent objects (see http:// www.eclipse.org/forums/index.php?t=msg&th=207009&sta rt=0&S=4c9224a2942682e6010a81e7ebefdb4e)
I figured out that BIRT uses transSVG() in the class PDFPage where it draws my svg's byte[] data:
private void transSVG( String svgPath, byte[] svgData, float x, float y, float height,
float width, String helpText ) throws IOException,
DocumentException
{
PdfTemplate template = contentByte.createTemplate( width, height );
Graphics2D g2D = template.createGraphics( width, height );
PrintTranscoder transcoder = new PrintTranscoder( );
if ( null != svgPath )
{
transcoder.transcode( new TranscoderInput( svgPath ), null );
}
else if ( null != svgData && svgData.length > 0 )
{
transcoder.transcode( new TranscoderInput(
new ByteArrayInputStream( svgData ) ), null );
}
PageFormat pg = new PageFormat( );
Paper p = new Paper( );
p.setSize( width, height );
p.setImageableArea( 0, 0, width, height );
pg.setPaper( p );
transcoder.print( g2D, pg, 0 );
g2D.dispose( );
drawImage( template, x, y, height, width, helpText );
}
private void drawImage( PdfTemplate image, float imageX, float imageY,
float height, float width, String helpText )
throws DocumentException
{
imageY = transformY( imageY, height );
contentByte.saveState( );
contentByte.concatCTM( 1, 0, 0, 1, imageX, imageY );
float w = image.getWidth( );
float h = image.getHeight( );
contentByte.addTemplate( image, width/w, 0f/w, 0f/h, height/h, 0f, 0f );
if ( helpText != null )
{
showHelpText( imageX, imageY, width, height, helpText );
}
contentByte.restoreState( );
}
This way, the PDF report contains my SVG image, but all translucent shapes are opaque.
I think there is a problem in the Batik library. Because when I generate a test PDF file containing the SVG image using iText, it looks absolutely amazing:
public static void saveChartAsPDF(File file, JFreeChart chart, int width, int height) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
writeChartAsPDF(out, chart, width, height);
out.close();
}
public static void writeChartAsPDF(OutputStream out, JFreeChart chart, int width, int height) throws IOException {
com.lowagie.text.Rectangle pagesize = new com.lowagie.text.Rectangle(width, height);
Document document = new Document(pagesize, 50, 50, 50, 50);
try {
PdfWriter writer = PdfWriter.getInstance(document, out);
document.open();
PdfContentByte cb = writer.getDirectContent();
PdfTemplate tp = cb.createTemplate(width, height);
Graphics2D g2 = tp.createGraphics(width, height, new DefaultFontMapper());
Rectangle2D r2D = new Rectangle2D.Double(0, 0, width, height);
chart.draw(g2, r2D);
g2.dispose();
cb.addTemplate(tp, 0, 0);
} catch (com.lowagie.text.DocumentException de) {
System.err.println(de.getMessage());
}
document.close();
}
So in other words. Is there a way to override BIRT's SVG handling with my own?
[Updated on: Thu, 21 April 2011 16:22] Report message to a moderator
|
|
|
Re: Bad dynamic image quality in PDF [message #666713 is a reply to message #666691] |
Thu, 21 April 2011 18:47 |
|
I noticed you commented on the bug. I believe the bug has been
assigned. Hopefully one of the devs will respond shortly. Any chance
you could email me the two pdfs one that you used iText directly, one
through birt? Also if I could a blank design with the svg image in it
it would be great. My email address is jasonweathersby at windstream
dot net.
BTW I do not see an extension point to override this behavior but you
could try to extend the pdf emitter.
Jason
On 4/21/2011 12:20 PM, Behnil wrote:
> Yes, I have. But the same problem with the PDF report remained
> unresolved there.
>
> In fact, the best solution would be to insert an SVG image to the PDF
> output. But unfortunately BIRT does it badly since it ignores
> translucent objects (see
> http://www.eclipse.org/forums/index.php?t=msg&th=207009& amp;start=0&S=4c9224a2942682e6010a81e7ebefdb4e)
>
>
> I figured out that BIRT uses transSVG() in the class PDFPage where it
> draws my svg's byte[] data:
>
> private void transSVG( String svgPath, byte[] svgData, float x, float y,
> float height,
> float width, String helpText ) throws IOException,
> DocumentException
> {
> PdfTemplate template = contentByte.createTemplate( width, height );
> Graphics2D g2D = template.createGraphics( width, height );
>
> PrintTranscoder transcoder = new PrintTranscoder( );
> if ( null != svgPath )
> {
> transcoder.transcode( new TranscoderInput( svgPath ), null );
> }
> else if ( null != svgData && svgData.length > 0 )
> {
> transcoder.transcode( new TranscoderInput(
> new ByteArrayInputStream( svgData ) ), null );
> }
> PageFormat pg = new PageFormat( );
> Paper p = new Paper( );
> p.setSize( width, height );
> p.setImageableArea( 0, 0, width, height );
> pg.setPaper( p );
> transcoder.print( g2D, pg, 0 );
> g2D.dispose( );
>
> drawImage( template, x, y, height, width, helpText );
> }
>
> private void drawImage( PdfTemplate image, float imageX, float imageY,
> float height, float width, String helpText )
> throws DocumentException
> {
> imageY = transformY( imageY, height );
> contentByte.saveState( );
> contentByte.concatCTM( 1, 0, 0, 1, imageX, imageY );
> float w = image.getWidth( );
> float h = image.getHeight( );
> contentByte.addTemplate( image, width/w, 0f/w, 0f/h, height/h, 0f, 0f );
> if ( helpText != null )
> {
> showHelpText( imageX, imageY, width, height, helpText );
> }
> contentByte.restoreState( );
> }
>
>
> This way, the PDF report contains my SVG image, but all translucent
> shapes are opaque. I thing there is a problem in the Batik library.
> Because when I generate a test PDF file containing the SVG image using
> iText, it looks absolutely amazing:
>
> public static void saveChartAsPDF(File file, JFreeChart chart, int
> width, int height) throws IOException {
> OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
> writeChartAsPDF(out, chart, width, height);
> out.close();
> }
>
> public static void writeChartAsPDF(OutputStream out, JFreeChart chart,
> int width, int height) throws IOException {
> com.lowagie.text.Rectangle pagesize = new
> com.lowagie.text.Rectangle(width, height);
> Document document = new Document(pagesize, 50, 50, 50, 50);
> try {
> PdfWriter writer = PdfWriter.getInstance(document, out);
> document.open();
> PdfContentByte cb = writer.getDirectContent();
> PdfTemplate tp = cb.createTemplate(width, height);
> Graphics2D g2 = tp.createGraphics(width, height, new DefaultFontMapper());
> Rectangle2D r2D = new Rectangle2D.Double(0, 0, width, height);
> chart.draw(g2, r2D);
> g2.dispose();
> cb.addTemplate(tp, 0, 0);
> } catch (com.lowagie.text.DocumentException de) {
> System.err.println(de.getMessage());
> }
> document.close();
> }
>
>
> So in other words. Is there a way to override BIRT's SVG handling with
> my own?
|
|
| |
Re: Bad dynamic image quality in PDF [message #667017 is a reply to message #666747] |
Mon, 25 April 2011 14:11 |
|
I should have said replace the emitter. You can checkout the source and
replace the pdf emitter plugin. You could also create another emitter
based on the same code but it will have to output another format extension.
Jason
On 4/22/2011 3:24 AM, Behnil wrote:
> The PDFs was sent. How can I extend the PDF emitter?
|
|
|
Re: Bad dynamic image quality in PDF [message #667772 is a reply to message #667017] |
Mon, 02 May 2011 07:34 |
Jan Krakora Messages: 477 Registered: December 2009 Location: Prague |
Senior Member |
|
|
Jason Weathersby wrote on Mon, 25 April 2011 16:11 | I should have said replace the emitter. You can checkout the source and
replace the pdf emitter plugin.
|
That's exactly what I've done and it works great for me now. What I exactly did:
- I've inserted an image report item into the report design.
- I've added an ImageHandler on that image. In its onCreate() method is set MIME type of that image to "image/svg+xml" and my JFreeChart object is serialized into array of bytes. Then this array is set as data of the image. (I know, it's horribly hack )
- I've checkout the BIRT's PDF emitter and extended its transSVG method in PDFPage class:
private void transSVG( String svgPath, byte[] svgData, float x, float y, float height, float width, String helpText ) throws IOException, DocumentException {
PdfTemplate template = null;
Graphics2D g2D = null;
Drawable drawable = null;
ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(svgData));
try {
drawable = (Drawable) inputStream.readObject();
} catch (ClassNotFoundException e) {
logger.log(Level.SEVERE, "Chyba pri deserializaci!", e);
}
if (drawable != null) {
Point2D prefferedSize = drawable.getPreffredSize();
float prefferedWidth = (float) prefferedSize.getX();
float prefferedHeight = (float) prefferedSize.getY();
template = contentByte.createTemplate(prefferedWidth, prefferedHeight);
g2D = template.createGraphicsShapes(prefferedWidth, prefferedHeight);
drawable.draw(g2D, prefferedWidth, prefferedHeight);
g2D.dispose();
} else {
template = contentByte.createTemplate(width, height);
g2D = template.createGraphics(width, height);
PrintTranscoder transcoder = new PrintTranscoder( );
if ( null != svgPath )
{
transcoder.transcode( new TranscoderInput( svgPath ), null );
}
else if ( null != svgData && svgData.length > 0 )
{
transcoder.transcode( new TranscoderInput(
new ByteArrayInputStream( svgData ) ), null );
}
PageFormat pg = new PageFormat( );
Paper p = new Paper( );
p.setSize( width, height );
p.setImageableArea( 0, 0, width, height );
pg.setPaper( p );
transcoder.print( g2D, pg, 0 );
g2D.dispose( );
}
drawImage( template, x, y, height, width, helpText );
}
Note that Drawable is my interface that contains only a draw method and a method for obtaining the object's preferred size. My JFreeChart chart then implements this interface. I know it's not the best solution, but it works for me now.
The summary:
- I say to BIRT this is an svg image, so it calls my edited transSVG method.
- As image's data I dont set svg data but my serialized JFreeChart instead (that's the worst hack).
- Then I draw my chart directly to the PDF using iText.
|
|
|
Re: Bad dynamic image quality in PDF [message #667916 is a reply to message #667772] |
Mon, 02 May 2011 18:36 |
|
Thanks for the update. Any chance you could add your fix to the
bugzilla entry?
Jason
On 5/2/2011 3:34 AM, Behnil wrote:
> Jason Weathersby wrote on Mon, 25 April 2011 16:11
>> I should have said replace the emitter. You can checkout the source and
>> replace the pdf emitter plugin.
>
> That's exactly what I've done and it works great for me now. What I
> exactly did:
>
> I've inserted an image report item into the report design.
> I've added an ImageHandler on that image. In its onCreate() method is
> set MIME type of that image to "image/svg+xml" and my JFreeChart object
> is serialized into array of bytes. Then this array is set as data of the
> image. (I know, it's horribly hack :? )
> I've checkout the BIRT's PDF emitter and extended its transSVG method in
> PDFPage class:
>
>
> private void transSVG( String svgPath, byte[] svgData, float x, float y,
> float height, float width, String helpText ) throws IOException,
> DocumentException {
>
> PdfTemplate template = null;
> Graphics2D g2D = null;
> Drawable drawable = null;
>
> ObjectInputStream inputStream = new ObjectInputStream(new
> ByteArrayInputStream(svgData));
> try {
> drawable = (Drawable) inputStream.readObject();
> } catch (ClassNotFoundException e) {
> logger.log(Level.SEVERE, "Chyba pri deserializaci!", e);
> }
>
> if (drawable != null) {
> Point2D prefferedSize = drawable.getPreffredSize();
> float prefferedWidth = (float) prefferedSize.getX();
> float prefferedHeight = (float) prefferedSize.getY();
>
> template = contentByte.createTemplate(prefferedWidth, prefferedHeight);
>
> g2D = template.createGraphicsShapes(prefferedWidth, prefferedHeight);
> drawable.draw(g2D, prefferedWidth, prefferedHeight);
> g2D.dispose();
> } else {
> template = contentByte.createTemplate(width, height);
> g2D = template.createGraphics(width, height);
> PrintTranscoder transcoder = new PrintTranscoder( );
> if ( null != svgPath )
> {
> transcoder.transcode( new TranscoderInput( svgPath ), null );
> }
> else if ( null != svgData && svgData.length > 0 )
> {
> transcoder.transcode( new TranscoderInput(
> new ByteArrayInputStream( svgData ) ), null );
> }
> PageFormat pg = new PageFormat( );
> Paper p = new Paper( );
> p.setSize( width, height );
> p.setImageableArea( 0, 0, width, height );
> pg.setPaper( p );
> transcoder.print( g2D, pg, 0 );
> g2D.dispose( );
> }
> drawImage( template, x, y, height, width, helpText );
> }
>
> Note that Drawable is my interface that contains only a draw method and
> a method for obtaining the object's preferred size. My JFreeChart chart
> then implements this interface. I know it's not the best solution, but
> it works for me now.
> The summary:
> - I say to BIRT this is an svg image, so it calls my edited transSVG
> method.
> - As image's data I dont set svg data but my serialized JFreeChart
> instead (that's the worst hack).
> - Then I draw my chart directly to the PDF using iText.
|
|
| | |
Goto Forum:
Current Time: Fri Apr 26 14:12:35 GMT 2024
Powered by FUDForum. Page generated in 0.05408 seconds
|