Have the following code:
image = new Image(display, imageData);
offScreenImageGC.drawImage(image, 0, 0, imageData.width, imageData.height, imageData.x, imageData.y, imageData.width, imageData.height);
/* Draw the off-screen image to the shell. */
shellGC.drawImage(offScreenImage, 0, 0);
... after executing the bottom instruction: shellGC.drawImage(offScreenImage, 0, 0); sometimes I get the image visible on the shellGC component, sometimes - not. I get it visible only when I "slow down" the execution of the program , for example when I am in debug mode. But when it runs fast - it does not show. I want it forcefully shown, flushed or whatever you name it, is it possible ?
Let me clarify that what I want to achieve is to implement an animation which is frame based, but yet to be able to play it double buffered, able to stop it, show only particular single frame paused, and etc things...
Thank you.
It came out that this is the ONLY SAFE way to double buffer with SWT:
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {
//Obtain the next frame
ImageData imageData = imageDataArray[iad.imageNumber];
Image imageFrame = new Image(display, imageData);
// Create the image to fill the canvas
Image image = new Image(display, canvas.getBounds());
// Set up the offscreen gc
GC gcImage = new GC(image);
//Draw the image offscreen
gcImage.setBackground(event.gc.getBackground());
gcImage.drawImage(imageFrame, 0, 0);
// Draw the offscreen buffer to the screen
event.gc.drawImage(image, 0, 0);
imageFrame.dispose();
image.dispose();
gcImage.dispose();
}
});
.... by using this method ONLY for doublebuffering there is guaranteed crossplatform equal runtime behaviour, and the unpredictable buffer behaviour is also gone.
Related
I'm working on an application which allows a used to place controls, move, resize, etc. But I'm trying to add icon images to a button control. When placed and instanced, it resizes the icon image per the code below.
But when I resize the control using user features and it calls this routing again, it fails to resize the image and it remains the original icon size. I've tried using "this.", passing the control to itself, I've done prints to ensure it's seeing the new size and width... what I am missing?
Also, when I create a 2nd control (or 3rd, etc), it uses the 1st image's initial size.
Thanks!
protected void sizeIcon () {
try {
File f2 = new File("media\\button.gif");
BufferedImage inputImage = ImageIO.read(f2);
BufferedImage img = new BufferedImage(this.getWidth(), this.getHeight(), inputImage.getType());
Graphics2D g = img.createGraphics();
g.drawImage(inputImage, 7, 0, this.getWidth(), this.getHeight(), null);
ImageIO.write(img, "gif", new File("test.gif"));
this.setIcon(new ImageIcon("test.gif"));
g.dispose();
} catch(Exception e) {System.out.println(e);}
Sorry, got it, appears the old file was not being replaces.
-MH
I use OpenImaj for a project and I need to display the video in 800*600 to a panel but I must capture images at 1920,1080 when I click a button.
My strategy was initially to capture from my webcam at 1920,1080 and to resize image in a icon of a label contained in my panelVideo.
My problem is that the performance is very low.
Is there an efficient method to resize video according to the size of panelVideo without changing the frame size (that I use for saving the image at 1920,1080)?
Thank you for your answer.
Regards.
final VideoCapture vc = new VideoCapture(1920,1080);
vc.setFPS(10);
final VideoDisplay<MBFImage> display = VideoDisplay.createVideoDisplay(vc, panelVideo);
display.addVideoListener(new VideoDisplayAdapter<MBFImage>()
{
#Override
public void beforeUpdate(final MBFImage frame)
{
//here I create a bufferedImage from the resized frame
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) img.getGraphics();
g.drawImage(ImageUtilities.createBufferedImageForDisplay(frame), 0, 0, 800, 600, null);
//here is the label that I use to display the video
labelVideo.setIcon(new ImageIcon(ImageUtilities.createBufferedImageForDisplay(frame)));
}
});
You can at least remove fixed code like this out of the loop - that is create it only once
//here I create a bufferedImage from the resized frame
BufferedImage img = new BufferedImage(800, 600, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) img.getGraphics();
and also have the Icon created once and setImage() as needed. Beyond that I dont know how to convert MBF to BufferedImage thats the pain of using different libraries. g.drawImage() is a good way to draw the scaled image.
See http://openimaj.org/apidocs/org/openimaj/image/processing/resize/package-frame.html for the OpenIMAJ classes that let you resize an MBFImage. You'll have to play and see what is fastest, but in my very quick experiments I found BilinearInterpolation to be better than ResizeProcessor with the default options, however using a different filter in ResizeProcessor might be faster.
Rather than creating a new BufferedImage each frame, you would probably be better off drawing the MBFImage into a Swing component that displays them directly: http://openimaj.org/apidocs/org/openimaj/image/DisplayUtilities.ScalingImageComponent.html or http://openimaj.org/apidocs/org/openimaj/image/DisplayUtilities.ImageComponent.html (note that technically these both convert to BufferedImage behind the scenes, but they only allocate the image once and just redraw into it saving a lot of time).
i need to resize my webcam feed to a constant value like 430*315 to view from my j panel without resizing it only show a little area that is equal to the resized j panel um using OpenCV VideoCapture method for capture video from webcam
below is my code part that i used to do grab the frames
if (webSource.grab()) {
try {
webSource.retrieve(frame);
Graphics g = jPanel2.getGraphics();
i tried
Size sz = new Size(430, 315);
Imgproc.resize(frame, frame, sz);
and
webSource.set(CV_CAP_PROP_FRAME_WIDTH, 430);
webSource.set(CV_CAP_PROP_FRAME_HEIGHT, 315);
i was unable to accomplish my requirement from any of that so is there a way that this can be done
While Capturing Frames from the Webcam you can resize using the resizing function.
// Using C++
VideoCapture cap(0);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 430);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 315);
Mat image;
cap.read(image);
resize(image, image, Size(430, 315), 0, 0, INTER_CUBIC);
namedWindow("firstframe", 1);
imshow("firstframe", image);
waitKey(0);
Maybe this can do the trick.
To get sections of a current image as a new image, use ROI (region of interest) to specify the section. The ROI is a rectangle here, which can be initialized several ways.
Sorry this is in C++, not Java;
Some ways to specify the region:
Rect ROI = Rect(Point(0, 0), Size(430, 315));
Rect ROI = Rect(0, 0, 430, 315);
Rect ROI = Rect(Point(x, y), Point(x + 430, y + 315));
Now to get a section of the captured frame:
Mat windowedframe = frame(ROI);
WARNING: This method doesn't care if the boundaries of the rectangle is located in the image or not, so if you go beyond the resolution of frame, it will crash.
I am currently profiling my Java-2d-Application (Game-Engine for learning purposes).
Since I cannot guarantee that each frame is overwritten completely, I have to clear the background to a solid color (i.e. Color.BLACK) each frame.
The way I do it is SLOW (about 40% of drawing-time in my environment goes to just clearing the background).
First I get a graphics-context from the bufferStrategy, then I draw a [PickYourColor]-Rectangle in full resolution on it before drawing the actual content.
// fill background with solid color
graphics.setColor(Color.BLACK);
graphics.fillRect(
0,
0,
(int) bounds.getWidth(),
(int) bounds.getHeight());
Is there a more efficient, platform-independant, way to clear the background to a solid color each frame using Java-2D (this is not a LWJGL-question)?
What I'm looking for is a graphics.clearBackgroundToSolidColor(Color color) - Method...
By request: here the full rendering method (it's not an SSCCE, but it's pretty short and self explanatory)
/**
* Create a new graphics context to draw on and
* notify all RenderListeners about rendering.
*/
public void render() {
///// abort drawing if we don't have focus /////
if (!this.windowJFrame.hasFocus()) {
return;
}
///// draw and create new graphics context /////
Graphics2D graphics = null;
do {
try {
graphics = (Graphics2D) this.bufferStrategy.getDrawGraphics();
Rectangle2 bounds = this.getBounds();
// set an inexpensive, yet pretty nice looking, rendering directives
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// fill background with solid color
graphics.setColor(Color.BLACK);
graphics.fillRect(
0,
0,
(int) bounds.getWidth(),
(int) bounds.getHeight());
// notify all listeners that they can draw now
synchronized (this.renderListeners) {
for (RenderInterface r : this.renderListeners) {
r.render(graphics, bounds);
}
}
// show buffer
graphics.dispose();
this.bufferStrategy.show();
} catch (Exception e) {
Logger.saveMessage("window", Logger.WARNING, "Caught exception while drawing frame. Exception: " + e.toString());
}
} while (this.bufferStrategy.contentsLost());
}
I can't say why the fillRect is slow, but you can try creating an Image and draw it as bg. not sure if it will be faster though.
try:
BufferedImage bi = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
int[] imageData =((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
Arrays.fill(imageData, 0);
then instead of fillRect draw the Image:
graphics.drawImage(bi, 0, 0, null);
Tell me how it went(I have my doubts about this).
If you would like to clear the entire background than try canvas.drawColor(color, PorterDuff.Mode.CLEAR). Should be a bit faster
I've setup a method for loading an image into a ByteBuffer and called Display.setIcon(), this works... partially. This sets the icon of the taskbar, but leaves the window's icon as the default LWJGL icon. Is there another Display method I need to call? Or is this something to do with windows.
Here's the method of loading the icon if needed:
public static final ByteBuffer[] getIcon()
{
Image image = Toolkit.getDefaultToolkit().getImage("rw_icon.PNG");
MediaTracker tracker = new MediaTracker(new JPanel());
tracker.addImage(image, 0);
try
{
tracker.waitForAll();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
tracker.removeImage(image);
BufferedImage bufImage = new BufferedImage(32, 32, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = bufImage.createGraphics();
graphics.drawImage(image, 0, 0, null);
graphics.dispose();
image.flush();
ByteBuffer buffer = ByteBuffer.allocateDirect(32*32*4);
buffer.clear();
byte[] bufferData = (byte[])bufImage.getRaster().getDataElements(0, 0, 32, 32, null);
buffer.put(bufferData);
buffer.rewind();
return (new ByteBuffer[] {buffer});
}
No.
You just need to pass an array of two versions of the icon (16x16, 32x32) to the setIcon(..) method.
It seems like you misunderstood the ByteBuffer[]. You are supposed to pass an array of different ByteBuffers. Not just a ByteBuffer array with one element in it. Therefore it would probably be best to create a new method which basically just does what your getIcon() method does, but expects a String as a file path. That way you can easily create the real array of icon byte-buffers.
public static int setIcon(java.nio.ByteBuffer[] icons)
Sets one or more icons for the Display. On Windows you should supply at least one
16x16 icon and one 32x32. Linux (and similar platforms) expect one
32x32 icon. Mac OS X should be supplied one 128x128 icon The
implementation will use the supplied ByteBuffers with image data in
RGBA (size must be a power of two) and perform any conversions
nescesarry for the specific platform.
NOTE: The display will make a
deep copy of the supplied byte buffer array, for the purpose of
recreating the icons when you go back and forth fullscreen mode. You
therefore only need to set the icon once per instance.
http://lwjgl.org/javadoc/org/lwjgl/opengl/Display.html#setIcon(java.nio.ByteBuffer[])