JLabel Icon not showing after change - java

I tried looking up this question, but most of the answers are that the file path is wrong, but that's most likely not the case. The file works the 1st time I use it.
I am making a battleships game, and use JLabels to show ships on map. I want to make a button to rotate ship from horizontal to vertical but it's icon disappears when I try to change it.
When I run this constructor code:
public Ship(int size, String direction, boolean active, Client c,
ClientGUI cg) {
this.c = c;
this.cg = cg;
health = size;
this.active = active;
this.direction = direction;
file = "img/" + Integer.toString(health) + direction + ".png"; // String
try {
System.out.println(file);
tx = ImageIO.read(new File(file)); // BufferedImage
} catch (IOException e) {
e.printStackTrace();
}
texture = new JLabel(new ImageIcon(tx));
if (direction.equals("v"))
texture.setBounds(0, 0, 40, 40 * size);
else
texture.setBounds(0, 0, 40 * size, 40);
texture.setVisible(true);
}
everything works and I can see the image.
But then I try to rotate it, using pretty much the same code:
void rotate() {
if (direction.equals("h")) {
direction = "v";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setBounds(0,0,40, 40 * size);
texture.setIcon(new ImageIcon(tx));
} else {
direction = "h";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setIcon(new ImageIcon(tx));
texture.setBounds(0,0,40 * size, 40);
}
cg.repaint(); // not sure if I need to do this
}
and it disappears...
I tried placing two ships, one is rotated, it's just missing the JLabel or the icon on JLabel.

If you update the JLabel texture by calling a method which changes it's state, it may or may not be updated immediately unless you call texture.repaint() or texture.paintAll(texture.getGraphics()), or some similar method.
Also, I would look into using a LayoutManager for whatever upper level component you are using to hold your grid of JLabels. If you use a GridLayout of your game board and either:
set the JLabel's preferred size with texture.setPreferredSize(Dimension) and call frame.pack() once when setting up your game; or
set the JLabel's size with label.setSize(Dimension) once and don't pack your JFrame
You will only need to set the size of the JLabel once, not every time you set a new ImageIcon to the label. Because, Ideally your game shouldn't be doing any extra work that it doesn't have to so it performs faster.
I would also recommend maintaining every possible ImageIcon as static fields in your class, rather than accessing them from the file every time. That way, you read them once from a static initializing method, which then reach ship can directly access when changing the direction.

I want to make a button to rotate ship from horizontal to vertical
You can use the Rotated Icon class to do the rotation for you.

Related

Cropping BufferedImage For Use in Xuggle encodeVideo

