【问题标题】:How to resize a JFreeChart before encoding as PNG如何在编码为 PNG 之前调整 JFreeChart 的大小
【发布时间】:2017-04-15 04:50:20
【问题描述】:

我正在尝试使用以下代码生成图表并通过休息响应呈现。

应用类

@SpringBootApplication
@EnableWebMvc
@EnableWebSecurity
public class JChartPoc  extends WebSecurityConfigurerAdapter{
public static void main(String[] args) {

    SpringApplication.run(JChartPoc.class, args);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/**").permitAll()
            .and()
            .csrf().disable();
 }
}

图表在尺寸为 500x500 的情况下渲染得非常好,但我有一个限制,将图像渲染为 352 x 90。

当指定这些维度时,图表会被截断。

我已经在

中生成了一个带有以下代码的折线图

控制器类。

@RestController
public class LineChartController {

@RequestMapping(value = "chartsPNG", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<byte[]> getPNGChart(@RequestHeader HttpHeaders headers)
        throws Exception {
    List<String> acceptLanguageList = headers
            .get(HttpHeaders.ACCEPT_LANGUAGE);
    String acceptLanguage = acceptLanguageList.get(0);
    if (acceptLanguage.equalsIgnoreCase("en-us")) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ChartUtilities.writeBufferedImageAsPNG(baos, createLineChart().createBufferedImage(380, 90));
        return new ResponseEntity<byte[]>(baos.toByteArray(), HttpStatus.OK);
    }
    return new ResponseEntity<byte[]>("Language Not Supported".getBytes(),
            HttpStatus.I_AM_A_TEAPOT);
}

private JFreeChart createLineChart() {
    DefaultCategoryDataset lineDataSet = new DefaultCategoryDataset();
    lineDataSet.setValue(122, "weekly", "3 Weeks Ago");
    lineDataSet.setValue(200, "weekly", "2 Weeks Ago");
    lineDataSet.setValue(246, "weekly", "1 Week Ago");
    lineDataSet.setValue(348, "weekly", "This Week");

    JFreeChart lineChart = ChartFactory.createLineChart(null, null, null,lineDataSet);
    modifyChart(lineChart);
    return lineChart;
}

protected void modifyChart(JFreeChart chart) {
    // plot manipulations
    CategoryPlot categoryPlotModifier = chart.getCategoryPlot();
    categoryPlotModifier.getRangeAxis().setTickLabelsVisible(false);
    categoryPlotModifier.setOutlineVisible(false);
    categoryPlotModifier.getRangeAxis().setVisible(false);
    categoryPlotModifier.getDomainAxis().setTickMarkInsideLength(10);
    categoryPlotModifier.getDomainAxis().setCategoryLabelPositionOffset(6);
    categoryPlotModifier.getDomainAxis().setLabelFont(
            new Font("SansSerif", Font.PLAIN, 100));
    categoryPlotModifier.setAxisOffset(new RectangleInsets());
    // categoryPlotModifier.getRangeAxis().resizeRange(500.);
    // change fonts on charts
    categoryPlotModifier.setBackgroundPaint(Color.WHITE);
    LineAndShapeRenderer renderer = (LineAndShapeRenderer) categoryPlotModifier
            .getRenderer();
    renderer.setBaseShape(new Polygon(), true);
    renderer.setBaseFillPaint(Color.WHITE, true);
    renderer.setBaseShapesVisible(true);
    renderer.setDrawOutlines(true);
    renderer.setUseFillPaint(true);
    // renderer.setSeriesStroke(0, new BasicStroke(1), true);
    CategoryItemLabelGenerator labelGenerator = new StandardCategoryItemLabelGenerator(
            "{2}", new DecimalFormat("0.00"));
    renderer.setBaseItemLabelGenerator(labelGenerator);
    renderer.setBaseItemLabelsVisible(true, true);
    // renderer.setBasePaint(Color.GREEN, true);
    // why not baseColor and why can't we change the color of individual
    // series
    renderer.setSeriesPaint(0, ChartColor.VERY_DARK_MAGENTA, true);
    // logger.info(Boolean.toString(renderer.getBaseShapesVisible()));
    chart.removeLegend();

 }
}

控制器中的这一行控制用于渲染的尺寸

ChartUtilities.writeBufferedImageAsPNG(baos,createLineChart().createBufferedImage(380, 90));

有没有办法调整图表的大小以呈现为 352 x 90 的 PNG 图像,该图像不会被弄脏但可以正确调整大小?

【问题讨论】:

  • 九十像素不算多;请编辑您的问题以包含一个 minimal reproducible example 来展示您描述的问题; screenshots 和/或预期结果的图表可能会使问题更清晰。
  • @trashgod 我已经用最少的代码更新了问题以重现错误。
  • 你可能会在范围轴上修改setUpperMargin(),提到here
  • 非常感谢@trashgod!这为我解决了问题。我将添加工作产品作为解决方案以供参考。也许它会帮助别人。

标签: java image png jfreechart image-resizing


【解决方案1】:

@trashgod 建议 setUpperMargin() 后的解决方案。我确信有一种编程方式来计算 setUpperMargin 函数所需的值,如果我实现它,我会更新这个答案。

@RestController
public class LineChartController {

    @RequestMapping(value = "chartsPNG", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<byte[]> getPNGChart(@RequestHeader HttpHeaders headers)
            throws Exception {
        List<String> acceptLanguageList = headers
                .get(HttpHeaders.ACCEPT_LANGUAGE);
        String acceptLanguage = acceptLanguageList.get(0);
        if (acceptLanguage.equalsIgnoreCase("en-us")) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ChartUtilities.writeBufferedImageAsPNG(baos, createLineChart().createBufferedImage(352, 90));
            return new ResponseEntity<byte[]>(baos.toByteArray(), HttpStatus.OK);
        }
        return new ResponseEntity<byte[]>("Language Not Supported".getBytes(),
                HttpStatus.I_AM_A_TEAPOT);
    }

    private JFreeChart createLineChart() {
        DefaultCategoryDataset lineDataSet = new DefaultCategoryDataset();
        lineDataSet.setValue(122, "weekly", "3 Weeks Ago");
        lineDataSet.setValue(200, "weekly", "2 Weeks Ago");
        lineDataSet.setValue(246, "weekly", "1 Week Ago");
        lineDataSet.setValue(348, "weekly", "This Week");

        JFreeChart lineChart = ChartFactory.createLineChart(null, null, null,lineDataSet);
        modifyChart(lineChart);
        return lineChart;
    }

    protected void modifyChart(JFreeChart chart) {
        Color lineChartColor = new Color(40, 54, 67);
        // plot manipulations
        CategoryPlot categoryPlotModifier = chart.getCategoryPlot();
        categoryPlotModifier.setOutlineVisible(false);
        categoryPlotModifier.setBackgroundPaint(Color.WHITE);

        //Axis modifications
        categoryPlotModifier.getRangeAxis().setVisible(false);
        categoryPlotModifier.getDomainAxis().setTickMarkInsideLength(10);
        categoryPlotModifier.getDomainAxis().setLabelFont(new Font("SansSerif", Font.PLAIN, 1));    
        //Needed to avoid truncation of plot and squeeze of category label name during resized rendering (352X90)
        categoryPlotModifier.getRangeAxis().setUpperMargin(.5);
        categoryPlotModifier.getDomainAxis().setCategoryMargin(.02);

//      Actual data point manipulations
        LineAndShapeRenderer renderer = (LineAndShapeRenderer) categoryPlotModifier.getRenderer();
        renderer.setSeriesShape(0,new Ellipse2D.Double(-3, -3, 6, 6), true);
        renderer.setBaseFillPaint(lineChartColor, true);
        renderer.setBaseShapesVisible(true);
        renderer.setDrawOutlines(true);
        renderer.setUseFillPaint(true);
        CategoryItemLabelGenerator labelGenerator = new StandardCategoryItemLabelGenerator("{2}", new DecimalFormat("0.00"));
        renderer.setBaseItemLabelGenerator(labelGenerator);
        renderer.setBaseItemLabelsVisible(true, true);
         /*renderer.setBasePaint(Color.GREEN, true);
        // why doesn't setBasePaint change the color of all shapes and lines 
         * in data points and why can't we change the color of individual series
         */
        renderer.setSeriesPaint(0, lineChartColor, true);
        // logger.info(Boolean.toString(renderer.getBaseShapesVisible()));
        chart.removeLegend();

    }
}

【讨论】:

    猜你喜欢
    • 2019-07-03
    • 1970-01-01
    • 2011-10-20
    • 2016-06-07
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多