JFree PIE CHART Enhancements - java

I want to draw Pie_chart for small data set has this form.
I used these code
DefaultPieDataset my_pie_chart_data = new DefaultPieDataset();
for(int i =1; i<9; i++) {
row = my_sheet.getRow(0);
cell = row.getCell(i);
chart_label=cell.getStringCellValue();
row = my_sheet.getRow(1);
cell = row.getCell(i);
chart_data=cell.getNumericCellValue();
my_pie_chart_data.setValue(chart_label,chart_data);
}
JFreeChart myPieChart=ChartFactory.createPieChart("PIE",my_pie_chart_data,true,true,false);
int width=640; /* Width of the chart */
int height=480; /* Height of the chart */
float quality=1; /* Quality factor */
ByteArrayOutputStream chart_out = new ByteArrayOutputStream();
ChartUtilities.writeChartAsJPEG(chart_out,quality,myPieChart,width,height);
int my_picture_id = my_workbook.addPicture(chart_out.toByteArray(), Workbook.PICTURE_TYPE_JPEG);
chart_out.close();
XSSFDrawing drawing = my_sheet.createDrawingPatriarch();
ClientAnchor my_anchor = new XSSFClientAnchor();
my_anchor.setCol1(4);
my_anchor.setRow1(5);
XSSFPicture my_picture = drawing.createPicture(my_anchor, my_picture_id);
my_picture.resize();
chart_file_input.close();
}
the resulting chart has these label on it, which is confusing, specially when the values are small because, they all refer to the same section. And I can live with the legend definition below.
Does anybody know how can I delete them ?

Related

How to put the image in the center of a cell of excel using java?

