How can I clear the cache of an swt.Image on macos? - java

I'm developing an application using Eclipse and SWT.
If I do the following on a mac, the second file has the same contents as the first one.
There was a bug in SWT that was solved nearly a decade ago that was related with how swt.GC was disposed. But in my case it's not being disposed.
It seems there's a cache being held somewhere, but I couldn't find a way to get rid of it.
My code, simplified:
Image myImg = new Image( Display.getDefault(), 100, 100 );
GC mygc = new GC( myImg );
// draw something
// Saves the image to a file.
saveImage( myImg );
// draw something else on the same image.
// Saves the image to another file.
saveImage( myImg );
myImg.dispose();
mygc.dispose();
If I do this after saving the first file, and before the extra drawing operations, the problem is solved:
mygc.dispose();
mygc = new GC( myImg );
But I don't want to dispose and create a new GC, because of performance issues.
On Windows it works perfectly.

Related

Still having problems with jLabel PNG images and can't resize the images

I've already read the post Java / Swing how to deal with different screen DPI and density settings?, regarding the jLabel images pixelization on new JDKs (above 9) and high DPI screens, but it didn't do the trick.
Here is my case and code:
My old projects using png images worked fine (no pixelization) on old DPI screens, but now, all images are pixelized. So, I'm burning out my brain here to solve this issue and created a new Java project using a high-resolution PNG image.
The Problem: Doesn't matter how hard I try, the image is not getting resized to the jLabel size. Here is the code:
initComponents(); //Initialize the JFrame components...
ImageIcon iconWorkHours = new ImageIcon(getClass().getResource("/horkhours/WorkHours.png"));
this.lblLogo.setPreferredSize(new Dimension(135, 133));
Image imageWorkHours = iconWorkHours.getImage();
imageWorkHours.getScaledInstance(lblLogo.getWidth(), lblLogo.getHeight(), Image.SCALE_SMOOTH);
BufferedImage bufImgWH = new BufferedImage(lblLogo.getWidth(), lblLogo.getHeight(), BufferedImage.TYPE_INT_ARGB);
bufImgWH.getGraphics().drawImage(imageWorkHours, 0, 0, null);
this.lblLogo.setIcon(new ImageIcon(bufImgWH));
The result keeps looking like this:

How do I supply a Color Model to a .tiff image in Java when the image does not provide a Color Model to be used?

