what I am trying to do is color in a certain section, is there sort of a tool that will fill in a section/region? Sort of like the Microsoft Paint bucket. Also, is there a way I can resize all objects in my JComponent to be smaller without having to go and change every single coordinate? Like, if I want the image to be twice as small, is there a way to make all lines and arcs and objects smaller with a simple line to them all, instead of manipulating all of the coordinates?
import java.awt.*;
import java.awt.geom.Line2D.Double;
import java.awt.geom.*;
import javax.swing.*;
public class MarioComponent extends JComponent {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.setBackground(Color.BLACK);
Color marioM = new Color(153,0,0);
g2.setColor(marioM);
Line2D.Double M1 = new Line2D.Double(309,204,338,154);
Line2D.Double M2 = new Line2D.Double(338,154,355,178);
Line2D.Double M3 = new Line2D.Double(355,178,380,158);
Line2D.Double M4 = new Line2D.Double(380,157,400,217);
Line2D.Double M5 = new Line2D.Double(400,217,380,226);
Line2D.Double M6 = new Line2D.Double(380,226,368,197);
Line2D.Double M7 = new Line2D.Double(368,197,349,213);
Line2D.Double M8 = new Line2D.Double(349,213,338,195);
Line2D.Double M9 = new Line2D.Double(338,195,322,220);
Line2D.Double M10 = new Line2D.Double(322,220,309,205);
g2.draw(M1);
g2.draw(M2);
g2.draw(M3);
g2.draw(M4);
g2.draw(M5);
g2.draw(M6);
g2.draw(M7);
g2.draw(M8);
g2.draw(M9);
g2.draw(M10);
QuadCurve2D.Double hatCurve1 = new QuadCurve2D.Double(263,223,263,86,377,86);
QuadCurve2D.Double hatCurve2 = new QuadCurve2D.Double(377,86,618,86,618,326);
g2.draw(hatCurve1);
g2.draw(hatCurve2);
g2.setColor(Color.WHITE);
QuadCurve2D.Double whiteCurve1 = new QuadCurve2D.Double(298,222,299,133,360,133);
QuadCurve2D.Double whiteCurve2 = new QuadCurve2D.Double(359,133,430,133,414,241);
g2.draw(whiteCurve1);
g2.draw(whiteCurve2);
Color insideHatColor = new Color(221,19,19);
g2.setColor(insideHatColor);
QuadCurve2D.Double redHatCurve1 = new QuadCurve2D.Double(158,262,158,223,326,226);
QuadCurve2D.Double redHatCurve2 = new QuadCurve2D.Double(326,226,545,242,544,337);
g2.draw(redHatCurve1);
g2.draw(redHatCurve2);
g2.setColor(Color.BLACK);
QuadCurve2D.Double hatBlackOutter1 = new QuadCurve2D.Double(542,336,542,346,486,346);
QuadCurve2D.Double hatBlackOutter2 = new QuadCurve2D.Double(486,346,488,255,158,262);
g2.draw(hatBlackOutter1);
g2.draw(hatBlackOutter2);
QuadCurve2D.Double outLine1 = new QuadCurve2D.Double(544,336,573,336,573,376);
QuadCurve2D.Double outLine2 = new QuadCurve2D.Double(533,341,533,397,499,397);
g2.draw(outLine1);
g2.draw(outLine2);
//draws eyes
g2.setColor(Color.BLACK);
g2.fillOval(278,297,35,80);
g2.fillOval(382, 317, 35, 80);
//draws nose, though has to be drawn after eyes because of the left eye being covered by nose
Color skin = new Color(255,204,153);
g2.setColor(skin);
Arc2D.Double nose = new Arc2D.Double(186, 343, 150, 147, 20, 300,Arc2D.OPEN);
g2.draw(nose);
g2.fill(nose);
//now for mustache. *sigh*
Color brown1 = new Color(64,43,21);
g2.setColor(brown1);
QuadCurve2D.Double stache1= new QuadCurve2D.Double(453,414,471,484,441,484);
QuadCurve2D.Double stache2= new QuadCurve2D.Double(441,484,444,541,387,533);
QuadCurve2D.Double stache3= new QuadCurve2D.Double(387,533,352,555,314,532);
QuadCurve2D.Double stache4= new QuadCurve2D.Double(314,532,250,547,249,510);
QuadCurve2D.Double stache5= new QuadCurve2D.Double(249,510,231,515,230,490);
QuadCurve2D.Double stache6= new QuadCurve2D.Double(230,490,348,498,348,453);
QuadCurve2D.Double stache7= new QuadCurve2D.Double(348,453,452,457,452,415);
g2.draw(stache1);
g2.draw(stache2);
g2.draw(stache3);
g2.draw(stache4);
g2.draw(stache5);
g2.draw(stache6);
g2.draw(stache7);
//underneath hat dark area
g2.setColor(Color.BLACK);
QuadCurve2D.Double underHat1= new QuadCurve2D.Double(158,265,158,310,260,310);
Line2D.Double underHat2 = new Line2D.Double(260,310,281,264);
Line2D.Double underHat3 = new Line2D.Double(265,310,263,344);
g2.draw(underHat1);
g2.draw(underHat2);
g2.draw(underHat3);
}
}
Related
I am performing Canny edge detector using Android and Opencv on an image to detect the largest contour, extract it using warpPerspective method then find all objects inside that contour. Everything is working as expected but only for image that isn't rotated.
I am using boundingRect to get the contour and use its coordinates to extract it.
Here my code:
private Mat detectLargestContour(Mat origMat) {
// long e1 = Core.getTickCount();
Mat mGray = new Mat();
MatOfDouble mu = new MatOfDouble();
MatOfDouble stddev = new MatOfDouble();
Imgproc.cvtColor(origMat, mGray, Imgproc.COLOR_BGR2GRAY);
Core.meanStdDev(mGray, mu, stddev);
Imgproc.GaussianBlur(mGray, mGray, new Size(5, 5), 5);
//Imgproc.Canny(mGray, mGray, 30, 80, 3, false); //FOR HIGH BRIGHTNESS
//Imgproc.Canny(mGray, mGray, 50, 130, 3, false); // FOR LOW BRIGHTNESS
Imgproc.Canny(mGray, mGray, mu.get(0, 0)[0], stddev.get(0, 0)[0], 3, false);
Mat kernell = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(9,9));
Imgproc.morphologyEx(mGray, mGray, Imgproc.MORPH_CLOSE, kernell);
Imgproc.dilate(mGray, mGray, Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3)));
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(mGray, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
//MatOfPoint2f approxCurve = new MatOfPoint2f();
double largest_area=0;
Rect rect = new Rect();
for (int idx = 0; idx < contours.size() ; idx++) {
double a = Imgproc.contourArea(contours.get(idx)); //Find the area of contour
if (a > largest_area) {
largest_area = a;
rect = Imgproc.boundingRect(contours.get(idx));
}
}
if (rect.area() > 100000) {
Imgproc.rectangle(origMat, rect.tl(), rect.br(), new Scalar(0, 255, 0));
p1 = new Point(rect.tl().x, rect.tl().y);
p2 = new Point(rect.tl().x + rect.width, rect.tl().y);
p3 = new Point(rect.tl().x, rect.tl().y + rect.height);
p4 = new Point(rect.tl().x + rect.width, rect.tl().y + rect.height);
card_corners = new ArrayList<>();
card_corners.add(p1);
card_corners.add(p3);
card_corners.add(p4);
card_corners.add(p2);
warpedCard = new Mat(origMat.rows(), origMat.cols(), CvType.CV_8UC3);
final Point p1 = new Point(warpedCard.cols() + marge, warpedCard.rows() + marge);
final Point p2 = new Point(0 - marge, warpedCard.rows() + marge);
final Point p3 = new Point(0 - marge, 0 - marge);
final Point p4 = new Point(warpedCard.cols() + marge, 0 - marge);
LinkedList<Point> sceneList = new LinkedList<Point>();
sceneList.addLast(p4);
sceneList.addLast(p3);
sceneList.addLast(p2);
sceneList.addLast(p1);
MatOfPoint2f scene = new MatOfPoint2f();
scene.fromList(sceneList);
MatOfPoint2f obj = new MatOfPoint2f();
obj.fromList(card_corners);
Mat homography = Calib3d.findHomography(obj, scene);
Imgproc.warpPerspective(origMat, warpedCard, homography, new Size(warpedCard.cols(), warpedCard.rows()));
return warpedCard;
}
return origMat;
}
It's weird but only boundingRect gave me a stable and performant result but the drawn rectangle doesn't rotate with the found contour.
How can I manage to resolve this issue? Any thoughts?
EDIT:
I changed boundingRect with minAreaRect.
Here is the code
int largest_idx = 0;
for (int idx = 0; idx < contours.size() ; idx++) {
double a = Imgproc.contourArea(contours.get(idx)); //Find the area of contour
if (a > largest_area) {
largest_area = a;
// rect = Imgproc.boundingRect(contours.get(idx));
largest_idx = idx;
}
}
MatOfPoint2f new_mat = new MatOfPoint2f( contours.get(largest_idx).toArray() );
RotatedRect rbox = Imgproc.minAreaRect(new_mat);
Log.d("rotatedrect_angle", "" + rbox.angle);
Point points[] = new Point[4];
rbox.points(points);
for(int i=0; i<4; ++i){
Imgproc.line(origMat, points[i], points[(i+1)%4], new Scalar(255,255,255));
}
And here is what I've got:
As you can see the detection isn't as accurate as when I used boundingRect.
A Python demo to find and draw a rotatedRect:
# 2019/03/01
# https://stackoverflow.com/a/54942835/3547485
import numpy as np
import cv2
gray = cv2.imread("tmp.png", cv2.IMREAD_GRAYSCALE)
th, threshed = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY_INV)
cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
cnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
rbox = cv2.minAreaRect(cnt)
pts = cv2.boxPoints(rbox).astype(np.int32)
cv2.drawContours(img, [pts], -1, (0, 255, 0), 1, cv2.LINE_AA)
cv2.imwrite("dst.png", img)
Useful OpenCV functions(in Python) : cv2.minAreaRect, cv2.boxPoints, cv.2drawContours. You can find corresponding functions in Java.
I am attempting to draw a custom polygon onto an image I have called in using imageIO. once the polygon has been added, the image should then be output.
Below is my code:
public static void setPoints(List<Integer> pointArrayX, List<Integer> pointArrayY,File dest) throws IOException{
BufferedImage image = ImageIO.read(new File(dest+""));
Graphics2D g2d = image.createGraphics();
g2d.fillRect(0, 0, image.getWidth(), image.getHeight());
g2d.setColor(Color.RED);
BasicStroke bs = new BasicStroke(2);
g2d.setStroke(bs);
int[] xPoly = new int[pointArrayX.size()];
int[] yPoly = new int[pointArrayY.size()];
Polygon poly = new Polygon(xPoly,yPoly,xPoly.length);
poly.getBounds();
g2d.setPaint(Color.RED);
g2d.drawPolygon(poly);
g2d.fillPolygon(xPoly, yPoly, xPoly.length);
g2d.drawPolygon(xPoly, yPoly, xPoly.length);
g2d.setStroke(bs);
g2d.drawPolyline(xPoly, yPoly, xPoly.length);
g2d.drawOval(100, 100, 200, 200);
g2d.draw(poly);
File outputfile = new File(dest+"");
ImageIO.write(image, "png", outputfile);
Once run, the only shape which appears in the output image is the Oval which I have defined. it is just the Polygon which does not appear.
You don't populate your arrays.
int[] xPoly = new int[pointArrayX.size()]; //create an array and set its size
int[] yPoly = new int[pointArrayY.size()]; //create an array and set its size
Polygon poly = new Polygon(xPoly,yPoly,xPoly.length); //use the created array
You need to add data to xPoly and yPoly. Try:
int[] xPoly = new int[pointArrayX.size()]; //create an array and set its size
int[] yPoly = new int[pointArrayY.size()]; //create an array and set its size
//loop i added to copy the elements from your method arguments to the new arrays
for(int i = 0; i < xPoly.size(); i++) {
xPoly[i] = pointArrayX.get(i);
yPoly[i] = pointArrayY.get(i);
}
Polygon poly = new Polygon(xPoly,yPoly,xPoly.length); //use the created array
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I've gone through and made classes for my objects and calls to them in my paint component, but I cant actually get them to move. Here is my move and check walls program that is in the object class:
public void move()
{
ballX += dx;
ballY += dy;
checkWalls();
}
//bounce of top/bottom, pass through left/right
public void checkWalls() {
//left-right
if(ballX > w) {
ballX = -diam;
}
else if(ballX < -diam) {
ballX = w;
}
//top-bottom
if(ballY < 0) {
dy *= -1;
}
else if(ballY + diam > h) {
dy *= -1;
}
}
And here is my call to them:
while(true) // infinite loop
{
jelly1.move();
frame.repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
Also i feel the need to mention i have a background and a background component. The while(true) is in the background component because that's where the objects are created. And the frame is set visible in the background where the main method is.
Paint component is as follows:
public class BackgroundComponent extends JComponent {
Jellyfish jelly1;
Jellyfish jelly2;
Jellyfish jelly3;
Diver diver;
public BackgroundComponent() {
diver = new Diver(100, 300);
jelly1 = new Jellyfish(450, 450);
jelly2 = new Jellyfish(150, 300);
jelly3 = new Jellyfish(350, 75);
diver = new Diver(100, 300);
}
public void paintComponent(Graphics g){
//Drawing instructions go here
//Recover Graphics2D
Graphics2D g2 = (Graphics2D)g;
//Make gradient
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
int w = getWidth();
int h = getHeight();
Color color1 = Color.CYAN;
Color color2 = Color.BLACK;
GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
g2.setPaint(gp);
g2.fillRect(0, 0, w, h);
//Constructs rectangles on edge of screen and draws them
Rectangle box = new Rectangle(0,0,75,700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box);
Rectangle box2 = new Rectangle(625, 0, 75, 700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box2);
//Draws lines, with a stroke of 5, over rectangles
Line2D.Double segment = new Line2D.Double(10, 0, 10, 700);
g2.setStroke(new BasicStroke(5));
g.setColor(Color.GRAY);
g2.draw(segment);
Line2D.Double segment2 = new Line2D.Double(30, 0, 30, 700);
g.setColor(Color.GRAY);
g2.draw(segment2);
Line2D.Double segment3 = new Line2D.Double(50, 0, 50, 700);
g.setColor(Color.GRAY);
g2.draw(segment3);
Line2D.Double segment4 = new Line2D.Double(70, 0, 70, 700);
g.setColor(Color.GRAY);
g2.draw(segment4);
Line2D.Double segment5 = new Line2D.Double(690, 0, 690, 700);
g.setColor(Color.GRAY);
g2.draw(segment5);
Line2D.Double segment6 = new Line2D.Double(670, 0, 670, 700);
g.setColor(Color.GRAY);
g2.draw(segment6);
Line2D.Double segment7 = new Line2D.Double(650, 0, 650, 700);
g.setColor(Color.GRAY);
g2.draw(segment7);
Line2D.Double segment8 = new Line2D.Double(630, 0, 630, 700);
g.setColor(Color.GRAY);
g2.draw(segment8);
//Draws rectangle around title with thick boarder
Rectangle box3 = new Rectangle(40,40,620,75);
g.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(5));
g2.draw(box3);
//Drawing text
String title = "Through the Depths";
//Sets font, font size, and color
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.DARK_GRAY);
g2.drawString(title, (50), 100);
//Places same text slightly up and over
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.WHITE);
g2.drawString(title, 53, 97);
//Draws ellipses with a stroke of 2 (these are the bubbles)
Ellipse2D.Double ellipse = new Ellipse2D.Double(450, 200, 150, 150);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
Ellipse2D.Double ellipse2 = new Ellipse2D.Double(510, 375, 90, 90);
g2.draw(ellipse2);
Ellipse2D.Double ellipse3 = new Ellipse2D.Double(470, 485, 70, 70);
g2.draw(ellipse3);
Ellipse2D.Double ellipse4 = new Ellipse2D.Double(510, 580, 45, 45);
g2.draw(ellipse4);
// Draws curves for bubbles
QuadCurve2D q = new QuadCurve2D.Float();
q.setCurve(548, 210, 607, 240, 590, 295);
g2.setStroke(new BasicStroke(3));
g2.draw(q);
QuadCurve2D q2 = new QuadCurve2D.Float();
q2.setCurve(575, 387, 607, 415, 585, 445);
g2.draw(q2);
QuadCurve2D q3 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(2));
q3.setCurve(515, 493, 545, 511, 528, 540);
g2.draw(q3);
QuadCurve2D q4 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(1));
q4.setCurve(538, 585, 558, 595, 545, 617);
g2.draw(q4);
// Sets color to pink before drawing jellyfish
g.setColor(Color.PINK);
//draws jellyfish
jelly1.draw(g);
jelly2.draw(g);
jelly3.draw(g);
// Draws diver
diver.draw(g);
while(true) // infinite loop
{
jelly1.move();
repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
}
}
while(true){ ... } and Thread.Sleep inside a paintComponent implementation is completely the wrong way of doing things. By doing this, you are blocking the Event Dispatching Thread completely which means that your UI will no longer be updated properly and the UI will no longer be responsive.
What you should do:
Remove the while(true){ ... } loop from the paintComponent override
Create a javax.swing.Timer, set it to run every 10 milliseconds
In the ActionListener.actionPerformed implementation - the action that will be performed each 10 ms - move the jelly and call for a repaint
Start this timer after initialization is done, eg at the end of your constructor or initialization method (not paintComponent).
Stop the timer when it is no longer needed
Simplified example for this Timer, based on your snippet:
new javax.swing.Timer( 10, new ActionListener( ) {
#override
public void actionPerformed( ActionEvent e ) {
jelly1.move();
repaint();
}
}).start();
I've been trying to use OpenCV's findhomography and perspectivetransform to get the transformation matrix from one set of points to another.
I generate 50 random points for each data set and draw them on the screen. I then ask findHomography to calculate a transformation matrix from the 2 sets of points and use it to transform the corners of the original set. The result of the perspective transform is drawn on the screen.
The problem is the matrix findhomography produces is not correct, even when ignoring the issue of outliers. I want to use this example in a feature matching problem.
Here is my code for testing.
//
Mat outImg = new Mat(500,1000,CvType.CV_32FC3,new Scalar(0,0,0));
//make obj test points
List<Point> p1 = new ArrayList<Point>();
for(int i=0;i<50;i++){
p1.add(new OpenCVTemplateMatcher().generateRandom2DPoint(50,50,450,450));
}
//make scene test points
List<Point> p2 = new ArrayList<Point>();
for(int i=0;i<50;i++){
p2.add(new OpenCVTemplateMatcher().generateRandom2DPoint(550,50,950,450));
}
System.out.println(p1.size());
//draw the points
for(Point p:p1){
Core.circle(outImg, p, 1, new Scalar(255,0,255),2);
}
for(Point p:p2){
Core.circle(outImg, p, 1, new Scalar(0,255,0),2);
}
//find bounding boxes on points and draw them
MatOfPoint2f mp1 = new MatOfPoint2f(); mp1.fromList(p1);
MatOfPoint2f mp2 = new MatOfPoint2f(); mp2.fromList(p2);
RotatedRect r1 = Imgproc.minAreaRect(mp1);
RotatedRect r2 = Imgproc.minAreaRect(mp2);
Point[] v1 = new Point[4]; r1.points(v1);
Point[] v2 = new Point[4]; r2.points(v2);
Core.line(outImg, v1[0], v1[1], new Scalar(0, 255, 0),1);
Core.line(outImg, v1[1], v1[2], new Scalar(0, 255, 0),1);
Core.line(outImg, v1[2], v1[3], new Scalar(0, 255, 0),1);
Core.line(outImg, v1[3], v1[0], new Scalar(0, 255, 0),1);
Core.line(outImg, v2[0], v2[1], new Scalar(255, 255, 0),1);
Core.line(outImg, v2[1], v2[2], new Scalar(255, 255, 0),1);
Core.line(outImg, v2[2], v2[3], new Scalar(255, 255, 0),1);
Core.line(outImg, v2[3], v2[0], new Scalar(255, 255, 0),1);
//show the corners
for(int i=0;i<4;i++){
Core.circle(outImg, v1[i], 3, new Scalar(200,250,50),2);
Core.circle(outImg, v2[i], 3, new Scalar(0,238,250),2);
}
MatOfPoint2f p1Corners = new MatOfPoint2f(); p1Corners.fromArray(v1);
MatOfPoint2f p2Corners = new MatOfPoint2f(); p2Corners.fromArray(v2);
//find transform as H
//Mat H = Calib3d.findHomography(p1Corners, p2Corners,Calib3d.RANSAC, 5);
Mat H = Calib3d.findHomography(mp1, mp2,0, 5);
//H = findTransform(mp1,mp2);
//find the transform of H from 1'(original)s corners
Mat orig_corners = new Mat(4,1,CvType.CV_32FC2);
Mat transformed_corners = new Mat(4,1,CvType.CV_32FC2);
orig_corners.put(0, 0, new double[] {v1[0].x,v1[0].y});
orig_corners.put(1, 0, new double[] {v1[1].x,v1[1].y});
orig_corners.put(2, 0, new double[] {v1[2].x,v1[2].y});
orig_corners.put(3, 0, new double[] {v1[3].x,v1[3].y});
Core.perspectiveTransform(orig_corners,transformed_corners,H);
Core.line(outImg, new Point(transformed_corners.get(0,0)), new Point(transformed_corners.get(1,0)), new Scalar(0, 255, 255),4);
Core.line(outImg, new Point(transformed_corners.get(1,0)), new Point(transformed_corners.get(2,0)), new Scalar(0, 255, 255),4);
Core.line(outImg, new Point(transformed_corners.get(2,0)), new Point(transformed_corners.get(3,0)), new Scalar(0, 255, 255),4);
Core.line(outImg, new Point(transformed_corners.get(3,0)), new Point(transformed_corners.get(0,0)), new Scalar(0, 255, 255),4);
Highgui.imwrite("test.jpg", outImg);
and here is a result
I found that findhomography doesn't work at all given any number of points other than 4 corners in each set, but then the problem becomes trivial. Am I using it wrong? If I wanted to write my own function for finding a transformation between 2 matrices how would I go about doing it?
When I add 1 chart to the document there is no problem
When I add the second chart I get this error ...
Exception in thread "main" com.itextpdf.text.exceptions.IllegalPdfSyntaxException: Unbalanced save/restore state operators.
chart1 = SpecialJFreeChartBuilder.createChart1(
"Site and Number of Requests ", results);
document.newPage();
PdfContentByte Add_Chart_Content = writer.getDirectContent();
PdfTemplate template_Chart_Holder = Add_Chart_Content
.createTemplate(width, height);
Graphics2D Graphics_Chart = template_Chart_Holder.createGraphics(
width, height, new DefaultFontMapper());
Rectangle2D Chart_Region = new Rectangle2D.Double(0, 0, 540, 380);
chart1.draw(Graphics_Chart, Chart_Region);
Graphics_Chart.dispose();
Add_Chart_Content.addTemplate(template_Chart_Holder, 0, 0);
chart2 = SpecialJFreeChartBuilder.createChart2(
"Site and totalAmount ", results);
document.newPage();
PdfContentByte Add_Chart_Content1 = writer.getDirectContent();
PdfTemplate template_Chart_Holder1 = Add_Chart_Content1
.createTemplate(width, height);
Graphics2D Graphics_Chart1 = template_Chart_Holder1.createGraphics(
width, height, new DefaultFontMapper());
Rectangle2D Chart_Region1 = new Rectangle2D.Double(0, 0, 540, 380);
chart2.draw(Graphics_Chart1, Chart_Region1);
Graphics_Chart.dispose();
Add_Chart_Content.addTemplate(template_Chart_Holder1, 0, 0);
....
document.close();
Can anyone help me ....
Solved the issue ... Graphics_Chart.dispose(); must be : Graphics_Chart1.dispose(); Graphics_Chart2.dispose();