I want to put an image set in the center of a cell of excel, I use XSSFClientAnchor to anchor the picture position, but still not working like in picture 1.
How to set the image in the center of a cell, like in picture 2.
InputStream iStream = new FileInputStream(iList.get(q.getProductID()));
byte[] bytes = IOUtils.toByteArray(iStream);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = new XSSFClientAnchor();
anchor.setCol1(1);
anchor.setRow1(row);
anchor.setCol2(2);
anchor.setRow2(row + 1);
Picture pic = patriarch.createPicture(anchor, pictureIdx);
pic.resize();
Images are not cell contents but hover over the sheet in a separate layer called drawing. They are anchored to the cells. A ClientAnchor provides following settings:
col1 = column index where left edge of picture is anchored on. So left edge of picture is anchored on left column edge of col1.
dx1 = difference in x direction. So left edge of picture is anchored on left column edge of col1 + dx1.
row1 = row index where top edge of picture is anchored on. So top edge of picture is anchored on top row edge of row1.
dy1 = difference in y direction. So top edge of picture is anchored on top row edge of row1 + dy1.
col2 = column index where right edge of picture is anchored on. So right edge of picture is anchored on left column edge of col2.
dx2 = difference in x direction. So right edge of picture is anchored on left column edge of col1 + dx2.
row2 = row index where bottom edge of picture is anchored on. So bottom edge of picture is anchored on top row edge of row2.
dy2 = difference in y direction. So bottom edge of picture is anchored on top row edge of row2 + dy2.
Thus, given a full two-cell-anchor, this determines the position of picture well as it's size.
If size of picture shall be it's native size, then only one-cell-anchor is needed. There col1+dx1 and row1+dy1 determines the position of top left edge of picture. The size is given by the native size of the picture.
If only col1 and row1 is set without dx1 and dy1, then top left edge of picture always is anchored to left edge of col1 and top edge of row1. So if centering over a cell is needed, then dx1 and dy1 needs to be calculated. To calculate dx1 and dy1 one needs to know the width and height of the picture as well as the width and height of the cell. Sounds simple but there are multiple different measurement units used for width and height of the cell and there are big differences between binary BIFF (*.xls) file system and Office Open XML (*.xlsx) file system.
The following code provides putPictureCentered method which puts a picture in sheet's drawing anchored to a cell given by colIdx and rowIdx. If possible, it calculates dx1 and dy1 so that the picture is anchored centered over the cell. It uses pixels as the common measurement unit. It considers differences between binary BIFF (*.xls) file system and Office Open XML (*.xlsx) file system. So it works for Sheet, may it be XSSFSheet or HSSFSheet.
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class CenterImageOverCell {
static void putPictureCentered(Sheet sheet, String picturePath, int pictureType, int colIdx, int rowIdx) throws Exception {
Workbook wb = sheet.getWorkbook();
//load the picture
InputStream inputStream = new FileInputStream(picturePath);
byte[] bytes = IOUtils.toByteArray(inputStream);
int pictureIdx = wb.addPicture(bytes, pictureType);
inputStream.close();
//create an anchor with upper left cell colIdx/rowIdx, only one cell anchor since bottom right depends on resizing
CreationHelper helper = wb.getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(colIdx);
anchor.setRow1(rowIdx);
//create a picture anchored to colIdx and rowIdx
Drawing drawing = sheet.createDrawingPatriarch();
Picture pict = drawing.createPicture(anchor, pictureIdx);
//get the picture width in px
int pictWidthPx = pict.getImageDimension().width;
//get the picture height in px
int pictHeightPx = pict.getImageDimension().height;
//get column width of column in px
float columnWidthPx = sheet.getColumnWidthInPixels(colIdx);
//get the height of row in px
Row row = sheet.getRow(rowIdx);
float rowHeightPt = row.getHeightInPoints();
float rowHeightPx = rowHeightPt * Units.PIXEL_DPI / Units.POINT_DPI;
//is horizontal centering possible?
if (pictWidthPx <= columnWidthPx) {
//calculate the horizontal center position
int horCenterPosPx = Math.round(columnWidthPx/2f - pictWidthPx/2f);
//set the horizontal center position as Dx1 of anchor
if (wb instanceof XSSFWorkbook) {
anchor.setDx1(horCenterPosPx * Units.EMU_PER_PIXEL); //in unit EMU for XSSF
} else if (wb instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
int DEFAULT_COL_WIDTH = 10 * 256;
anchor.setDx1(Math.round(horCenterPosPx * Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75f * DEFAULT_COL_WIDTH / columnWidthPx));
}
} else {
System.out.println("Picture is too width. Horizontal centering is not possible.");
//TODO: Log instead of System.out.println
}
//is vertical centering possible?
if (pictHeightPx <= rowHeightPx) {
//calculate the vertical center position
int vertCenterPosPx = Math.round(rowHeightPx/2f - pictHeightPx/2f);
//set the vertical center position as Dy1 of anchor
if (wb instanceof XSSFWorkbook) {
anchor.setDy1(Math.round(vertCenterPosPx * Units.EMU_PER_PIXEL)); //in unit EMU for XSSF
} else if (wb instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
float DEFAULT_ROW_HEIGHT = 12.75f;
anchor.setDy1(Math.round(vertCenterPosPx * Units.PIXEL_DPI / Units.POINT_DPI * 14.75f * DEFAULT_ROW_HEIGHT / rowHeightPx));
}
} else {
System.out.println("Picture is too height. Vertical centering is not possible.");
//TODO: Log instead of System.out.println
}
//resize the picture to it's native size
pict.resize();
}
public static void main(String[] args) throws Exception {
//Workbook wb = new HSSFWorkbook(); String resultName = "CenterImageTest.xls";
Workbook wb = new XSSFWorkbook(); String resultName = "CenterImageTest.xlsx";
Sheet sheet = wb.createSheet("Sheet1");
int colIdx = 1;
int colWidth = 20; //in default character widths
int rowIdx = 1;
float rowHeight = 100; //in points
//========================prepare sheet
//create cell
Row row = sheet.createRow(rowIdx);
Cell cell = row.createCell(colIdx);
//set column width of colIdx in default character widths
sheet.setColumnWidth(colIdx, colWidth * 256);
//set row height of rowIdx in points
row.setHeightInPoints(rowHeight);
//========================end prepare sheet
//put image centered
String picturePath = "./pict100x100.png"; // small image
//String picturePath = "./pict100x200.png"; // image too height
//String picturePath = "./pict200x100.png"; // image too width
//String picturePath = "./pict200x200.png"; // image too big
putPictureCentered(sheet, picturePath, Workbook.PICTURE_TYPE_PNG, colIdx, rowIdx);
FileOutputStream fileOut = new FileOutputStream("./" + resultName);
wb.write(fileOut);
fileOut.close();
wb.close();
}
}

How to set image size via HSSFWorkbook