I am fairly new to Java, and so some of the classes like Color Model and JAI are not familiar to me. I have a tiff image I am reading into a program in Java. This is my read-in code:
BufferedImage img = null;
String input[] = {"LE70160412002112EDC00_sr_band5", "LE70160412002144EDC00_sr_band5"};
String filetype = "tif";
File file = new File(input[0] + "output.csv");
int numFiles = 0;
while (numFiles < 2){
if (filetype == "tif"){
FileSeekableStream stream = new FileSeekableStream(new File(input[numFiles] + ".tif"));
TIFFDecodeParam decodeParam = new TIFFDecodeParam();
decodeParam.setDecodePaletteAsShorts(true);
ParameterBlock params = new ParameterBlock();
params.add(stream);
RenderedOp image1 = JAI.create("tiff", params);
img = image1.getAsBufferedImage();
}
}
To be clear, other things are done further down in the while loop that I excluded such that the files are not overwriting each other. The problem I am having is not being able read in the file and get further into the loop. I had a tiff file that only had black and white pixels (0 or 255 red value for all pixels), and the code ran correctly because the file supplied the Color Model. The new tiff file I am trying to use is a greyscale picture (0 to 255 red value for all pixels), and every time I run the code it gives me the following error message:
Exception in thread "main" java.lang.IllegalArgumentException: No ColorModel is supplied and the image ColorModel is null.
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2500)
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
at Soda.DoStuff.doStuff(DoStuff.java:60)
at Soda.Driver.main(Driver.java:6)
My first instinct given the error message is to create a new Color Model. There may also be a better way to use JAI to import the tiff file such that it supplies the Color Model for the greyscale image. My end goal is to get the red value for each pixel in the image, so I do not want the data coming in to be altered from it's original form.
Any help I can get would be much appreciated. I am open to any suggestions.
EDIT:
Someone commented to try and use the getDefaultColorModel class inside the PlanarImage library, so I changed the bottom line of the code to this:
cm = PlanarImage.getDefaultColorModel(0, 1); //
img = image1.getAsBufferedImage(null, cm);
This also did not completely work but provided a different error message:
Exception in thread "main" java.lang.IllegalArgumentException: SampleModel and ColorModel parameters must be non-null.
at com.sun.media.jai.util.JDKWorkarounds.areCompatibleDataModels(JDKWorkarounds.java:363)
at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2505)
at Soda.DoStuff.doStuff(DoStuff.java:64)
at Soda.Driver.main(Driver.java:6)
I have extensively read through https://docs.oracle.com/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/PlanarImage.html to learn about the PlanarImage class, but I still cannot figure out how to properly format a ColorModel. (0,1) creates a color model with 8 pixel bits and 1 component. I also tried with (1,1) which creates a color model with 16 pixel bits and 1 component. Both provided the same error message above.
EDIT2: Unfortunately, I cannot link the image itself. However, I can tell you how I got the image from USGS. Forewarning, getting this image requires you to make a free account, and then afterwards you have to 'order' the picture from USGS, which is simply they need to process the request and give a download link for a zip file. It WILL take some time before you can actually access the picture. I also suggest making the account first because it will not let you start the image checkout process until you have an account made.
Using this link, http://earthexplorer.usgs.gov/, you pick a point on the map, then set the date range so that it ends on 12/31/2002 (the start date does not matter). The go to the Data set tab where under the "Landsat Archive" bullet, you will hit the checkbox for "Landsat Surface Reflectance - L7 ETM+". Hit OK on the dialogue, then hit "Results" at the bottom of the screen.
Once you have signed into your account and done this search, you should see many images on the left side of your screen with similar names to the filenames in my code above. You want to hit the shopping cart next to one of the images (You only need one, my whole project required 2, but for the purposes of reading in the file, that's not necessary). The shopping cart should turn green. Then in the top right corner there is a link to an Item Basket. You hit "Proceed to Checkout" and "Submit Order" on successive screens, and then you wait for an email from USGS.
Finally unzip the file, and you should have about 10 images. As you can see in the code, I am using the image with the name "sr_band5", but I believe any of the bands are greyscale which I cannot read in. Hope this can help.

Android native SDL glContext messed up picture

I'm trying to setup SDL2 native application with use of custom glContext.
Java part: this has by default Absolute layout which is deprecated. And i wonder if i need to use some kind of SurfaceView:
mSurface = new SDLSurface(getApplication());
mLayout = new RelativeLayout(this);
mLayout.setLeft(0);
mLayout.setTop(0);
mLayout.addView(mSurface);
setContentView(mLayout);
Next, i'm creating opengl context in my native code:
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2");
SDL_SetHint(SDL_HINT_RENDER_OPENGL_SHADERS, "1");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 0 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
m_glContext = SDL_GL_CreateContext(_window);
SDL_GL_MakeCurrent(_window, m_glContext);
Window is created like this:
m_mainWindow = SDL_CreateWindow("clovo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2048, 1536,
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_FULLSCREEN);
I thought the case may be in size of window, but after creation the size is fits the screen. Also, this code works fine in iOS.
I can't find a solution for a problem. Can't even find a problem. I'm new to Android, so maybe there something about glContext what i should know?
Found the problem.
It's occur when i'm using my own framebuffers and then setting it back to default.
In order to not set wrong buffer at my renderer initialization i'm storing default framebuffer
GLint default_buffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &default_buffer);
And then i can restore default buffer to draw to screen.

How to hide SWT Browser or run in headless mode?

I took the rendered page from the SWT Browser and exported it to an image. My problem is that I am not able to get it to export properly when the shell is not visible. How can I go about hiding the browser and have the image export properly?
I have tried setting shell.Visible() to false but that messes up the image export.
This is how I export the image (not sure if this is necessary to the question):
GC source = new GC (shell);
Image image = new Image(display, browser.getClientArea());
source.copyArea(image, 0, 0);
ImageLoader io = new ImageLoader ();
io.data = new ImageData[] { image.getImageData() };
File f = new File (currentDir+"/workpng.png");
io.save (f.getAbsolutePath(), SWT.IMAGE_PNG);
This might be impossible because the X server/Windows will throw away all rendering commands when the window isn't visible (no point in rendering what you can't see).
Also what is the client area of the browser in this case?
To make this work, you'll need to allow the shell to open be visible (i.e. not hidden by some other window). Tools like Jenkins use a plugin that starts an X session with Xvfb or Xvnc. After setting the env variable DISPLAY, all UI rendering goes to these sessions.