I have an application to capture video of the screen and save to a file. I give the user the ability to pick between 480, 720, and "Full Screen" video sizes. A 480 will record in a small box on the screen, 720 will record in a larger box, and of course, "Full Screen" will record in an even larger box. However, this full screen box is NOT the actual screen resolution. It is the app window size, which happens to be around 1700x800. The Video Tool works perfectly for the 480 and 720 options, and will also work if "Full Screen" is overwridden to be the entire screen of 1920x1080.
My question: Are only certain sizes allowed? Does it have to fit a certain aspect ratio, or be an "acceptable" resolution? My code, below, is modified from the xuggle CaptureScreenToFile.java file (the location of the problem is noted by comments):
public void run() {
try {
String parent = "Videos";
String outFile = parent + "example" + ".mp4";
file = new File(outFile);
// This is the robot for taking a snapshot of the screen. It's part of Java AWT
final Robot robot = new Robot();
final Rectangle customResolution = where; //defined resolution (custom record size - in this case, 1696x813)
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Rectangle fullResolution = new Rectangle(toolkit.getScreenSize()); //full resolution (1920x1080)
// First, let's make a IMediaWriter to write the file.
final IMediaWriter writer = ToolFactory.makeWriter(outFile);
writer.setForceInterleave(false);
// We tell it we're going to add one video stream, with id 0,
// at position 0, and that it will have a fixed frame rate of
// FRAME_RATE.
writer.addVideoStream(0, 0, FRAME_RATE, customResolution.width, customResolution.height); //if I use fullResolution, it works just fine - but captures more of the screen than I want.
// Now, we're going to loop
long startTime = System.nanoTime();
while (recording) {
// take the screen shot
BufferedImage screen = robot.createScreenCapture(fullResolution); //tried capturing using customResolution, but did not work. Instead, this captures full screen, then tries to trim it below (also does not work).
// convert to the right image type
BufferedImage bgrScreen = convertToType(screen, BufferedImage.TYPE_3BYTE_BGR); //Do I need to convert after trimming?
BufferedImage trimmedScreen = bgrScreen.getSubimage((int)customResolution.getX(), (int)customResolution.getY(), (int)customResolution.getWidth(), (int)customResolution.getHeight());
// encode the image
try{
//~~~~Problem is this line of code!~~~~ Error noted below.
writer.encodeVideo(0, trimmedScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); //tried using trimmedScreen and bgrScreen
} catch (Exception e) {
e.printStackTrace();
}
// sleep for framerate milliseconds
Thread.sleep((long) (1000 / FRAME_RATE.getDouble()));
}
// Finally we tell the writer to close and write the trailer if
// needed
writer.close();
} catch (Throwable e) {
System.err.println("an error occurred: " + e.getMessage());
}
}
public static BufferedImage convertToType(BufferedImage sourceImage, int targetType) {
BufferedImage image;
// if the source image is already the target type, return the source image
if (sourceImage.getType() == targetType)
image = sourceImage;
// otherwise create a new image of the target type and draw the new image
else {
image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), targetType);
image.getGraphics().drawImage(sourceImage, 0, 0, null);
}
return image;
}
Error:
java.lang.RuntimeException: could not open stream com.xuggle.xuggler.IStream#2834912[index:0;id:0;streamcoder:com.xuggle.xuggler.IStreamCoder#2992432[codec=com.xuggle.xuggler.ICodec#2930320[type=CODEC_TYPE_VIDEO;id=CODEC_ID_H264;name=libx264;];time base=1/50;frame rate=0/0;pixel type=YUV420P;width=1696;height=813;];framerate:0/0;timebase:1/90000;direction:OUTBOUND;]: Operation not permitted
Note: The file is successfully created, but has size of zero, and cannot be opened by Windows Media Player, with the following error text:
Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.
Sorry for the wordy question. I'm interested in learning WHAT and WHY, not just a solution. So if anyone can explain why it isn't working, or point me towards material to help, I'd appreciate it. Thanks!
Try to have the dimension even numbers 1696x812

JTree set transparency of Icon

