PNG Image and Resize

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
VK

PNG Image and Resize

Post by VK » Fri Jun 17, 2005 5:39 pm

Hi,

We tried improving the resolution of JFree image using the PNG Image encoder code posted on JFree. But canvas size is too big when I incrase the resolution to 300 dpi.

public BufferedImage getHiResChartImage(JFreeChart chart, double resolution, double width, double height, int imageType)
{
int screenResolution = Toolkit.getDefaultToolkit().getScreenResolution();
double scaleRatio = resolution / screenResolution;
int rasterWidth = (int) (width * scaleRatio);
int rasterHeight = (int) (height * scaleRatio);
log("rasterWidth : "+rasterWidth);
log("rasterHeight : "+rasterHeight);
log("scaleRatio : "+scaleRatio);
//BufferedImage image = new BufferedImage(rasterWidth, rasterHeight, BufferedImage.TYPE_INT_RGB);
BufferedImage image = chart.createBufferedImage((int)width,(int)height);
Graphics2D g2 = image.createGraphics();
g2.transform(AffineTransform.getScaleInstance(scaleRatio, scaleRatio));
chart.draw(g2, new Rectangle2D.Double(0, 0, width,height), null);
g2.dispose();
return image;
}



public String saveHiResImage(JFreeChart chart, double width, double height, double resolution, int imageType) {

String fileName = "JFreeImage_" + getUniqueTime();
String extension = ".png";
String file = "D:\\Vinayak\\RMD\\Chart_Evaluation\\images\\HiRes\\" + fileName + "_" + width + "x" + height + "x_Res-" + resolution + "dpi" + extension;

try
{

BufferedImage rendImage = getHiResChartImage(chart,resolution, width, height, imageType);
PNGMetadata png = new PNGMetadata();
int resX = (int)Math.ceil(resolution * 0.0254f);
png.pHYs_pixelsPerUnitXAxis = resX;
png.pHYs_pixelsPerUnitYAxis = resX;
png.pHYs_unitSpecifier = 1;
png.pHYs_present = true;

IIOImage iioImage = new IIOImage(rendImage, null, png);

//..Write generated image to a file
//.. Save as PNG
File f = new File(file);
ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("png").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(f);
writer.setOutput(ios);

//.. Set the compression quality and other header information
ImageWriteParam iwparam = new ImageWriteParam()
{
public int getProgressiveMode()
{
return MODE_COPY_FROM_METADATA;
}
};
writer.write(png, iioImage, iwparam);
writer.write(iioImage);
writer.dispose();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return file;
}


If you comment the following line then size is proper but then again we do not get good resolution.

g2.transform(AffineTransform.getScaleInstance(scaleRatio, scaleRatio));

Please advise

Tzaphkiel
Posts: 44
Joined: Tue May 13, 2003 1:37 pm
Location: Belgium

Post by Tzaphkiel » Mon Jun 20, 2005 8:18 am

Hi,

By "good resolution" you mean the resolution of the "file" the image is stored in? i.e.: the image file resolution?

I'll re-post my actual working code on this topic in a while...

I think you've missed a step that created a (very) big image (in memory) of the JFreeChart, and stores it in the file using the header to set the correct resolution... thus the ratio (resolution/image size - dpi) is correct in the file...

See the following post (in a while - since I don't have direct access to internet) and it should make sense !

Regards
Tzaphkiel
Image

Tzaphkiel
Posts: 44
Joined: Tue May 13, 2003 1:37 pm
Location: Belgium

Post by Tzaphkiel » Mon Jun 20, 2005 9:19 am

Here is the code:

Code: Select all

	/**
	 * Method encodeAndWritePreviewImage.
	 * 
	 * @param chart
	 *                the JFreeChart instanciation to get the graphic from.
	 * @param filePath
	 *                the wanted file path (including the file name and extension).
	 * @param _chartParams
	 *                the name is explicit.
	 * @param overwrite
	 *                if the files should be overwritten or left as is if they already
	 *                exist.
	 * @return the fileName that was created
	 */
	public static final String encodeAndWritePreviewImage(Chart chart, String filePath, ChartParameter _chartParams,
			boolean overwrite, boolean simpleFileNames)
	{
		File f = null;
		ImageOutputStream ios = null;

		// mm => cm
		double width = _chartParams.getWidth(); //mm
		double outputWidth = width / 10.0f; //cm

		// mm => cm
		double height = _chartParams.getHeight(); //mm
		double outputHeight = height / 10.0f; //cm

		float resolution = _chartParams.getResolution();//dpi

		String fileName = filePath.substring(0, filePath.lastIndexOf("."));
		String extension = filePath.substring(filePath.lastIndexOf(".") + 1);
		String file;

		DecimalFormat nf = new DecimalFormat("####");
		if (!simpleFileNames)
			file = fileName + "-" + nf.format(width) + "x" + nf.format(height) + "x" + nf.format(resolution) + "dpi." + extension;
		else
			file = fileName + "." + extension;

		try
		{
			RenderedImage rendImage = chart.getHiResChartImage(resolution, outputWidth, outputHeight);
			IIOImage iioImage = null;
			if (extension.equals("png"))
			{
				PNGMetadata png = new PNGMetadata();
				int resX = (int) Math.ceil(resolution / 0.0254f);
				png.pHYs_pixelsPerUnitXAxis = resX;
				png.pHYs_pixelsPerUnitYAxis = resX;
				png.pHYs_unitSpecifier = 1;
				png.pHYs_present = true;
				iioImage = new IIOImage(rendImage, null, png);
			}
			else if (extension.equals("jpg"))
			{
				//				DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
				//				DocumentBuilder parser = null;
				//				try
				//				{
				//					parser = fact.newDocumentBuilder();
				//				}
				//				catch (ParserConfigurationException e1)
				//				{
				//					e1.printStackTrace();
				//				}
				//				Document doc = parser.newDocument();
				//				Element dimensionElem = doc.createElement("Dimension");
				//				Element horizontalPixelSize =
				// doc.createElement("HorizontalPixelSize");
				//				int resX = (int) Math.ceil(resolution / 0.0254f);
				//				horizontalPixelSize.setNodeValue("" + Math.round(1 / (resX * resX *
				// 10)));
				//				dimensionElem.appendChild(horizontalPixelSize);
				//				
				//				Element verticalPixelSize = doc.createElement("VerticalPixelSize");
				//				verticalPixelSize.setNodeValue("" + Math.round(1 / (resX * resX *
				// 10)));
				//				dimensionElem.appendChild(verticalPixelSize);
				//				
				//				jpegMetadata = new JPEGMetadata();
				//				jpegMetadata.mergeTree(IIOMetadataFormatImpl.standardMetadataFormatName,
				// dimensionElem);
				iioImage = new IIOImage(rendImage, null, null);
			}

			f = new File(file);
			if (!(!overwrite && f.exists()))
			{
				ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName(extension).next();
				ios = ImageIO.createImageOutputStream(f);
				ImageWriteParam jpegWriteParam = null;
				if (extension.equals("jpg"))
				{
					jpegWriteParam = writer.getDefaultWriteParam();
					jpegWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
					jpegWriteParam.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
					jpegWriteParam.unsetCompression();
					//					jpegWriteParam.setCompressionQuality(1.0f);
					//					jpegWriteParam.setCompressionType(null);
				}
				writer.setOutput(ios);

				if (extension.equals("jpg"))
					writer.write(null, iioImage, jpegWriteParam);
				else
					writer.write(iioImage);

				writer.dispose();
			}
			else
			{
				Logger.getLogger("be.nbb.batchpubgraph.jobsbatchprog").warning(
						f.getAbsolutePath() + " already exists and overwrite mode not set (-o) !");
			}
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		finally
		{
			if (ios != null)
				try
				{
					ios.close();
				}
				catch (IOException e1)
				{
					e1.printStackTrace();
				}
		}
		return file;
	}



	/**
	 * Method getHiResChartImage.
	 * 
	 * @param resolution
	 * @param width
	 * @param height
	 * @return
	 */
	public BufferedImage getHiResChartImage(double resolution, double width, double height)
	{
		width = width / CM_TO_INCH * _screenResolution;
		height = height / CM_TO_INCH * _screenResolution;
		double scaleRatio = resolution / _screenResolution;
		int rasterWidth = (int) (width * scaleRatio);
		int rasterHeight = (int) (height * scaleRatio);
		BufferedImage image = new BufferedImage(rasterWidth, rasterHeight, BufferedImage.TYPE_INT_RGB);
		//		BufferedImage image = _chart.createBufferedImage(rasterWidth,
		// rasterHeight, width, height, null);
		Graphics2D g2 = image.createGraphics();
		g2.transform(AffineTransform.getScaleInstance(scaleRatio, scaleRatio));
		_chart.draw(g2, new Rectangle2D.Double(0, 0, width, height), null);
		g2.dispose();
		return image;
	}
Like said in other parts of the forum, the screenResotion is the one of the machine running the code (have to get it using the toolkit) !

Hope this helps

Regards
Tzaphkiel
Image

Locked