How do I get rid of the mouse cursor in full-screen exclusive mode?

I'm working on a simple 2D game engine in Java, and having no trouble with FSEM, buffer strategies, and so on; my issue is with the mouse cursor. In windowed mode, I can hide the mouse cursor, no problem, by using setCursor() from my JFrame to set a wholly-transparent cursor. However, after a call to device.setFullScreenWindow(this) to go into FSEM, the mouse cursor comes back, and subsequent calls to setCursor() to set it back to my blank cursor have no effect. Calling device.setFullScreenWindow(null) allows me to get rid of the cursor again - it's only while I'm in FSEM that I can't get rid of it.
I'm working under JDK 6, target platform is JDK 5+.
UPDATE: I've done some more testing, and it looks like this issue occurs under MacOS X 10.5 w/Java 6u7, but not under Windows XP SP3 with Java 6u7. So, it could possibly be a bug in the Mac version of the JVM.
Try Creating a custom invisible cursor:
Toolkit toolkit = Toolkit.getDefaultToolkit();
Point hotSpot = new Point(0,0);
BufferedImage cursorImage = new BufferedImage(1, 1, BufferedImage.TRANSLUCENT);
Cursor invisibleCursor = toolkit.createCustomCursor(cursorImage, hotSpot, "InvisibleCursor");
setCursor(invisibleCursor);
One developer found a way around it by creating a one pixel cursor out of a transparent GIF.
http://sevensoft.livejournal.com/23460.html
I know you tried that, but his is specifically addressing the issue of full-screen mode, exactly as you say, so perhaps there's something he's done that you haven't.
I think I've finally found the solution:
System.setProperty("apple.awt.fullscreenhidecursor","true");
This is an Apple-proprietary system property that hides the mouse cursor when an application is in full-screen mode. It's the only way I've found to fix it.
Here's what has been working for me:
Toolkit toolkit = Toolkit.getDefaultToolkit();
// get the smallest valid cursor size
Dimension dim = toolkit.getBestCursorSize(1, 1);
// create a new image of that size with an alpha channel
BufferedImage cursorImg = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
// get a Graphics2D object to draw to the image
Graphics2D g2d = cursorImg.createGraphics();
// set the background 'color' with 0 alpha and clear the image
g2d.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.0f));
g2d.clearRect(0, 0, dim.width, dim.height);
// dispose the Graphics2D object
g2d.dispose();
// now create your cursor using that transparent image
hiddenCursor = toolkit.createCustomCursor(cursorImg, new Point(0,0), "hiddenCursor");
Granted, I haven't tested it on Mac (yet), only Windows. But when I used the common methods I was getting the cursor as black box, so I use the code above the create a transparent box and set it as the cursor instead. Of course you have to use the setCursor method on an AWT object (such as your app's Frame) to set this hiddenCursor. Here is my hideMouse method ('fr' is my Frame):
public void hideMouse(boolean hide) {
if(hide) {
fr.setCursor(hiddenCursor);
} else {
fr.setCursor(Cursor.getDefaultCursor());
}
}
I don't know if this knowledge applies but in a old VB6 app I had the same problem and I got rid of it moving the cursor out of the screen giving it some very large values.
Hope it helps.
If you're running only on Windows, it looks like you'll need to call ShowCursor(FALSE) through JNI. At least, to make the cursor hide complete.
Here's some code which creates the 1x1 cursor. It works for me, though I still get a 1x1 cursor.
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension dim = toolkit.getBestCursorSize(1,1);
transCursor = toolkit.createCustomCursor(gc.createCompatibleImage(dim.width, dim.height),
new Point(0, 0), "transCursor");
((Component)mainFrame).setCursor(transCursor);
Specifically for your Mac problem, through JNI you could use the following:
Quartz Display Services Reference - CGDisplayHideCursor

Categories

Resources