I want to insert an image in my excel workbook using Apache Poi but I can't set size of image. I wrote this code but it's not what I want.
InputStream inputStream2=new FileInputStream("C:\\Users\\ftk1187\\Desktop\\tec.png");
byte[] imageBytes2 = IOUtils.toByteArray(inputStream2);
int pictureureIdx2 = wb.addPicture(imageBytes2, Workbook.PICTURE_TYPE_PNG);
inputStream2.close();
CreationHelper helper2 = wb.getCreationHelper();
Drawing drawing2 = sheet.createDrawingPatriarch();
ClientAnchor anchor2 = helper2.createClientAnchor();
anchor2.setDx1(0);
anchor2.setDy1(0);
anchor2.setDx2(100);
anchor2.setDy2(120);
anchor2.setCol1(8);
anchor2.setRow1(1);
Picture pict2 = drawing2.createPicture(anchor2, pictureureIdx2);
pict2.resize(2);
It scaling the image but I want to resize it with centimeters. I looked some forums but I didn't find anything to solve this problem. Also I want to align this picture to middle of cell. What can I try next?
This is not as simple as you might think. Not only that there are many different measurement units to take into account, unfortunately there also are big differences between binary *.xls and Office Open XML *.xlsx file formats.
Best measurement unit to work with here will be pixels. This can be converted to EMU using Units.EMU_PER_PIXEL. So instead of resizing the picture in centimeters, it should be done in pixels. But one can convert centimeter to pixels using following formula:
float pixels = cm / 2.54f * 72f * Units.PIXEL_DPI / Units.POINT_DPI
That is: 1 inch = 2.54 cm, so cm / 2.54 are inches, inches * 72 are points and points * pixel DPI / points DPI are pixels.
If we need working using pixels and want placing the picture horizontal and vertical centered over a cell, of course we also need having the cell width and the row height in pixels. Having this, we can calculate the horizontal and vertical start and end position of the picture over the cell. Then we can set picture's anchor as starting on top left of the cell plus dx1 = horizontal start position and plus dy1 = vertical start position. Also picture's anchor ends on top left of the cell plus dx2 = horizontal end position and plus dy2 = vertical end position.
The following complete example places the picture in size of 3 cm x 1.5 cm horizontal and vertical centered over cell B2 which is 100pt height and 50 default characters width. It works for HSSF as well as for XSSF.
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
class CreateExcelPictureOverCell {
public static void main(String[] args) throws Exception {
Workbook workbook = new HSSFWorkbook(); String filePath = "./Excel.xls";
//Workbook workbook = new XSSFWorkbook(); String filePath = "./Excel.xlsx";
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(1); // row 2
float rowHeightInPoints = 100f;
row.setHeightInPoints(rowHeightInPoints);
float rowHeightInPixels = rowHeightInPoints * Units.PIXEL_DPI / Units.POINT_DPI;
Cell cell = row.createCell(1); // col B
sheet.setColumnWidth(1, 50*256); // 50 default characters width
float colWidthInPixels = sheet.getColumnWidthInPixels(1);
InputStream inputStream = new FileInputStream("./logo.png");
byte[] imageBytes = IOUtils.toByteArray(inputStream);
int pictureureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
inputStream.close();
CreationHelper helper = workbook.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
//set start position of picture's anchor to top left B2
anchor.setRow1(1);
anchor.setCol1(1);
//create picture
Picture pict = drawing.createPicture(anchor, pictureureIdx);
//get picture's original size
int pictOriginalWidthInPixels = pict.getImageDimension().width;
int pictOriginalHeightInPixels = pict.getImageDimension().height;
//set picture's wanted size
float pictWidthInCm = 3f;
float pictWidthInPixels = pictWidthInCm / 2.54f * 72f * Units.PIXEL_DPI / Units.POINT_DPI;
//want scaling in aspect ratio?
//float scale = pictWidthInPixels / pictOriginalWidthInPixels;
//float pictHeightInPixels = pictOriginalHeightInPixels * scale;
//want explicit set height too?
float pictHeightInCm = 1.5f;
float pictHeightInPixels = pictHeightInCm / 2.54f * 72f * Units.PIXEL_DPI / Units.POINT_DPI;
//calculate the horizontal center position
int horCenterPosInPixels = Math.round(colWidthInPixels/2f - pictWidthInPixels/2f);
//set the horizontal center position as Dx1 of anchor
if (workbook instanceof XSSFWorkbook) {
anchor.setDx1(horCenterPosInPixels * Units.EMU_PER_PIXEL); //in unit EMU for XSSF
} else if (workbook instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
int DEFAULT_COL_WIDTH = 10 * 256;
anchor.setDx1(Math.round(horCenterPosInPixels * Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75f * DEFAULT_COL_WIDTH / colWidthInPixels));
}
//calculate the vertical center position
int vertCenterPosInPixels = Math.round(rowHeightInPixels/2f - pictHeightInPixels/2f);
//set the vertical center position as Dy1 of anchor
if (workbook instanceof XSSFWorkbook) {
anchor.setDy1(Math.round(vertCenterPosInPixels * Units.EMU_PER_PIXEL)); //in unit EMU for XSSF
} else if (workbook instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
float DEFAULT_ROW_HEIGHT = 12.75f;
anchor.setDy1(Math.round(vertCenterPosInPixels * Units.PIXEL_DPI / Units.POINT_DPI * 14.75f * DEFAULT_ROW_HEIGHT / rowHeightInPixels));
}
//set end position of picture's anchor to top left B2
anchor.setRow2(1);
anchor.setCol2(1);
//calculate the horizontal end position of picture
int horCenterEndPosInPixels = Math.round(horCenterPosInPixels + pictWidthInPixels);
//set the horizontal end position as Dx2 of anchor
if (workbook instanceof XSSFWorkbook) {
anchor.setDx2(horCenterEndPosInPixels * Units.EMU_PER_PIXEL); //in unit EMU for XSSF
} else if (workbook instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
int DEFAULT_COL_WIDTH = 10 * 256;
anchor.setDx2(Math.round(horCenterEndPosInPixels * Units.DEFAULT_CHARACTER_WIDTH / 256f * 14.75f * DEFAULT_COL_WIDTH / colWidthInPixels));
}
//calculate the vertical end position of picture
int vertCenterEndPosInPixels = Math.round(vertCenterPosInPixels + pictHeightInPixels);
//set the vertical end position as Dy2 of anchor
if (workbook instanceof XSSFWorkbook) {
anchor.setDy2(Math.round(vertCenterEndPosInPixels * Units.EMU_PER_PIXEL)); //in unit EMU for XSSF
} else if (workbook instanceof HSSFWorkbook) {
//see https://stackoverflow.com/questions/48567203/apache-poi-xssfclientanchor-not-positioning-picture-with-respect-to-dx1-dy1-dx/48607117#48607117 for HSSF
float DEFAULT_ROW_HEIGHT = 12.75f;
anchor.setDy2(Math.round(vertCenterEndPosInPixels * Units.PIXEL_DPI / Units.POINT_DPI * 14.75f * DEFAULT_ROW_HEIGHT / rowHeightInPixels));
}
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
try {
Resource resource = new ClassPathResource(IMAGE);
// FileInputStream obtains input bytes from the image file
java.io.InputStream inputStream = resource.getInputStream();
// Get the contents of an InputStream as a byte[].
byte[] bytes = IOUtils.toByteArray(inputStream);
// Adds a picture to the workbook
int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
// close the input stream
inputStream.close();
// Returns an object that handles instantiating concrete classes
CreationHelper helper = workbook.getCreationHelper();
// Creates the top-level drawing patriarch.
Drawing drawing = sheet.createDrawingPatriarch();
// Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
// set top-left corner for the image
anchor.setCol1(0);
anchor.setDx1(100);
// Creates a picture
Picture pict = drawing.createPicture(anchor, pictureIdx);
// Reset the image to the original size
pict.resize();
} catch (Exception e) {
// TODO: handle exception
}

Blank fields in Libgdx's table

I have another problem with tables in Libgdx. I want to create a game board using it and give to user a possibility to add / remove elements from that board ( table ). So first of all I would like to know how to initialize that table so that it already has fields but invisible fields ( so that it's possible to get position of that field and put there new element ). So those are my 2 first questions :
How to create those invisible fields ( all fields have fixed static size ) ?
How to get position and change element ( actor ) in that field?
Hope someone can help me.
You can create those by adding a cell to a table and set the size of the cell.
You can then add a invisible button to that cell and if the button is clicked you can remove it and add a new element.
Here some example code:
// uiskin from libgdx tests
skin = new Skin(Gdx.files.internal("uiskin.json"));
table = new Table();
// invisible button style
final ButtonStyle bStyle = new ButtonStyle();
int colNum = 10, rowNum = 10;
for (int row = 0; row < rowNum; row++)
{
for (int col = 0; col < colNum; col++)
{
final Button l = new Button(bStyle);
l.addListener(new ClickListener()
{
#Override
public void clicked(InputEvent event, float x, float y)
{
Cell<Button> cell = table.getCell(l);
cell.clearActor();
cell.setActor(new Label("test", skin));
}
});
table.add(l).size(100, 100);
}
table.row();
}
stage = new Stage();
table.setFillParent(true);
stage.addActor(table);
Gdx.input.setInputProcessor(stage);
The skin files can be downloaded here: https://github.com/libgdx/libgdx/tree/master/tests/gdx-tests-android/assets/data
You need the uiskin.json, uiskin.atlas and uiskin.png file.

Snapshot entire TableView

I am currently trying to create an image from a TableView using snapshot, and the snapshot is only grabbing the tableview that is visible on the screen. I've tried messing with the SnapshotPreferencesviewport, but that didn't help. Any suggestions or workarounds would be appreciated.
EDIT: I have now also tried creating a new pane of the same width and height of the TableView, adding the TableView, and taking a snapshot of that, but it ends up blank. I've continued to play around with this. Creating a new pane and adding it to a scene gives me all the columns of the TableView, but not all the rows.
Code to take the snapshot is below.
WritableImage image = null;
//Get the node
TableView<ObservableList<ObjectProperty<Item>>>pattern = mainApp.getPVController().getPattern();
//Create rectangle to define viewport
Rectangle2D rect = new Rectangle2D(0, 0, pattern.getWidth(), pattern.getHeight());
//Define snapshot parameters
SnapshotParameters params = new SnapshotParameters();
params.setViewport(rect);
//Take the snapshot
image = pattern.snapshot(params, image);
Ok, so I figured out a workaround. I used the underlying data of the TableView and made a GridPane that represented the underlying data, which worked well. My data was represented by color, so that is what you will see below. You could certainly do this with other data types.
Now I am having trouble with the gridlines that I put in varying their shade and width- but that's another question. Code to create the GridPane is below.
GridPane gPane = new GridPane();
gPane.setSnapToPixel(true);
gPane.setStyle("-fx-background-color: DARKGREY; -fx-padding: 1;"
+"-fx-hgap: 1; -fx-vgap: 1;");
for(int i=0; i<mainApp.getItemList().size(); i++){ // rows
for(int j=0; j<mainApp.getItemList().get(0).size(); j++){ //columns
Color color = mainApp.getItemList().get(i).get(j).getValue().getDisplayColor();
int r = (int) (color.getRed() * 255);
int g = (int) (color.getGreen() * 255);
int b = (int) (color.getBlue() * 255);
Rectangle rect = new Rectangle(5,5);
rect.setStyle("-fx-fill: rgb(" + r + "," + g + "," + b + ");");
gPane.add(rect, j, i);
}
}
Scene scene = new Scene(gPane);
WritableImage image = gPane.snapshot(new SnapshotParameters(), null);

Image histogram generated by JFreeChart

I want to display histogram of image color channels.
At first my reading of pixels looks like:
for(int i=0; i<width; i++)
for(int j=0; j<height; j++) {
data=writeableRaster.getDataElements(i, j, null);
red=colorModel.getRed(data);
green=colorModel.getGreen(data);
blue=colorModel.getBlue(data);
rgb=(red+green+blue)/3;
++redL[red];
++greenL[green];
++blueL[blue];
++rgbL[rgb];
}
}
I also have additional method for creating chart with given channel colors table:
int number = channelHistogram.length;
HistogramDataset dataset = new HistogramDataset();
dataset.setType(HistogramType.RELATIVE_FREQUENCY);
dataset.addSeries("Hist",channelHistogram,number);
String plotTitle = "Hist";
String xaxis = "number";
String yaxis = "value";
PlotOrientation orientation = PlotOrientation.VERTICAL;
boolean show = false;
boolean toolTips = false;
boolean urls = false;
JFreeChart chart = ChartFactory.createHistogram( plotTitle, xaxis, yaxis,
dataset, orientation, show, toolTips, urls);
But chart is wrong displayed. It means at Y axis there are "low" values (from ~ 0 - 0.09) and at X axis there aren't values from scope 0 - 255.
Any help?
dataset.setType(HistogramType.RELATIVE_FREQUENCY);
Can you try setting different options here and see if it helps? Also if you can show what channelHistogram field contains that may be helpful to debug.

Categories