Hello I'm trying to add an Image that I have on my desktop to my JFrame that I have created i have imported all the necessary functions and the correct variables the only trouble i have is with Image observer I set my x and y values for my image but it causes an error in my drawImage component and it asks for an Image observer which i don't know what it is and if i auto fill something my Image doesn't appear on my JFrame. If one of you can look at my code or answer what an Image observer does i would be greatly appreciated
public class Window2 extends JPanel {
// Image Import
ImageIcon i = new ImageIcon("C: / Class Pokemon Game/ src / GameTitle (1).psd");
Image title = i.getImage();
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.RED);
g.fillRect(0, 40, 5000, 20);
g.**drawImage**(title, 500, 500);
}
}
the error is
add argument to match 'drawImage(Image, int, int, ImageObserver)'
ImageObserver is an interface that has methods for handling notification of state of image loading. It can use this for redisplay as needed. JFrame and Applet both implement ImageObserver interface.
To keep users informed regarding the loading of an image
ImageObserver interface – Enables the monitoring of the loading process so that
users can be informed and the image can be used asap once it is loaded.
Loading an image asynchronously – how to know when the image is ready.
An image is ready – getImage() method returns, long before anything is
known about the image.
imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
Note: java.awt.Component implements ImageObserver, all the subclasses do as
well!
g.drawImage(imge, 0,0, this) -- this refers to the ImageObserver instance.
imageUpdate() – Called by the ImageObserver whenever necessary. You do not call
it explicitly!
If the image is complete, returns false.
If the image is not complete and needs to be updated, returns true.
ImageObserver.ALLBITS = 32
Various constants are combined to form the infoflags argument, which indicates
whether all information is available or not.
You can skip using an ImageObserver by putting it as null
for example (Using Graphics2D)
g2.drawImage(Image texture, x, y, width, height, null);
Related
When ran, the program displays a 3D sphere rendered in a P3D environment in the PGraphics object 'g', which is shown by taking the rendered PGraphics object and displaying it through the image() method in the main graphics context, which happens to be P2D.
The purpose of the program is to show how window size doesn't always correlate with render size. If you play an old Widows98 game in full screen, the game most likely will be rendered at 480p no matter what, so taking it into full screen just decreases the pixels per inch, plus making the image appear blurry. Which is fine, since fullscreen at 480p is preferred over windowed mode ( esp. if you're on 4K X_X )
the mouse's y position in the window changes the 3d camera's field of view, and the x position changes the rendering resolution of the P3D context used to display the sphere. Additionally, the P3D context is drawn in the main (P2D) context through the image() method, and is 'forcefully'. displayed at the size of the window. So if the P3D render resolution is smaller than the window, then it will start to look blurry and more pixelated, and if the render resolution is larger, you get a strange sharpening effect.
Now, my program works fine as it is, but. Another purpose of the program is shadowed by this issue, it's how the 'crispness' of the sphere fades as the render resolution decreases. You might say that it's clearly shown, but what I'm looking for is an image where there is no "anti-alias" effect going on. I want the image to preserve the pixels as the resolution gets smaller, so you can see the actual shape of the sphere at say, 50 x 50 pixels.
The noSmooth() method doesn't seem to work, and before you tell me to just do
g.loadPixels();
and then do a double for loop to draw the raw pixels to the 2d context. No, it's sloppy. I know that there must be some reason why this blurring is going on. I'm hoping that it's the image() method and that I should be using a different method or I should add another method before it to remove image blurring.
PGraphics g;
void setup(){
size(1000,1000,P2D);
frameRate(1000);
noSmooth();
}
void draw(){
background(200);
float res = map(mouseX,0,width,0.75,128);
if (res==0) {
res=1;
}
g = createGraphics((int)(width/res),(int)(height/res),P3D);
g.noSmooth(); // is this thing working?????
float cameraZ = ((height/2.0) / tan(PI*60.0/360.0));
g.beginDraw();
g.perspective(radians(map(mouseY,0,height,0.1,160)), width/height, cameraZ/10.0, cameraZ*10.0);
g.camera(g.width/2.0, g.height/2.0, (height/2.0) / tan(PI*30.0 / 180.0), g.width/2.0, g.height/2.0, 0, 0, 1, 0);
g.background(200);
g.translate(g.width/2 ,g.height/2);
g.sphere(100);
g.endDraw();
image(g, 0, 0, width, height); // this is where it all comes together
text("rendering resolution: "+g.width+" x "+g.height,0,14);
text("fps: "+frameRate,0,14*2);
}
Replace g.noSmooth() with ((PGraphicsOpenGL)g).textureSampling(2);
Credits go to Vallentin as I oddly enough had the same question with the P3D renderer
(Edit: This solution fixes the problem in the default renderer, but the OP is using the P2D renderer. The solution should be similar, so if somebody knows how to change the image interpolation mode in opengl, that's the answer.)
This is not really caused by anti-aliasing. It's caused by image scaling.
Also, it's much easier to help if you provide a MCVE, like this one:
PGraphics buffer;
void setup() {
size(1000, 1000);
buffer = createGraphics(100, 100);
buffer.noSmooth();
buffer.beginDraw();
buffer.background(255);
buffer.line(0, 0, width, height);
buffer.endDraw();
}
void draw() {
background(0);
image(buffer, 0, 0, mouseX, mouseY);
}
This code exhibits the same problem, but it's much easier to understand and work with.
Anyway, tracing through Processing's code, we can see that the image() function eventually calls the imageImpl() function in the PGraphics class here.
This function then draws your image using this code:
beginShape(QUADS);
texture(img);
vertex(x1, y1, u1, v1);
vertex(x1, y2, u1, v2);
vertex(x2, y2, u2, v2);
vertex(x2, y1, u2, v1);
endShape();
The endShape() function is then implemented in the renderer, specifically the PGraphicsJava2D class, which calls the drawShape() function here:
protected void drawShape(Shape s) {
if (fillGradient) {
g2.setPaint(fillGradientObject);
g2.fill(s);
} else if (fill) {
g2.setColor(fillColorObject);
g2.fill(s);
}
if (strokeGradient) {
g2.setPaint(strokeGradientObject);
g2.draw(s);
} else if (stroke) {
g2.setColor(strokeColorObject);
g2.draw(s);
}
}
Finally, that shows us that the Graphics2D.fill() function is being called, which is what actually draws your function.
The "problem" is that Graphics2D.fill() is scaling your image using an algorithm that causes some blurriness. We can consult the Java API and Google to figure out how to fix that though.
Specifically, this tutorial shows you how to set various rendering hints to change the scaling algorithm. We can use that in Processing like this:
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import processing.awt.PGraphicsJava2D;
PGraphics buffer;
void setup() {
size(1000, 1000);
buffer = createGraphics(100, 100);
buffer.noSmooth();
buffer.beginDraw();
buffer.background(255);
buffer.line(0, 0, width, height);
buffer.endDraw();
}
void draw() {
if (mousePressed) {
Graphics2D g2d = ((PGraphicsJava2D)g).g2;
g2d.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
}
background(0);
image(buffer, 0, 0, mouseX, mouseY);
}
First, we import the classes we're going to need. Then we get to the Graphics2D instance in the renderer, and finally we call its setRenderingHint() function. I wrapped it in an if(mousePressed) so you could easily see the difference. When you click the mouse, interpolation is set to nearest neighbor, and you no longer see the blurriness.
Also notice that my code uses the g variable that's inherited from the PApplet superclass, so you would have to change your g variable so it's no longer hiding it.
I'm making a space game that renders objects onto a JPanel.
These objects' render method is called in my Space class.
I have 2 objects, alienShip and myShip with respective classes. Each class has a render method. I can't get both ships to render onto my JPanel simultaneously, it's either one or the other. I only see the object that calls the .render(g2) method first.
SPACE CLASS:
spaceImage=new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
foregroundImage=new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
//create the space Image background and instantiate ships (myShip, alienShip)
//Below render() method is called in my Game class using a standard game loop with
update method and rendor method.
public void render(Graphics2D g) {
Graphics2D g2=(Graphics2D) foregroundImage.getGraphics();
g2.drawImage(spaceImage, 0, 0, null);
myShip.render(g2); <---alienShip does not appear, only myShip.
alienShip.render(g2); <---If I swap these 2 commands, then alienShip appears,
and myShip does not
g.drawImage(foregroundImage, x, x, null);
}
ALIENSHIP AND MYSHIP CLASS:
public void render(Graphics2D g) {
g.drawImage(shipImage, x, y, null);
g.dispose();
}
I've tried to create a Drawable interface, and loop through all drawable objects calling DrawableObject.render(g2), but doesn't fix it. Furthermore, I have bullets that DO rendor simultaneously with myShip.
myShip and alienShip does extend an abstract class called Ship as well. Hope this makes sense.
You're .dispose()ing the graphics object after drawing one item, then trying to draw another item with it.
Currently I have a JPanel with its paintComponent overridden with lots of image processing based on various states. When an event occurs (infrequent) many of the states change and the images that are drawn change. It doesn't seem the best way to keep doing all the processing every time the paintComponent is it possible to do something like when an event occurs draw everything to a Graphics2D instance and then merge this with the paintComponent one? Is this also the best way to do it?
As MadProgrammer suggested, storing rendered output can help you.
When the event that might change the image occurs, you can draw stuff to a BufferedImage like following.
private BufferedImage renderedImage;
public void triggerEvent(int width, int height) {
this.renderedImage = new BufferedImage(width, height, TYPE_INT_ARGB);
Graphics2D g = this.renderedImage.createGraphics();
// Paint things on g.
}
#Override
public void paintComponent(Graphics g) {
g.drawImage(this.renderedImage, 0, 0, this);
}
Hope this helps.
I am in the holiday spirit, and I was thinking about writing a little countdown timer for Christmas, but ran into some difficulty that I cannot resolve. I have 2 PImage variables, one that was directly loaded from an image on the hard drive called "origbkg", while the other is the actual image that is being displayed as the background for my program. I made it this way so that if the user changes the size of the window, the image will resize correspondingly. However, when I make the window very small, and then try to maximize it again it loses resolution, although it should be getting reset to the original full resolution image that was loaded off the drive.
When I have tried to display the "origbkg" on the screen, it also is getting modified for some reason when all I am doing is setting bkgimg=origbkg.
Here is my code:
//Christmas Countdown Clock
//by: Ben Templin
//============================================================
//-------------------------Variables-------------------------
boolean bkgsized;
String background;
PImage origbkg;
PImage bkgimg;
int count;
int psize;
int size;
//-------------------------Setup-------------------------
void setup()
{
frameRate(30);
smooth();
size(displayWidth-250, displayHeight-250);
frame.setResizable(true);
background="default";
textSize(20);
fill(255, 0, 0);
text("Loading Images...", width/2-100, height/2);
origbkg=loadImage("Christmas-Tree.png");
bkgsized=false;
bkgimg=origbkg;
}
//-------------------------Draw-------------------------
void draw()
{
size=width+height;
if(psize!=size){
bkgsized=false;
}
if(bkgsized==false){
sizebkg();
}
psize=width+height;
}
//-------------------------Size the Background-------------------------
void sizebkg()
{
bkgimg=origbkg;
bkgimg.resize(width, height);
image(bkgimg, 0, 0);
bkgsized=true;
}
Can someone please tell me why "origbkg" is getting changed? Thanks in advance, and
Merry Christmas!
bkgimg=origbkg;
bkgimg.resize(width, height);
Variable origbkg holds a reference to a PImage object. First, this code copies that reference into bkgimg, so that both bkgimg and origbkg refer to the same PImage. Then, it resizes the image which bkgimg refers to--which is the same image that origbkg refers to! To use this technique, you'll have to use some method to clone or copy the image, and set bkgimg to the copy, not the original. However, for this use case, it is actually more efficient to simply use the image() method with additional parameters to rescale the image to fit into your width and height:
image(origbkg, 0, 0, width, height);
This way, you don't have to create a new copy of the image each time it is resized.
As a side note, your draw() method's check to see if the window has been resized is flawed: It checks whether the sum of width+height has changed, but this check fails to account for the possibility that the window is resized such that its width grows by the same distance that height shrinks, or vice versa. To properly check for a resize, you must store both a pwidth variable and a pheight variable and compare them.
I have an Image img that, when trying to use any of above mentioned get methods, returns -1. Why is this? And what is an ImageObserver object?
According to the documentation for Image, these methods return a -1 if the size, width, or height (respectively) are not yet known.
Also, ImageObserver is simply an interface that provides methods to get notifications about the information of an Image object that is being constructed.
You can use the MediaTrack to get your image's width & height like that :
// ...
Image img;
// ...
// ... loading the image using IO or Toolkit ot something
MediaTracker MTrack = new MediaTracker(this); // in my case, 'this' is a JFrame
MTrack.addImage(img,1);
try
{
MTrack.waitForID(1);
}
catch(InterruptedException e)
{
e.getMessage();
}
int width = img.getWidth(null);
int height = img.getHeight(null);
double ratio = (double)width/(double)height;
// ....
// ....
According to the Java docs, it seems that if you call getHeight() etc. on an Image while it's still in the construction phase, such that the height is not really "known", -1 is returned and the ImageObserver provided is notified.
ImageObserver is an interface that provides a way for you to have a callback method that is called when the image is updated in some way. ImageObserver is implemented by java.awt.Component, so if you extend that in the containing class you could override imageUpdated() and store the image height when the function is called asynchronously (if Image.getHeight returns -1).
In GraphTest, override imageUpdate:
#Override
public void imageUpdate(Image img, int flags,
int x, int y, int width, int height) {
if ((flags & (WIDTH|HEIGHT)) == (WIDTH|HEIGHT)) {
// width and height have meaningful values, do your resize here
}
super.imageUpdate(img, flags, x, y, width, height);
}
The problem is the time needed to load the Image.
As long as the image is not loaded you get the -1. When the image is finally loaded, it fires the ImageObserver. The obeserver, in your case the Background instance - g.drawImage(bkg, 0, 0, this); - will force a repaint of the Background causing the now loaded image to be painted.
You can also use the java.awt.MediaTracker to track the status of your Image.
[]]