For some reason I have found a glitch that makes no sense at all and only appears on the Galaxy Note 4, as I think now. The only test devices I have is a Nexus 7 (2012), blue stacks beta and the Note 4. This glitch only is appearing on the note 4. Here is the drawing code:
if(!started){
continue;
}
h = getHolder();
if (!h.getSurface().isValid()){
continue;
}
Canvas c = h.lockCanvas();
c.drawRect(0, 0, this.getWidth(), this.getHeight(), white);
//draw walls
for(int i=0;i<walls.length;i++){
c.drawRect(walls[i].x, walls[i].y, walls[i].bottom, walls[i].right, red);
}
//draw portals
for(int i=0;i<portals.length;i++){
Log.d("S", i+"");
Log.d("S", portalimages[i].toString());
c.drawBitmap(portalimages[i], portals[i].x1, portals[i].y1, null);
c.drawBitmap(portalimages[i], portals[i].x2, portals[i].y2, null);
}
//draw startlocations
for(int i=0;i<startlocations.length;i++){
c.drawBitmap(player, startlocations[i].x, startlocations[i].y, null);
}
//draw checkpoints
for(int i=0;i<checkpoints.length;i++){
c.drawRect(checkpoints[i].x, checkpoints[i].y, checkpoints[i].x+this.getHeight()/18, checkpoints[i].y+this.getHeight()/18, blue);
}
//draw middle line
c.drawRect(0, getHeight()/2-getHeight()/80, getWidth(), getHeight()/2+getHeight()/80, black);
menu.draw(c);
h.unlockCanvasAndPost(c);
The glitch happens once my onClick is called. it just adds a new startlocation:
startlocations[location] = new Coord(lastx, lasty);
if(location>0){
location = 0;
}else{
location++;
}
break;
Note: startlocations is setup with startlocations = new Coord[2];
Sorry for the video quality. The Note 4 is my Dad's so I had to send it over a messaging service and it compressed it, then YouTube compressed it more. Then it breaks out into this: https://www.youtube.com/watch?v=Ig9mflYBPaI
There is nothing else that changes on click of the player start locations button. I will try to look more into this but I decided to post it here in case I missed something. Thanks!
Edit:
I now know that the problem goes away when you do not have this line : c.drawBitmap(player, startlocations[i].x, startlocations[i].y, null); which makes no sense. There is no error and it is loaded with this code. BitmapFactory.decodeResource(getResources(), R.drawable.portal); and later is adjusted with Bitmap.createScaledBitmap(player, this.getHeight()/18, this.getHeight()/18, true);
I found the answer and it makes NO sense at all. For some reason, just in this class, the image needs to have transparency or else it glitches. Later on I draw other non transparent images. It makes no sense but it works. please tell me if you know any reason why this happens.
My guess is that in the other class I used the main package but in this class it's a different package. This could be the reason why it's only this class (or method). I'll have to do more testing.
Thanks.
Related
I have an image with a green background.
I used this function to remove the background.
public void removeBackground(PImage img, color c, float thres) {
colorMode(HSB);
for(int i = 0; i < img.width; i++){
for(int j = 0; j < img.height; j++){
color cp = img.get(i, j);
//threshold accounts for compression
if(abs(hue(cp) - hue(c)) < thres){
img.set(i, j, color(0,0,0,0));
}
}
}
}
Using these parameters, I attempted to remove the background.
PImage FBSprite;
public void settings() {
size(500, 500);
}
void setup(){
FBSprite = loadImage("FlappyBirdSprite.jpg");
FBSprite.resize(50, 0);
removeBackground(FBSprite, FBSprite.get(0,0), 0.5);
image(FBSprite, 0, 0);
}
void draw(){
background(200);
image(FBSprite, 0, 0);
}
The background turns to black instead of transparent.
ARGB result:
HSB result with 1 alpha:
You are going to love this: change this line
colorMode(HSB);
for this:
colorMode(ARGB);
And it should do the trick. What just happened? Unless you need to work in HSB at that very specific point, there's no point to it. ARGB is just like RGB but it has an ALPHA setting, or transparency if you prefer. Seems like you already were ready to work in ARGB since you set color(0,0,0,0) like this, so this may be a a copy and paste programming issue. Or maybe you just didn't notice. It happens to me all the time. If that's the first thing, though, try to keep a keen eye for this kind of problem in the future. Most people doesn't talk about other bad design patterns except for spaghetti code which everybody knows, but cut and paste programming is real and it hurts a lot, especially if you work with some in-house platform with inexistant documentation. Not that it happened to me.
Have fun!
Instead of setting the alpha of the pixels being removed to 0, I set the alpha to 1. The alpha is so small that you can't see the border.
My problem is quite simple to understand. I have a JPanel inside a JFrame in order to display some graphics using the drawFormula() method below to display 3d points in screen using perspective projection. Everytime drawFormula() reaches its end I just recall itself to draw the shape again and again and again and because I dont want to have any image flickering problems I dont use the paintComponent method but i call drawImage() method from panelG which I get from this.getGraphics() method of my JPanel. Everything runs fine, but the problem is that after a certain amount of time it stops rendering and i believe that it has to do with the list of BufferedImages it holds everytime i call drawImage(). Is there a way to remove the previous not needed images from the stack? Thanks in advance!
public void drawFormula(){
for(double i=latMin;i<latMax;i+= 0.05){
for(double j=longMin;j<longMax;j+= 0.05){
calc(m,n1,n2,n3,i,j);
applyRotationX();
applyRotationY();
applyRotationZ();
if(outX>xxmin && outX<xxmax && outY>yymin && outY<yymax){
xxx = (int)((outX-xxmin)*xinc);
yyy = (int)((outY-yymin)*yinc);
zzz = (int)((outZ-zzmin)*zinc);
//img_g.drawRect(xxx, yyy, 1, 1);
//img_g.drawRect((int) (planeX.getOffset(new Vector3D(xxx,yyy,zzz)))+600,(int) (planeY.getOffset(new Vector3D(x[i],y[i],z[i])))+350+j,1,1);
//img_g.setColor(new Color(Color.HSBtoRGB((float)(outX/outY), (float)(outY), (float)(outZ))));
drawPoint(xxx, yyy, zzz);
//panelG.drawImage(img, 0, 0, null);
}
}
}
//panelG.dispose();
//panelG = getGraphics().create();
panelG.drawImage(img, 0, 0, null);
thetaX += 1;
thetaX %= 360;
img_g.setColor(Color.black);
img_g.fillRect(0, 0, getWidth(), getHeight());
drawFormula();
}
I think it stops rendering due to a stackoverflow. You have an unconditioned recursion in your code (the drawFormula() at the end of drawFormula), which will cause a stackoverflow at some point. For the flickering: use setDoubleBuffered(true), this should solve your problem aswell.
I am trying to draw increasing circles in a TextureView. The centre of all circles is the same. I then try to increase the drawn Circle until a specific limit is reached. Then I want to clear the canvas and start over again. However using my code (see below), the canvas seems to never be cleared. Actually it flashes white shortly when it should be cleared, but then when the first circle in the next cycle is drawn (after attempting to clear canvas), all previous circles reappear and the whole animation seems to go crazy. After letting it run for several seconds I am left with dozens of circles (some overlapping) instead of only approximately 4 per cycle. Furthermore they do not have the radius I gave them (basically my code ends up drawing numerous circles of random sizes). Spent several days trying different things, but nothing seems to help.
Here's my code:
paint.setColor(Color.argb(opac, 177, 177, 177));
stroke = 5;
paint.setStrokeWidth(stroke);
radius = 10;
Canvas canvas = new Canvas();
Boolean clear = false;
//Added these two lines following advice from a previous answer:
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
while (mRunning && !Thread.interrupted()) {
canvas = mSurface.lockCanvas(null);
try {
if(clear){
canvas.drawPaint(clearPaint); //This line should clear the canvas.
clear = false;
}else{
canvas.drawCircle(circleX, circleY, radius, paint);
}
} finally {
mSurface.unlockCanvasAndPost(canvas);
}
if(radius+15 <= circleY-stroke/2){
radius+=15;
}else{
radius = 10;
clear = true;
}
try {
Thread.sleep(360);
} catch (InterruptedException e) {
// Interrupted
}
Would really appreciate it if someone could help me out here. I wasn't able to proceed with my project for several weeks now due to this problem.
Create a new Paint Instance for just clearing the canvas
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
In your if() block for clearing the canvas, paint it with the above instance of Paint
if(clear){
canvas.drawPaint(clearPaint);
clear = false;
}
I searched google for this problem, but i can't really resolve them.
More info on code below.
Here are the two snippets of code, relevant:
//prepare
g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.white);
g.fillRect(0,0,getWidth(),getHeight());
for(ListIterator<Chunk> it = chunkvector.listIterator();it.hasNext();){
Chunk r = it.next();
r.drawChunk(g);
}
for(ListIterator<Entity> it = vectorpainter.listIterator();it.hasNext();){
Entity r = it.next();
r.drawObjects(g);
}
//Chat
if(coni.getVerified()){
try {
chat.update(g);
} catch (IOException e) {
println("I/O Exception while updating chat! "+e.toString());
}
//Framerate Anzeige
if(fps_on){
g.setColor(Color.red);
g.drawString("FPS: "+fps, 20, 20);
}
//Tickberechnung & Anzeige
tick++;
if(tick>=65536)
tick=0;
if(tick_on){
g.setColor(Color.red);
g.drawString("Tick: "+tick,80,20);
}
//end drawing
g.dispose();
strategy.show();
interesting about that:
Chunks, Entities are painted, white rect also, but fps and tick NEVER (both are true, of course), i even wrote System.out.print("..."); into the if-clauses, and it is executed! :S
I think it is something about GPU acceleration, so i added the second code block, how images are loaded. One entity does also drawString, (showing playername above head) and it works, but in the main thread not? :(
second:
public Image[] loadPics(String path, int cnt){
Image[] anim = new Image[cnt];
BufferedImage source = null;
BufferedImage temp;
URL pic_url = getClass().getResource(path);
if (pic_url == null) {
fail("Can't find ref: "+path);
}
try{
source = ImageIO.read(pic_url);
}catch(IOException e){
fail("Failed to load: "+path);
}
// create an accelerated image of the right size to store our sprite in
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
for(int x=0;x<cnt;x++){
temp = source.getSubimage(x*source.getWidth()/cnt, 0,
source.getWidth()/cnt, source.getHeight());
anim[x]= gc.createCompatibleImage(temp.getWidth(), temp.getHeight(), Transparency.BITMASK);
anim[x].getGraphics().drawImage(temp,0,0,null);
}
System.out.println(pic_url+" - loaded.");
return anim;
}
second one i copied from a tutorial, maybe a bit edited.Before that i"ve painted with paintComponent(Graphics g) ... this worked, tutorial have said i could get better performance using this method, so i tried, and want to manage it somehow.
Now it is drawing in a run loop, when i copy everything to paintComponent, no Images are drawn.
For those who managed to get past all the text a little bit of extra work:
The program runs fine on a university pc - not that good hardware ^^ , and bit of laggy at mine, which should be more than double the computationpower. Any ideas? :(
Java(c) 1.7
Many thanks, even you just read that! :)
Okay, this can be closed. My drawing problem had nothing to do with the code above.
Problem was, that things i wanted to paint were not in the picture. That I achieved through giving statements like:
fillRect(50,50,2/3*frame.getHeight(),130);
the 2/3 resolves to 0, multiplied with frameHeight...
Trick was to write (int)(2./3.*frame.getHeight())
and one time I also tried to draw a String into the panel section, where closing , maximize buttons are, that wont work too , of course.
THanks anyway!
I am implementing layers in a 2D engine of mine and I would like layers to be stackable, and I would also like a feature to 'cut holes' in layers - this means using alpha. However when writing it standalone I can't seem to get anything to use true alpha, it tried to fake it by blending colours together, for instance (my code):
BufferedImage background, foreground;
public GraphicsTest() {
background = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB);
foreground = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB); // Fully capable of alpha.
Random r = new Random();
int white = Color.white.getRGB();
// Draw random white dots
for (int i=0; i<500; i++) {
int
x = r.nextInt(500),
y = r.nextInt(500);
background.setRGB(x, y, white);
}
}
#Override
protected void paintComponent(Graphics g) {
BufferedImage output = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB); // Fully capable of alpha.
Graphics2D canvas = output.createGraphics();
Graphics2D overlay = foreground.createGraphics();
canvas.drawImage(background, 0, 0, null);
overlay.setColor(Color.white);
overlay.fillRect(0, 0, 500, 500);
// Start drawing with alpha
overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
overlay.setColor(new Color(0xFF000000)); // Overwrite/draw full alpha, colour doesn't matter when alpha is 100%
overlay.fillRect(100, 100, 125, 87);
//canvas.setColor(Color.red);
//canvas.fillRect(0, 0, 500, 500);
canvas.drawImage(foreground, 0, 0, null);
overlay.dispose();
canvas.dispose();
g.drawImage(output, 0, 0, null);
// Also write to a file for manual raw pixel checking
try {
// Does output a 32-bit depth image
ImageIO.write(output, "PNG", new File("c:/output.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
This is the most basic test I could think of, I have two images, one for the background and one for the foreground, I am needing to see the background through the foreground in the 127x87 (random sized) box.
Currently it results in a white screen with a black box, the back box should be that part of the background.
I have tried all sorts of methods here, settings the composite and drawing black with full alpha but when combined I never see the background, the setColor(0xFF000000) doesn't seem to be doing anything but drawing black and the composite is the culprit of this 'faking', instead of overwriting FF000000 (black) on a 00FFFFFF (white with no alpha) background yielding FF000000 (what I set it to) it is instead 007F7F7F (grey with no alpha).
The only reason I can see for this is the fact that everything is going through a Graphics2D object, I cannot use output.setRGB as it is slow and I wouldn't know how to draw custom shapes with it.
You need to change 3 things for your code to behave properly.
As #vandale said, you need to use a color with actual alpha with the boolean constructor.
Second, the alpha is the opacity (so it should be 0 for transparent color). You get:
overlay.setColor(new Color(0x0000000, true));
Third, you need to say that your paint operation will actually override whatever was already there (you don't want to draw on top (ATOP) of the existing but rather replace with the transparent color (IN) what was there). You get:
overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1f));