use ImageIO.write Java to save jpg in real time - java

There is my code. I try to analysis data and create the graph and save to local driver. The program is working fine now. But I find out that the jpg file only can be save to local drive after the program is all finished. However, there are too many data and too many graph need to be created. The whole program may run for hours. I am just wondering could I make it save the jpg in real time? so I can view all graph it just created. Or I don't have to give up all graph if I need to stop the program before it finish all.
Thank you
protected void paintComponent(Graphics g) {
System.out.println("go");
super.paintComponent(g);
BufferedImage jpg = new BufferedImage(1040, 400,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = jpg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
double total=0;
// Draw ordinate.
g2.draw(new Line2D.Double(SPACE, SPACE, SPACE, h-SPACE));
// Draw abcissa.
g2.draw(new Line2D.Double(SPACE, h/2, w-SPACE, h/2));
double xInc = (double)(w - 2*SPACE)/(data.size()-1);
double scale = (double)(h/2 - SPACE*3)/getMax();
// Mark data points.
g2.setPaint(Color.red);
for(int i = 0; i < data.size(); i++) {
double x = SPACE + i*xInc;
double y;
if(data.get(i)!=0){
y= h/2 - SPACE - scale*data.get(i);
total = total + data.get(i);
}else{
y = h/2;
}
g2.fill(new Ellipse2D.Double(x, y-1, 4, 4));
}
try {
ImageIO.write(jpg, "JPEG", new File("111\\"+total/data.size() + ".jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

paintComponent is called as event handling, whenever repainting is needed. And may occur often. Painting should be done fast too. So save the image outside the paint component.
Maybe check the file existence, or number the files.
Call Graphics.dispose() too, to prevent resource leaks.
BufferedImage jpg = new BufferedImage(1040, 400,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = jpg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintComponent(g2);
g2.dispose();
Also you picked a program-relative folder. Below I picked the user's folder, and
possibly create a directory 111 if not present (mkdirs).
String userHome = System.getProperty("user.home");
File imgFile = new File(userHome + "/111/" + (total/data.size()) + ".jpg");
// Windows still allows `/` instead of `\` as path separator.
imgFile.getParentFile().mkdirs();
System.out.println("Writing to image: " + imgFile.getPath());
...
ImageIO.write(jpg, "JPEG", imgFile);

Related

Taking a screenshot with JOGL

I am looking for a way to screenshot my GLCanvas programmatically without awt Robot.
Here is my current setup:
Constructor:
glcaps = new GLCapabilities(GLProfile.get(GLProfile.GL2));
glcaps.setDoubleBuffered(true);
glcaps.setHardwareAccelerated(true);
glcanvas = new GLCanvas(glcaps);
glcanvas.setSize(720, 720);
glcanvas.addGLEventListener(this);
glcanvas is declared as an instance variable: GLCanvas glcanvas
OpenGL init:
#Override
public void init(GLAutoDrawable glad) {
GL2 gl = glad.getGL().getGL2();
glu = new GLU();
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glDepthFunc(GL2.GL_LEQUAL);
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
gl.glClearColor(0f, 0f, 0f, 1f);
// Some camera related code not shown
}
OpenGL display:
public void display(GLAutoDrawable glad) {
GL2 gl = glad.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
...
// Orient camera and draw a simple cube
...
gl.glFlush();
}
Screenshot method:
BufferedImage b = new BufferedImage(glcanvas.getWidth(), glcanvas.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = b.createGraphics();
glcanvas.setupPrint(glcanvas.getWidth(), glcanvas.getWidth(), 50, 50, 50);
glcanvas.print(g);
try {
ImageIO.write(b, "png", new File("test.png"));
} catch (IOException ex) {
// Error handling
}
glcanvas.releasePrint();
g.dispose();
This method works, as in executes without crashing, but the png file I get is just black with no cube. I also tried using glReadPixels but that does not work either as it just gives me a buffer full of 0's (black).
I think that the problem is that I am not reading glcanvas from the draw thread. Is this the error, and if so, how can I solve it?
All answers appreciated!
First, you have to be sure that you read the framebuffer after what you want to catch has been rendered.
Second, you can do something like this:
protected void saveImage(GL3 gl3, int width, int height) {
try {
BufferedImage screenshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = screenshot.getGraphics();
ByteBuffer buffer = GLBuffers.newDirectByteBuffer(width * height * 4);
// be sure you are reading from the right fbo (here is supposed to be the default one)
// bind the right buffer to read from
gl3.glReadBuffer(GL_BACK);
// if the width is not multiple of 4, set unpackPixel = 1
gl3.glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
// The color are the three consecutive bytes, it's like referencing
// to the next consecutive array elements, so we got red, green, blue..
// red, green, blue, and so on..+ ", "
graphics.setColor(new Color((buffer.get() & 0xff), (buffer.get() & 0xff),
(buffer.get() & 0xff)));
buffer.get(); // consume alpha
graphics.drawRect(w, height - h, 1, 1); // height - h is for flipping the image
}
}
// This is one util of mine, it make sure you clean the direct buffer
BufferUtils.destroyDirectBuffer(buffer);
File outputfile = new File("D:\\Downloads\\texture.png");
ImageIO.write(screenshot, "png", outputfile);
} catch (IOException ex) {
}
}
I filled some comment inside, if something is still unclear, don't hesitate to ask further

Add watermark to image

I'm trying to add watermark to an image on my website. The way I want it to work is to show the watermark when the image is downloaded or shown on other websites. On my website I want to show it without the watermark. It would be awesome if the watermark is placed on the picture. Is this possible to do the above mentioned by using some picture meta-data or http headers for example? Or is it impossible to perform this and should I do it by adding a footer upon upload and hiding it?
You can reference the follow link:
Add text watermark to image
static void addTextWatermark(String text, File sourceImageFile, File destImageFile) {
try {
BufferedImage sourceImage = ImageIO.read(sourceImageFile);
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
// initializes necessary graphic properties
AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
g2d.setComposite(alphaChannel);
g2d.setColor(Color.BLUE);
g2d.setFont(new Font("Arial", Font.BOLD, 64));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(text, g2d);
// calculates the coordinate where the String is painted
int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
int centerY = sourceImage.getHeight() / 2;
// paints the textual watermark
g2d.drawString(text, centerX, centerY);
ImageIO.write(sourceImage, "png", destImageFile);
g2d.dispose();
System.out.println("The tex watermark is added to the image.");
} catch (IOException ex) {
System.err.println(ex);
}
}
Add image watermark to image
static void addImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile) {
try {
BufferedImage sourceImage = ImageIO.read(sourceImageFile);
BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);
// initializes necessary graphic properties
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
g2d.setComposite(alphaChannel);
// calculates the coordinate where the image is painted
int topLeftX = (sourceImage.getWidth() - watermarkImage.getWidth()) / 2;
int topLeftY = (sourceImage.getHeight() - watermarkImage.getHeight()) / 2;
// paints the image watermark
g2d.drawImage(watermarkImage, topLeftX, topLeftY, null);
ImageIO.write(sourceImage, "png", destImageFile);
g2d.dispose();
System.out.println("The image watermark is added to the image.");
} catch (IOException ex) {
System.err.println(ex);
}
}
http://www.codejava.net/java-se/graphics/adding-a-watermark-over-an-image-programmatically-using-java

Creating a PNG image using an array of points in Java (Always comes up black)

I currently have a one-dimensional double array holding 50 different points meant to be spaced 1 apart. I need these points to be drawn and connected by lines in an image. Currently the PNG image is being produced, and if I add in an individual line it will work, but somehow the loop makes the entire image come up as black. Any ideas on what's going wrong?
BufferedImage bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig2 = bi.createGraphics();
ig2.setBackground(Color.white);
ig2.setColor(Color.red);
for(int i = 0; i < 49; i++){
Shape line = new Line2D.Double(i,finalpoints[i],i+1,finalpoints[i+1]);
ig2.draw(line);
}
//Export the result to a file
try {
ImageIO.write(bi, "PNG", new File("C://Users/vince/Desktop/heightmap.png"));
} catch (IOException e) {
System.out.println("There was an error writing the image to file");
}
There is two overloaded Line2D.Double constructors: the 1st one takes two Point2D as parameters so if your array contains Point2D objects your code should be :
Shape line = new Line2D.Double(finalpoints[i],finalpoints[i+1]);
the second method Line2D.Double(double x1, double y1, double x2, double y2)
and it takes the points' coordinates, so if you want the second, tour code should be like this:
Shape line = new Line2D.Double(finalpoints[i].getX(), finalpoints[i].getY(), finalpoints[i+1].getX(), finalpoints[i+1].getY());
if your array doesn't contain Point2D objects, just update your post so we can help you.
Setting the foreground color does not fill the background.
Also a Graphics.dispose() is needed.
BufferedImage bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig2 = bi.createGraphics();
ig2.setBackground(Color.white);
ig2.setColor(Color.white);
ig2.fillRect(0, 0, 50, 50);
ig2.setColor(Color.red);
// Better use a ig2.drawPolyline (Polygon) so the joints are nicer.
for(int i = 0; i < 49; i++){
Shape line = new Line2D.Double(i,finalpoints[i],i+1,finalpoints[i+1]);
ig2.draw(line);
}
ig2.dispose();

Shift Image while keeping dimensions

I have an image that I would like to shift by some x, y value and then save. My problem is that I would like to keep my original dimensions, so that there is x and y "blank" space left after shifting my image.
Also, is there any way I can set the "blank" space to black?
Example: I shift a 600x600 image down by 45 and left by 30, so that the image is still 600x600 but the result has a 45 height and 30 width of "blank" space.
So far I have been using getSubimage method of BufferedImage to try and solve this but I cannot seem to return to the original dimensions.
Any ideas on how to solve this problem?
You could do that by creating a new buffered image and drawing on to it.
// Create new buffered image
BufferedImage shifted = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// Create the graphics
Graphics2D g = shifted.createGraphics();
// Draw original with shifted coordinates
g.drawImage(original, shiftx, shifty, null);
Hope this works.
public BufferedImage shiftImage(BufferedImage original, int x, int y) {
BufferedImage result = new BufferedImage(original.getWidth() + x,
original.getHeight() + y, original.getType());
Graphics2D g2d = result.createGraphics();
g2d.drawImage(original, x, y, null);
return result;
}
Should work.
Saving
public void SaveImage(BufferedImage image, String filename) {
File outputfile = new File(filename + ".png");
try {
ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Removing BufferedImage pixel values and or setting them transparent

I have been working with the polygon class and trying to set the pixel values inside of the polygon to transparent or remove them all together if this is possible, however I have hit a bit of a wall as I am trying to store the values as RGB int values and don't know how I would be able to make a pixel transparent/removed via this method.
Additionally to this I would also like to do the same thing but keeping pixels inside the polygon and deleting those outside if possible in order to be left with only the pixels contained within the polygon. I have searched around for this before but to no avail.
I did attempt to create a SSCCE for this to make it easier to work with and view for anyone taking the time to help however as its part of a much larger programme that I am working on creating one is proving to take some time, however once I have one working to better demonstrate this problem I will edit this post.
Thank you to anyone for taking the time to help me with this problem
Below I have some code for what I am currently using to segment the pixels that are contained within an already specified polygon. This is extremely similar to the way i do it for setting pixels outside the polygon to transparent only with the if statement arguments swapped around to remove a segment of the image and haveing a return for newImage rather than save image stuff and it works perfectly, however when I do it this way to save the pixels contained in the polygon it doesn't save for some reason.
public void saveSegment(int tabNum, BufferedImage img) {
segmentation = new GUI.Segmentation();
Polygon p = new Polygon();
Color pixel;
p = createPolygon(segmentation);
int height = img.getHeight();
int width = img.getWidth();
newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//loop through the image to fill the 2d array up with the segmented pixels
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
//If the pixel is inside polygon
if(p.contains(x, y) == true) {
pixel = new Color(img.getRGB(x, y));
//set pixel equal to the RGB value of the pixel being looked at
int r = pixel.getRed(); // red component 0...255
int g = pixel.getGreen(); // green component 0...255
int b = pixel.getBlue(); // blue component 0...255
int a = pixel.getAlpha(); // alpha (transparency) component 0...255
int col = (a << 24) | (r << 16) | (g << 8) | b;
newImage.setRGB(x, y, col);
}
else {
pixel = new Color(img.getRGB(x, y));
int a = 0; // alpha (transparency) component 0...255
int col = (a << 24);
newImage.setRGB(x, y, col);
}
}
}
try {
//then save as image once all in correct order
ImageIO.write(newImage, "bmp", new File("saved-Segment.bmp"));
JOptionPane.showMessageDialog(null, "New image saved successfully");
} catch (IOException e) {
e.printStackTrace();
}
}
An easier way is to use Java2D's clipping capability:
BufferedImage cutHole(BufferedImage image, Polygon holeShape) {
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = newImage.createGraphics();
Rectangle entireImage =
new Rectangle(image.getWidth(), image.getHeight());
Area clip = new Area(entireImage);
clip.subtract(new Area(holeShape));
g.clip(clip);
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
BufferedImage clipToPolygon(BufferedImage image, Polygon polygon) {
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(), image.getType());
Graphics2D g = newImage.createGraphics();
g.clip(polygon);
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}

Categories