Generate a png of a chart in Java [duplicate] - java

How does one programmatically render image files from JFreeChart . I have code for ChartPanel: is it possible to render directly to an image - without creating AWT/GUI components?
val chart = .. // Imagine code to generate chart data here..
val panel = new ChartPanel(chart)
panel.renderToImage() // replace this with logic to save image file

Use one of the ChartUtilities methods, such as writeChartAsJPEG() or writeChartAsPNG(), that can write to a java.io.OutputStream; or saveChartAsJPEG() or saveChartAsPNG(), that can write to a java.io.File. Some examples are seen here and here. For example,
ChartUtilities.saveChartAsPNG(new File("chart.png"), chart, width, height);
You'll also want to look into headless mode, mentioned here.

Related

JavaFX .setStyle(...) isn't not working when `-fx-background-image` changes

What i want to achieve:
I am using a FileChooser and the user selects an appropriate .jpg image file . Then i am copying that image , renaming it background.jpg to a known folder and trying to set it as the background image of the application using .setStyle(...); There is not problem of copying the image [ i am checking it]
The Problem that occurs:
I have a Stage with a BorderPane . The BorderPane has an background Image , i do that using
borderPane.setStyle("-fx-background-image:url('filepath')");
!It works well the first time!
->Then i am deleting that file [background.jpg] and i am replacing it with another file named also [background.jpg] . The background image of the BorderPane isn't changing ....
I have tried also resetting the same style using again :
borderPane.setStyle("-fx-background-image:url('filepath')");
Finally when i am changing the filename , for example to [background-12.jpg] and reseting the style using the above it changes the background image.
Which exactly is the problem ? I mean i am sure that the background.jpg has been created , i am checking it and also when i am changing the name to something other again and again it works .
Is the Java CSS Parser lazy to parse the new style which is the same but has other -fx-background-image resource ?
As for the File path i am sure it is well , i am using the code below :
//Maou is the File URL in appropriate format for CSS
String maou = file.getAbsoluteFile().toURI().toString()
//Here i add the appropriate file separator, if not JavaFX will report error
maou = maou.replaceAll("\\Q\\\\E", "//");
//Print maou
System.out.println("Maou=\n" + maou);
Solution :
I found as best solution using James_D answer , a little bit modified so it covers the whole window:
BackgroundImage bgImg = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT,
new BackgroundSize(window.getWidth(), window.getHeight(), true, true, true, true));
Rather than using an inline style, I would recommend setting the background via the background property directly:
Image img = new Image(file.getAbsoluteFile().toURI().toString());
BackgroundImage bgImg = new BackgroundImage(img,
BackgroundRepeat.NO_REPEAT,
BackgroundRepeat.NO_REPEAT,
BackgroundPosition.DEFAULT,
BackgroundSize.DEFAULT);
borderPane.setBackground(new Background(bgImg));
The Background class provides Java API programmatic access to all the same properties that can be set by CSS.
While I don't know exactly what's going on, presumably it's some form of caching which JavaFX is doing to try to be "helpful". I may look into the source code later.
To be honest, though, setting a background via CSS feels like the wrong approach to me. I always avoid setting any styles explicitly, like:
borderPane.setStyle("something");
and prefer to add and remove style classes:
borderPane.getStyleClass().add("foo");
borderPane.getStyleClass().remove("foo");
I don't think this is possible in your situation, so I would instead use a StackPane
to layer your content over an ImageView.
ImageView img = new ImageView(new Image(new URL("path")));
StackPane stack = new StackPane();
stack.getChildren.addAll(img, /*overlaid content*/);

Server-side/ non-interactive rendering of Charts to image files from JFreeChart

How does one programmatically render image files from JFreeChart . I have code for ChartPanel: is it possible to render directly to an image - without creating AWT/GUI components?
val chart = .. // Imagine code to generate chart data here..
val panel = new ChartPanel(chart)
panel.renderToImage() // replace this with logic to save image file
Use one of the ChartUtilities methods, such as writeChartAsJPEG() or writeChartAsPNG(), that can write to a java.io.OutputStream; or saveChartAsJPEG() or saveChartAsPNG(), that can write to a java.io.File. Some examples are seen here and here. For example,
ChartUtilities.saveChartAsPNG(new File("chart.png"), chart, width, height);
You'll also want to look into headless mode, mentioned here.

JFreeChart Smudging of lines in Candlestick Chart

