Slick2d and AWT fonts rendering weirdly - java

I am currently working on a Slick2D project and fonts are really bothering me. I figured out how to loas them properly (I think ?) but it's not rendering that nice on screen.
This is what I would like to get, and this is what I actually get.
Also, here is the corresponding code for loading the font :
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.util.ResourceLoader;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
public final class SlickGraphicsConstants {
public static final TrueTypeFont BIG_FONT = loadFont("freestylescript.ttf", Font.PLAIN, 50);
private static TrueTypeFont loadFont(String name, int style, int size) {
InputStream is = ResourceLoader.getResourceAsStream(name);
try {
Font f = Font.createFont(Font.TRUETYPE_FONT, is);
f = f.deriveFont(style, (float) size);
return new TrueTypeFont(f, true);
} catch (FontFormatException | IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
Could anyone help me for this one please ?

Related

How to refresh/reload an image in Swing GUI as the real image file changes?

I am trying to implement Remote FrameBuffer Protocol using Java socket programming.
I have a server side program that takes screenshot of the entire screen using robot and store it in BufferedImage .Then I converted it into a byte array and sending it to the client .
Objective :
To display the entire screen of the server side machine in a Swing GUI of the client side.
Problem i am facing :
i am able to send the image in bytes from server and receive it from the server by the client (client.java) and convert it into a jpg image (output.jpg) using ImageIO and put that image in a Swing frame.
But i am able to see the first image in the Swing and whenever the image gets updated ,the image in the Swing is not updating or refreshing .
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
client.java
package remoteclient;
import java.lang.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class client {
public static void main(String args[])throws Exception{
Socket s=new Socket("localhost",5900);
DataInputStream din=new DataInputStream(s.getInputStream());
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int width=0,height=0;
try {
width = din.readInt(); //getting width and height from server thru socket.
height = din.readInt();
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame("Client");
JLabel label = new JLabel();
f.setSize(width, height);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
boolean continueLoop = true;
while(continueLoop)
{
try {
int len = din.readInt();
byte[] imageInByte = new byte[len];
System.out.println(len);
din.readFully(imageInByte);
System.out.println(imageInByte);
ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte);
BufferedImage bImage2 = ImageIO.read(bis);
// Image im1 = bImage2.getScaledInstance(width,height, Image.SCALE_SMOOTH);
ImageIO.write(bImage2, "jpg", new File("output.jpg") );
bImage2 = ImageIO.read(new File("output.jpg"));
label.setIcon(new ImageIcon(im1));
ImageIcon icon = new ImageIcon(bImage2);
icon.getImage().flush();
label.setIcon( icon );
f.getContentPane().add(label, BorderLayout.CENTER);
f.pack();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
Updated code with comments about demo code that should be removed from your working code:
Here's an example, using default UIManager icons, and SwingWorker, as noted in the comments to the original posting. You would instead use images from your server connection.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingLabelWithUpdatedImage {
public static void main(String args[]) throws Exception {
final JLabel label = new JLabel("", SwingConstants.CENTER);
final JFrame frame = new JFrame("Client");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label, BorderLayout.CENTER);
final Dimension preferredSize = new Dimension(200, 100);
frame.setPreferredSize(preferredSize);
frame.setVisible(true);
frame.pack();
final ImageUpdateWorker task = new ImageUpdateWorker(label);
task.execute();
}
public static class ImageUpdateWorker extends SwingWorker<Void, IconInfo> {
// iconInfoList is not need in your code. It's here so I can
// supply a dummy set of icons to demonstrate UI updates.
final List<IconInfo> iconInfoList;
private JLabel label;
ImageUpdateWorker(JLabel label) {
this.label = label;
// Delete this in your code
this.iconInfoList = initIconInfoList();
}
#Override
public Void doInBackground() {
boolean isTrue = true;
while (isTrue) {
// Put your socket code to read the next icon from a server.
// You don't need to do the ImageIO.write(), ImageIO.read() dance,
// unless you must save the icon to disk. In that case, you don't need
// to read it back in.
// Here, I just rotate the iconInfoList to make it
// appear as though a new icon was received.
// Your code will not have any need to do this.
Collections.rotate(iconInfoList, -1);
// Just publish the icon you create from the image
// you receive from your remote server.
publish(iconInfoList.get(0));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void process(List<IconInfo> icons) {
// You might check for an empty list.
// #kleopatra's suggestion to get the last icon is correct.
// See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/interim.html
IconInfo iconInfo = icons.get(icons.size() - 1);
label.setIcon(iconInfo.icon);
// Your code will not do this
label.setText(iconInfo.name);
// You can get the icon dimensions just from the icon,
// so you don't really need the IconInfo class.
label.setSize(iconInfo.dimension);
}
/** Demo code only. It doesn't belong in your working code.
*/
protected List<IconInfo> initIconInfoList() {
// Just a quick way to get some icons; don't need to
// fetch from a server just to demonstrate how to
// refresh the UI.
List<IconInfo> iconInfoList = UIManager.getDefaults().keySet().stream()
.filter(this::isIconKey)
.map(IconInfo::new)
.filter(iconInfo -> iconInfo.icon != null)
.collect(Collectors.toList());
return iconInfoList;
}
/** Demo code only. It doesn't belong in your working code.
*/
protected boolean isIconKey(Object key) {
return String.class.isAssignableFrom(key.getClass())
&& ((String) key).toLowerCase().contains("icon");
}
}
/** This is just a convenience to convey
* the icon and its UIManager key (i.e., name).
* Your remote server doesn't supply a name,
* so you don't really need this class.
* It's just to make the demo more expressive.
*/
public static class IconInfo {
final private String name;
final private Icon icon;
final private Dimension dimension;
IconInfo(Object name) {
this.name = name.toString();
icon = UIManager.getIcon(name);
dimension = icon == null
? new Dimension(32, 32)
: new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
}
}

JTextPane Line Count Including Icons and Components

I've recently been experimenting with the user of JTextPanes for an upcoming project I'll be working on, there have been various posts online detailing how to go about counting the number of lines within the text pane however the solutions I found all seem to fail when inserting Icons or Components into the text pane's document.
The solution I found that worked for plain text was this one (with the solution implemented of course): BadLocationException when using Utilities.getRowStart On hit of Enter key
However once I try to insert a Component (JLabel) or a plain Icon for that matter, the getRowStart() method from Utilities throws a null pointer exception. What I find unusual about this is the Java Doc states that "...This is represented in the associated document as an attribute of one character of content. ", so I assumed it would treat it as any other character but it seems this is not the case.
I've included a code example to replicate the problem if anyone would like to try it. I have a feeling that it just simply isn't possible, which would be a shame.
import java.awt.Dimension;
import java.awt.Image;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;
public class Test{
private JFrame frame;
private JTextPane textPane;
private Image img;
private URL imgURL;
public Test(){
frame = new JFrame();
frame.setSize(new Dimension(500,300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textPane = new JTextPane();
try {
imgURL = new URL("http://www.freeiconspng.com/uploads/floppy-save-icon--23.png");
img = ImageIO.read(imgURL);
JLabel label = new JLabel(new ImageIcon(img.getScaledInstance(10, 10, Image.SCALE_SMOOTH)));
textPane.insertComponent(label);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
frame.getContentPane().add(textPane);
frame.setVisible(true);
}
public JTextPane getTextPane(){
return this.textPane;
}
public int getLineCount(){
int totalCharacters = textPane.getDocument().getLength();
int lineCount = (totalCharacters == 0) ? 1 : 0;
try {
int offset = totalCharacters;
while (offset > 0) {
offset = Utilities.getRowStart(textPane, offset) - 1;
lineCount++;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return lineCount;
}
public static void main(String[] args){
Test t = new Test();
t.getLineCount();
}
}
The problem was solved after the following comment:
It doesn't throw any exception for me once I wrap the content inside
your main method inside a EventQueue.invokeLater() call. I.e.:
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Test t = new Test();
t.getLineCount();
}
});

How to read a GIF with Java's ImageIO and preserve the animation?

I'm working on a project and the goal is to have all images read with ImageIO. This seems to work for everything except GIF images (which display as a static image of the initial frame). I have seen other answers on Stack Overflow and from a thread on the Oracle forums but most require using Java's File class which I can't access due to the program's SecurityManager. I've been able to break the GIF down into an Image array and edit the metadata, but after stitching everything back together I can only display a single image.
Below is a SSCCE for the program:
import java.awt.Image;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GifRenderer {
public static void main(String[] args) throws Exception {
Image image = null;
byte[] imageByteArray = null;
try {
String location = "http://i.imgur.com/Ejh5gJa.gif";
imageByteArray = createByteArray(location);
// This works, but I'm trying to use ImageIO
//image = Toolkit.getDefaultToolkit().createImage(imageByteArray);
InputStream in = new ByteArrayInputStream(imageByteArray);
image = ImageIO.read(in);
} catch (IOException e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.setSize(300, 300);
JLabel label = new JLabel(new ImageIcon(image));
frame.add(label);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Constraint: This method simulates how the image is originally received
private static byte[] createByteArray(String urlString) throws IOException {
URL url = new URL(urlString);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096];
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
} catch (IOException e) {
e.printStackTrace ();
} finally {
if (is != null) { is.close(); }
}
return baos.toByteArray();
}
}
Some constraints worth mentioning that might not be clear:
The image is originally received as a byte array
The image should be read by ImageIO
The final result should be an Image object
The File class can't be accessed
Given these constraints is there still a way to use ImageIO to display the GIF the same way Toolkit.getDefaultToolkit().createImage() would display the image?

Questions about JavaCV example

HI guys I am experimenting with the use of JavaCV as I want to get to know how it works in order to include it's functionality in a project I have in mind. I have downloaded and set up OpenCV just like what the instructions said and I also have downloaded form bytedeco the JavaCV 1.0 jars that I need to include in my project.
I have started with an example program I found online that basically grabs and save images from a webcam. The code I have written is the following:
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.VideoInputFrameGrabber;
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.*;
public class GrabberShow implements Runnable{
IplImage image;
CanvasFrame canvas = new CanvasFrame("Web Cam");
public GrabberShow(){
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
public void run(){
FrameGrabber grabber = new VideoInputFrameGrabber(0);
int i = 0;
try{
grabber.start();
IplImage img;
while(true){
img = grabber.grab();
if(img != null){
cvFlip(img, img, 1);
cvSaveImage((i++) + "-aa.img", img);
canvas.showImage(img);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
GrabberShow gs = new GrabberShow();
Thread th = new Thread(gs);
th.start();
}
}
This is a very straightforward and easy example. The problem I am experiencing can be found on the following lines:
img = grabber.grab();
and
canvas.showImage(img);
The problem I face is a Type Mismatch "Cannot convert from Frame to opencv_core.LplImage".
I have tried searching for this online but I was unable to locate a good answer about this. What I did found was the same example only. Does anyone have any ideas about this?
Need to stress out that this the first time I use openCV with Java. I have used it in the past to make and object tracking program but this was done with native openCV and using Python.
The code you have looks like it would probably work for javacv version 0.10. For 1.0 theFrameGrabber's returnFrame objects that then need to be converted to IplImage objects using a OpenCVFrameConverter.ToIplImage.
import org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvFlip;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.VideoInputFrameGrabber;
...
public class GrabberShow implements Runnable {
CanvasFrame canvas = new CanvasFrame("Web Cam");
public GrabberShow() {
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
public void run() {
FrameGrabber grabber = new VideoInputFrameGrabber(0);
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
int i = 0;
try {
grabber.start();
IplImage img;
while (true) {
Frame frame = grabber.grab();
img = converter.convert(frame);
if (img != null) {
cvFlip(img, img, 1);
cvSaveImage((i++) + "-aa.img", img);
canvas.showImage(frame);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
GrabberShow gs = new GrabberShow();
Thread th = new Thread(gs);
th.start();
}
}

Chroma key effect in Java

I also need to find a library which allows to implement the "chroma key" effect in Java. The video contains some part in green color, which is replaced which a picture during the rendering in order to create a new video.
I am linking my question with a similar question which was already answered but with uncomplete answer (Looking for Chromakey library in Java). Could you please specify how did you do to have something up and working so quickly? I have been unsuccessful for some months fighting against the same issue.
c00kiemon5ter pointed several resources:
JavaCV
JAI (Java Advanced Imaging API)
Java Image Processing Cookbook
Which one did work for you?
JavaCV contains lots of methods to process video streams.
This code should get you started: http://tech.groups.yahoo.com/group/OpenCV/message/59118 but it's probably too slow in Java. Try this approach:
Create a filter which turns all the green pixels into a mask (look for things that "select by color").
Use the mask to copy the background image into the video.
I would like to contribute with a piece of code which gave me quite good results. I wonder if I used the classes and methods that Aaron Digulla suggested.
Please note that in this case my video has black background, that is why I am replacing the black color with the background image. I expect to obtain better results when I can edit the video to have green background, because black color is more likely to be used within the video main characters and replacing wrong pixels causes a quite awful effect.
--
package transparentvideo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.media.Manager;
import javax.media.Player;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TransparentVideo
{
Player mediaPlayer;
JFrame invisibleFrame;
JFrame visibleFrame;
JLabel videoScreen;
JPanel offScreenVideo;
String backgroundImageFile="nature.jpg";
String videoFile="girl.mov";
public TransparentVideo()
{
invisibleFrame = new JFrame();
invisibleFrame.setSize(400, 400);
Container container=invisibleFrame.getContentPane();
offScreenVideo = getvidComp();
offScreenVideo.setPreferredSize(container.getSize());
offScreenVideo.setVisible(true);
container.add(offScreenVideo);
invisibleFrame.setVisible(true);
visibleFrame=new JFrame();
visibleFrame.setSize(container.getSize());
visibleFrame.setLocationRelativeTo(null);
videoScreen = new JLabel();
visibleFrame.getContentPane().add(videoScreen);
visibleFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
visibleFrame.setVisible(true);
invisibleFrame.setVisible(false);
try
{
while(true)
{
if(mediaPlayer.getState()==Player.Started)
reDraw();
Thread.sleep(100);
}
}
catch (Exception ex)
{
System.out.println(ex.getMessage());
}
}
public void reDraw()
{
BufferedImage bi=new BufferedImage(videoScreen.getWidth(), videoScreen.getHeight(),
BufferedImage.TYPE_INT_ARGB);
bi.getGraphics().drawImage(new ImageIcon(backgroundImageFile).getImage(), 0 , 0 ,
videoScreen.getWidth(), videoScreen.getHeight(), null);
BufferedImage screenShot = createImage((JComponent) offScreenVideo,
new Rectangle(invisibleFrame.getBounds()));
Image im = makeColorTransparent(new ImageIcon(screenShot).getImage(), Color.BLACK);
bi.getGraphics().drawImage(im, 0 ,0 , videoScreen.getWidth(), videoScreen.getHeight(), null);
videoScreen.setIcon(new ImageIcon(bi));
}
public static BufferedImage createImage(Component component, Rectangle region)
{
if (!component.isDisplayable()) {
Dimension d = component.getSize();
if (d.width == 0 || d.height == 0) {
d = component.getPreferredSize();
component.setSize(d);
}
layoutComponent(component);
}
BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
if (!component.isOpaque())
{
g2d.setColor(component.getBackground());
g2d.fillRect(region.x, region.y, region.width, region.height);
}
g2d.translate(-region.x, -region.y);
component.paint(g2d);
g2d.dispose();
return image;
}
public static void layoutComponent(Component component)
{
synchronized (component.getTreeLock())
{
component.doLayout();
if (component instanceof Container)
{
for (Component child : ((Container) component).getComponents())
{
layoutComponent(child);
}
}
}
}
public JPanel getvidComp()
{
Manager.setHint(Manager.LIGHTWEIGHT_RENDERER,true);
try
{
mediaPlayer = Manager.createRealizedPlayer(new File(videoFile).toURL());
mediaPlayer.realize();
mediaPlayer.prefetch();
JPanel video=new JPanel(new BorderLayout());
video.add(mediaPlayer.getVisualComponent()) ;
mediaPlayer.start();
return video;
}
catch( Exception d)
{
return null;
}
}
public static Image makeColorTransparent( Image im, final Color color)
{
ImageFilter filter = new RGBImageFilter()
{
public int markerRGB = color.getRGB() | 0xFF000000;
public final int filterRGB(int x, int y, int rgb)
{
Color c=new Color(rgb);
int red=c.getRed();
int green=c.getGreen();
int blue=c.getBlue();
//if(red<140 && green<140 && blue<140)
{
int alpha=Math.max(Math.max(red , green), Math.max(green, blue))*3;
c=new Color(red , green , blue , alpha>255 ?255 :alpha );
}
return c.getRGB();
}
};
ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
return Toolkit.getDefaultToolkit().createImage(ip);
}
public static void main(String[] args) {
new TransparentVideo();
}
}

Categories