I want to give a visual indication that a node has been transferred to clipboard with a "Cut" action. One intuitive look used by at least one proprietary OS is to make this the same image, but slightly transparent.
I'd quite like to know whether it is in fact possible somehow to use the icons used by the Windoze OS (W7)... but I'd be more intrigued if it were possible to interfere in some way (in the renderer) with the Icon, by somehow messing with the Graphics object used by Icon.paintIcon() ... just for a given node, obviously. I'm not clear where an Icon goes hunting for the Graphics object it uses when it is painted ... any enlightenment would be most welcome.
later
Many thanks to MadProgrammer. Spotted this possibility as a way of extracting obfuscated visuals with a view to their manipulation: https://home.java.net/node/674913 ... it works. Putting code here in case of broken link...
public class IconTest {
public static void main(String[] args) {
Icon leafIcon = UIManager.getIcon("Tree.leafIcon");
// ... ("Tree.closedIcon") ("Tree.openIcon")
BufferedImage img1 = new BufferedImage(leafIcon.getIconWidth(),
leafIcon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = img1.createGraphics();
g.drawImage(((ImageIcon) leafIcon).getImage(), 0, 0, null);
g.dispose();
try {
ImageIO.write(img1, "PNG", new File("leafIcon.png"));
} catch (IOException e) {
System.out.println("Error writing to file leafIcon" + ", e = " + e);
System.exit(0);
}
}
}
Then use MadProgrammer's technique to alter the image in any way one likes: change transparency, colour, etc. Great stuff.
I'd quite like to know whether it is in fact possible somehow to use the icons used by the Windoze OS (W7)
FileSystemView#getSystemIcon will give you the OS's icon representation of a given File, for example...
Icon icon = FileSystemView.getFileSystemView().getSystemIcon(new File("ThatImportantDoc.docx"));
I want to give a visual indication that a node has been transferred to clipboard with a "Cut" action. One intuitive look used by at least one proprietary OS is to make this the same image, but slightly transparent.
You need to paint the previous Icon to BufferedImage, which has had a AlphaComposite applied to it, for example
BufferedImage img = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
You then need to wrap the resulting BufferedImage in a ImageIcon, which allows you to pass the image as a Icon to the rest of the API.
JPanel panel = new JPanel();
panel.add(new JLabel(icon));
panel.add(new JLabel(new ImageIcon(img)));
JOptionPane.showMessageDialog(null, panel, "Icon", JOptionPane.PLAIN_MESSAGE);
To get this to finally work, you will need to provide a TreeCellRenderer capable of supporting your functionality. Have a look at How to Use Trees for more details
Just one tweak enabling me to do what I mainly wanted to do: get the UI images "from the source code".
public class IconTest {
public static void main(String[] args) {
// OS folder icon
// Icon icon = FileSystemView.getFileSystemView().getSystemIcon(new File("."));
// proprietary word processor
// Icon icon = FileSystemView.getFileSystemView().getSystemIcon(new File("Doc1.docx"));
// taken from PNG file
// Icon icon = new ImageIcon( "openIcon.png" );
// taken directly from the Java images held somewhere (?) in the code
Icon icon = UIManager.getIcon("Tree.leafIcon");
// Icon icon = UIManager.getIcon("Tree.openIcon");
// ... ("Tree.closedIcon") ("Tree.openIcon")
BufferedImage img = new BufferedImage( icon.getIconWidth(),
icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver.derive( 0.5f));
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
JPanel panel = new JPanel();
panel.add(new JLabel(icon));
panel.add(new JLabel(new ImageIcon(img)));
JOptionPane.showMessageDialog(null, panel, "Icon", JOptionPane.PLAIN_MESSAGE);
}
}

How to get the color of a pixel in a Java applet to produce a map?

I am working with a Java to create a small applet. I am interested if there is a way I can "scan" an image to get the color values of a certain pixel. I would prefer to not have to display the image on the screen, but if you find that is the only way, please tell me. I would ideally like to be able to have my applet scan an image file and create an image on the screen according to the image. Please try to keep the answers a little bit simple, as I am still getting used to all of the technical terms.
Thanks,
~Rane
What I have so far:
import java.applet.Applet;
public class LoadGuideImage {
Applet applet;
public LoadGuideImage(Applet applet){
this.applet = applet;
}
public String getPixelColor(String pathToImage, int Xpix, int Ypix){
int redC = 0;
int greenC = 0;
int blueC = 0;
//Get Pixel colors here and save to ints
return redC + " " + greenC + " " + blueC;
}
}
Are you suggesting something like this 'the other guy'?:
BufferedImage img = (BufferedImage) getImage(pathToImage);
System.out.println("Color: " + img.getRGB(3, 3));
getImage method:
public Image getImage(String path) {
Image img;
URL url = null;
try {
url = applet.getDocumentBase();
} catch (Exception e){
// TODO: handle exception
}
img = applet.getImage(url, path);
return img;
}
nice name by the way. So I was in the same position a while ago.
use this for your get image method, just tweak it and use it to benefit you:
public class ImageLoader {
public BufferedImage load(String path){
try {
return ImageIO.read(getClass().getResource(path));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
I have a been making a game that uses individual pixels to load those pixels and then put tiles where certain pixels are located in the map. If you would like to take my code snippet from there let me know and ill hook you up :P

TYPE_INT_ARGB images are not shown correctly

I am creating an image with random pixels and an integer in the middle. However, the color just doesn't seem right.
As you can see, the color is not right. Here's the code
private void createImage(){
try{
String key = "3534";
BufferedImage thumbnail = new BufferedImage(300, 300,BufferedImage.TYPE_INT_ARGB);
Graphics graphics = thumbnail.getGraphics();
graphics.setFont(new Font(null, Font.BOLD, 100));
randomizePixels(graphics);
graphics.setColor(new Color(255,255,255,255));
graphics.drawString(key, thumbnail.getWidth()/2, thumbnail.getHeight()/2);
ImageIO.write(thumbnail,"jpg",new File("c:\\image1.jpg"));
}catch (Exception e){
e.printStackTrace();
}
}
private void randomizePixels(Graphics graphics){
Random random = new Random();
for(int k=0;k<300;k++){
for(int j=0;j<300;j++){
graphics.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat(), random.nextFloat()));
graphics.fillRect(k,j,1,1);
}
}
}
As you can see, I've set the color of number (255,255,255,255), which is white with 100% opacity.
Is there anything that I must be doing wrong? How can I get my number to be white?
First of all, I'm getting slightly different result when running your code. The dots should have random color, not all red as you are posting.
I'm not sure what exactly you want to accomplish, but I guess you want a random noise and put an overlay with partially visible text. I'd start with using png as an output format. I'm not sure how the jpg handles transparency.
So you should first paint the randomized pixels with solid color and then write over that the text.
You need to move setting the color after you randomize the pixels like this:
private static void createImage(){
try{
String key = "3534";
BufferedImage thumbnail = new BufferedImage(300, 300,BufferedImage.TYPE_INT_ARGB);
Graphics graphics = thumbnail.getGraphics();
randomizePixels(graphics);
graphics.setColor(new Color(255, 255, 255 ,255));
graphics.setFont(new Font(null, Font.BOLD, 100));
graphics.drawString(key, thumbnail.getWidth()/2, thumbnail.getHeight()/2);
ImageIO.write(thumbnail, "png", new File("image1.png"));
}catch (Exception e){
e.printStackTrace();
}
}
private static void randomizePixels(Graphics graphics){
Random random = new Random();
for(int k=0;k<300;k++){
for(int j=0;j<300;j++){
graphics.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat(),1));
graphics.fillRect(k,j,1,1);
}
}
}
After that, the text will get the color you want / with "hidden" text