This has reference to JFreeChart rendering of candlestick charts. Below is the code fragment that generates a candle stick chart with JFreeChart.
This code has been tested and has been working for a long time. However, the version of JFreeChart was changed from 1.0.17 to 1.0.19 and the candlestick chart generated with 1.0.19 is showing smudging of the candle objects/lines. When I changed the library back to 1.0.17, the candlestick objects/lines once again becomes clear.
The images with both the libraries are provided below.
I have tried to find the cause of this and have been unsuccessful as yet. Now, the question is, since the code is tested and possibly does not have any error (at least what I can figure or am I missing something?), is the issue with the library? Have anyone faced this problem and has an work around
I shall be rather grateful, if someone has found the reason/solution to this and shared the same.
Please use MS Paint to view the images.
try{
chart=ChartFactory.createCandlestickChart("Candlestick Chart", "Date", "EOD Closing Price", (OHLCDataset)dataset, true);
plot=(XYPlot)chart.getPlot();
CandlestickRenderer renderer=new Chart_CandlestickRenderer();//(CandlestickRenderer)plot.getRenderer();
renderer.setSeriesPaint(0, Color.BLACK);
renderer.setUpPaint(Color.WHITE);
renderer.setDownPaint(Color.BLACK);
//HighLowItemLabelGenerator candleTooltipGenerator=new HighLowItemLabelGenerator(new SimpleDateFormat("dd-MMM-yyyy"), new DecimalFormat());
XYToolTipGenerator candleTooltipGenerator=Chart_TooltipProvider.getOHLCTooltipGenerator();
renderer.setBaseToolTipGenerator(candleTooltipGenerator);
plot.setRenderer(0,renderer);
//Organize the data to draw Fibbonacci retracements with highs and lows
DefaultOHLCDataset ohlcDataset=(DefaultOHLCDataset)dataset;
int dataCount=ohlcDataset.getItemCount(0);
data=new double[dataCount*2];//for each data item we shall get 2 values, high and low
for(int i=0;i<dataCount;i++){
//for each i 2 data values need to be put into the array and adjust the index accordingly
data[i*2]=ohlcDataset.getHighValue(0, i);
data[i*2+1]=ohlcDataset.getLowValue(0, i);
}//for closing
//If there is only the candlestick to be drawn, return, as the job has been done, draw the Fibonnaci and return
if(indicators.length==1){
this.drawFibonnaciRetracement(data, plot);
retVal=true;
return retVal;
}//if closing
}catch(Exception e){e.printStackTrace();return retVal;}
Try setting setAntiAlias of the JFreeChart to false.
JFreeChart chart = ChartFactory.createCandlestickChart(...);
chart.setAntiAlias(false);

How to combine multiple charts created using JFreeChart API?

My requirement is need to display 2 barchart and 3 trendchart in single page. For that, i have used JFreeChart API and sending the image in bytearray format through response. Its working fine for single image. How do i merge all 5 charts and send that through response?. Please help me.
Sample Code:
chartTypeCode="1";
chartTypeDesc="Order Line Status Bar Chart";
chart = createChart(defaultFromDate,defaultToDate,chartTypeCode);
chartImage[0] = chart.createBufferedImage(600, 400);
chartTypeCode="2";
chartTypeDesc="Order Sent To OMS Trend Chart";
chart = createTrendChart(defaultFromDate,defaultToDate,chartTypeCode);
chartImage[1] = chart.createBufferedImage(600, 400);
chartTypeCode="3";
chartTypeDesc="Shipment Trend Chart";
chart = createTrendChart(defaultFromDate,defaultToDate,chartTypeCode);
chartImage[2] = chart.createBufferedImage(600, 400);
chartTypeCode="4";
chartTypeDesc="Return Trend Chart";
chart = createTrendChart(defaultFromDate,defaultToDate,chartTypeCode);
chartImage[3] = chart.createBufferedImage(600, 400);
chartTypeCode="5";
chartTypeDesc="PSP Email Bar Chart";
chart = createChart(defaultFromDate,defaultToDate,chartTypeCode);
chartImage[4] = chart.createBufferedImage(600, 400);
I don't know that you can send many charts as they are individual images.
You should consider instead saving each chart to your server using servlet utilities and then using JFreeChart's servlet to query each image. This will allow you to use standard image tags which means you can use text html with maps (for tooltips) and css.
See my answer to a similar question for more info.

How to customize series fill in area chart via BIRT chart API?

I am trying to create a gradient fill for a series in an area chart that I am building through the BIRT chart API, but the book "Integrating and Extending BIRT" and the Interwebs seem curiously silent about how to get it to work. It seems no matter what I do, I always get a flat color from the default palette. I've tried using SeriesDefinition.getSeriesPalette().update(Gradient) and even creating my own Palette with the gradient fill in it and setting that on the SeriesDefinition, but to no avail. I've also noticed that if I do not perform a shift() on the Palette, even if it's shift(0), which the Javadocs claim will do nothing, I get NullPointerException when I try to generate the chart:
Caused by: java.lang.NullPointerException
at org.eclipse.birt.chart.render.Area.renderDataPoints(Area.java:521)
at org.eclipse.birt.chart.render.Line.renderSeries(Line.java:570)
at org.eclipse.birt.chart.render.AxesRenderer.renderPlot(AxesRenderer.java:2181)
at org.eclipse.birt.chart.render.AxesRenderer.render(AxesRenderer.java:314)
at org.eclipse.birt.chart.factory.Generator.render(Generator.java:1368)
... 108 more
Here's the latest (non-working) code that I've tried:
Gradient gradient = FillUtil.createDefaultGradient(BirtReportBuilder.COLOR_WHITE);
gradient.setStartColor(ColorDefinitionImpl.WHITE());
gradient.setEndColor(ColorDefinitionImpl.create(76, 116, 131));
gradient.setDirection(90);
SeriesDefinition sdY = SeriesDefinitionImpl.create();
sdY.getQuery().setDefinition("\"Quantity\"");
Palette pal = PaletteImpl.create(gradient);
pal.shift(0);
sdY.setSeriesPalette(pal);
sdY.getSeries().add(as1);
yAxisPrimary.getSeriesDefinitions().add(sdY);
So what's the magic incantation to get the BIRT charting API to use my Gradient as the area fill?
This code works for me, I get a ugly coloured serie...
sdY.getSeriesPalette().update(GradientImpl.create(ColorDefinitionImpl.create(255,255,255), ColorDefinitionImpl.create(200,0,0,150), 90, false));
Hope it will help you ;p

Categories