Java BufferedImage alternatives

I am trying to implement a simple class that will allow a user to crop an image to be used for their profile picture. This is a java web application.
I have done some searching and found that java.awt has a BufferedImage class, and this appears (at first glance) to be perfect for what I need. However, it seems that there is a bug in this (or perhaps java, as I have seen suggested) that means that the cropping does not always work correctly.
Here is the code I am using to try to crop my image:
BufferedImage profileImage = getProfileImage(form, modelMap);
if (profileImage != null) {
BufferedImage croppedImage = profileImage
.getSubimage(form.getStartX(), form.getStartY(), form.getWidth(), form.getHeight());
System.err.println(form.getStartX());
System.err.println(form.getStartY());
File finalProfileImage = new File(form.getProfileImage());
try {
String imageType = getImageType(form.getProfileImage());
ImageIO.write(croppedImage, imageType, finalProfileImage);
}
catch (Exception e) {
logger.error("Unable to write cropped image", e);
}
}
return modelAndView;
}
protected BufferedImage getProfileImage(CropImageForm form, Map<String, Object> modelMap) {
String profileImageFileName = form.getProfileImage();
if (validImage(profileImageFileName) && imageExists(profileImageFileName)) {
BufferedImage image = null;
try {
image = getCroppableImage(form, ImageIO.read(new File(profileImageFileName)), modelMap);
}
catch (IOException e) {
logger.error("Unable to crop image, could not read profile image: [" + profileImageFileName + "]");
modelMap.put("errorMessage", "Unable to crop image. Please try again");
return null;
}
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Please try again.");
return null;
}
private boolean imageExists(String profileImageFileName) {
return new File(profileImageFileName).exists();
}
private BufferedImage getCroppableImage(CropImageForm form, BufferedImage image, Map<String, Object> modelMap) {
int cropHeight = form.getHeight();
int cropWidth = form.getWidth();
if (cropHeight <= image.getHeight() && cropWidth <= image.getWidth()) {
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Crop size larger than image.");
return null;
}
private boolean validImage(String profileImageFileName) {
String extension = getImageType(profileImageFileName);
return (extension.equals("jpg") || extension.equals("gif") || extension.equals("png"));
}
private String getImageType(String profileImageFileName) {
int indexOfSeparator = profileImageFileName.lastIndexOf(".");
return profileImageFileName.substring(indexOfSeparator + 1);
}
The form referred to in this code snippet is a simple POJO which contains integer values of the upper left corner to start cropping (startX and startY) and the width and height to make the new image.
What I end up with, however, is a cropped image that always starts at 0,0 rather than the startX and startY position. I have inspected the code to make sure the proper values are being passed in to the getSubimage method, and they appear to be.
Are there simple alternatives to using BufferedImage for cropping an image. I have taken a brief look at JAI. I would rather add a jar to my application than update the jdk installed on all of the production boxes, as well as any development/testing servers and local workstations.
My criteria for selecting an alternative are:
1) simple to use to crop an image as this is all I will be using it for
2) if not built into java or spring, the jar should be small and easily deployable in a web-app
Any suggestions?
Note: The comment above that there is an issue with bufferedImage or Java was something I saw in this posting: Guidance on the BufferedImage.getSubimage(int x, int y, int w, int h) method?
I have used getSubimage() numerous times before without any problems. Have you added a System.out.println(form.getStartX() + " " + form.getStartY()) before that call to make sure they're not both 0?
Also, are you at least getting an image that is form.getWidth() x form.getHeight()?
Do make sure you are not modifying/disposing profileImage in any way since the returned BufferedImage shares the same data array as the parent.
The best way is to just simply draw it across if you want a completely new and independent BufferedImage:
BufferedImage croppedImage = new BufferedImage(form.getWidth(),form.getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics g = croppedImage.getGraphics();
g.drawImage(profileImage,0,0,form.getWidth(),form.getHeight(),form.getStartX(),form.getStartY(),form.getWidth(),form.getHeight(),null);
g.dispose();
You can do it in this manner as well (code is not 100% tested as I adopted for example from an existing app i did):
import javax.imageio.*;
import java.awt.image.*;
import java.awt.geom.*;
...
BufferedImage img = ImageIO.read(imageStream);
...
/*
* w = image width, h = image height, l = crop left, t = crop top
*/
ColorModel dstCM = img.getColorModel();
BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(w, h), dstCM.isAlphaPremultiplied(), null);
Graphics2D g = dst.createGraphics();
g.drawRenderedImage(img, AffineTransform.getTranslateInstance(-l,-t));
g.dispose();
java.io.File outputfile = new java.io.File(sessionScope.get('absolutePath') + java.io.File.separator + sessionScope.get('lastUpload'));
ImageIO.write(dst, 'png', outputfile);
Thanks for all who replied. It turns out that the problem was not in the cropping code at all.
When I displayed the image to be cropped, I resized it to fit into my layout nicely, then used a javascript cropping tool to figure out the coordinates to crop.
Since I had resized my image, but didn't take the resizing into account when I was determining the cropping coordinates, I ended up with coordinates that appeared to coincide with the top left corner.
I have changed the display to no longer resize the image, and now cropping is working beautifully.

Categories