2014-11-03 78 views
0

我正在编写一个非常基本的绘画应用程序。填充算法需要几秒钟

我的应用程序有一个图像,当我在任何地方触摸这个地方填充颜色。

我使用洪水填充算法(http://en.wikipedia.org/wiki/Flood_fill),具体是第二种方法Alternative implementations部分。

我使用像素图来更新纹理。

这工作正常在我的电脑上,问题是当我的Android上执行应用程序(摩托罗拉G与720p分辨率,Android 4.4),算法需要几秒钟,我不喜欢那,我想这个过程需要更少的时间。所以,问题是高分辨率(或大部分填充)算法需要几秒钟。

我做的一件事是检查每5个像素,而不是1个像素,但我想知道是否有其他优化。

我知道有这样做的应用程序(如https://play.google.com/store/apps/details?id=com.coloring.toddlers&hl=en)。任何人都可以告诉我任何建议?

谢谢。

编辑:用一些代码更新问题(我已经从接口中删除了空方法)。可能是有没有使用的变量。这是检查每个像素的版本。

我floodfill算法

import com.badlogic.gdx.*; 
import com.badlogic.gdx.assets.AssetManager; 
import com.badlogic.gdx.graphics.Color; 
import com.badlogic.gdx.graphics.GL20; 
import com.badlogic.gdx.graphics.Pixmap; 
import com.badlogic.gdx.graphics.Texture; 
import com.badlogic.gdx.input.GestureDetector; 
import com.badlogic.gdx.math.Vector2; 
import com.badlogic.gdx.scenes.scene2d.Stage; 
import es.angelluis..Actors.BackgroundActor; 
import es.angelluis..Actors.ImageActor; 
import es.angelluis..util.Pixel; 

import java.util.ArrayList; 

public class Images implements Screen, InputProcessor { 

    private Stage stage; 
    private ImageActor img = new ImageActor(); 
    private AssetManager manager; 
    private Texture texture = null; 

    public Images(){ 
     manager = new AssetManager(); 
     stage = new Stage(); 
     manager.load("dibujo1.png",Texture.class); 
     stage.addActor(img); 
     InputMultiplexer im = new InputMultiplexer(); 
     im.addProcessor(this); 
     im.addProcessor(stage); 
     Gdx.input.setInputProcessor(im); 


    } 

    @Override 
    public void render(float delta) { 
     Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
     if (manager.update()){ 
      if (!img.loaded){ 
       texture = manager.get("dibujo1.png", Texture.class); 
       int x = (Gdx.graphics.getWidth()-texture.getWidth())/2; 
       int y = (Gdx.graphics.getHeight()-texture.getHeight())/2; 
       img.load(texture, x,y, texture.getWidth(), texture.getHeight()); 
       texture.getTextureData().prepare(); 
       pix = texture.getTextureData().consumePixmap(); 
      } 
      stage.draw(); 
     } 
    } 

    @Override 
    public boolean touchDown(int screenX, int screenY, int pointer, int button) { 
     int colorSelected = Color.rgba8888(Color.RED); 

     if (screenX < img.getX() || screenX > img.getX() + img.getWidth() || screenY < img.getY() || screenY > img.getY() + img.getHeight()){ 
      return false; 
     } 

     //Get Texture to update. 
     Pixmap source = img.getPixmap(); 
     // Obtenemos las coordenadas locales a la textura. 
     screenX = screenX - (int)img.getX(); 
     screenY = screenY - (int)img.getY(); 
     // Get Color. 
     int colorInicial = source.getPixel(screenX, screenY); 



     // If color is the same we will exit. 
     if (colorInicial == colorSelected){ 
      return false; 
     } 

     ArrayList<Pixel> pixels = new ArrayList<Pixel>(); 
     int colorPixel = source.getPixel(screenX, screenY); 

     if (colorPixel == colorInicial){ 
      // Store the initial pixel in pixels linked list. 
      pixels.add(new Pixel(screenX, screenY)); 
      while(!pixels.isEmpty()){ 
       Pixel p = pixels.get(0); 
       source.setColor(Color.RED); 
       source.drawPixel(p.getX(), p.getY()); 
       pixels.remove(0); 
       // Now get all pixel that I should be update in this y coords. So get west and east. 
       ArrayList<Pixel> line = new ArrayList<Pixel>(); 
       int w = p.getX()-1; 
       colorPixel = source.getPixel(w, p.getY()); 
       while (colorPixel == colorInicial && w != 0){ 
        line.add(new Pixel(w, p.getY())); 
        w--; 
        colorPixel = source.getPixel(w, p.getY()); 
       } 
       int e = p.getX() + 1; 
       colorPixel = source.getPixel(e, p.getY()); 
       while (colorPixel == colorInicial && e != img.getWidth()){ 
        line.add(new Pixel(e, p.getY())); 
        e++; 
        colorPixel = source.getPixel(e, p.getY()); 
       } 

       // Draw the line that I store before. 
       while (!line.isEmpty()){ 
        Pixel linePixel = line.get(0); 
        line.remove(0); 
        source.setColor(Color.RED); 
        source.drawPixel(linePixel.getX(), linePixel.getY()); 

        // I check the north pixel and store it if they should be updated 
        colorPixel = source.getPixel(linePixel.getX(), linePixel.getY()+1); 
        if (colorPixel == colorInicial){ 

         pixels.add(new Pixel(linePixel.getX(), linePixel.getY()+1)); 
        } 
        // I check the south pixel and store it if they should be updated 
        colorPixel = source.getPixel(linePixel.getX(), linePixel.getY()-1); 
        if (colorPixel == colorInicial){ 
         //System.out.println("Entramos en sur"); 

         pixels.add(new Pixel(linePixel.getX(), linePixel.getY()-1)); 
        } 
       } 
      } 
     } 
     img.setTexture(new Texture(source)); 
     return false; 
    } 
} 

ImageActor

package es.angelluis..Actors; 

import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.graphics.Pixmap; 
import com.badlogic.gdx.graphics.Texture; 
import com.badlogic.gdx.graphics.g2d.Batch; 
import com.badlogic.gdx.scenes.scene2d.Actor; 

public class ImageActor extends Actor{ 

    private Texture img; 
    public boolean loaded = false; 
    private int x,y,width,height; 

    public void load(Texture img, int x, int y, int width, int height){ 
     this.img = img; 
     loaded = true; 
     this.x = x; 
     this.y = y; 
     this.width = width; 
     this.height = height; 
    } 

    public void setTexture(Texture img){ 
     this.img = img; 
    } 

    public Pixmap getPixmap(){ 
     if (!img.getTextureData().isPrepared()){ 
      img.getTextureData().prepare(); 
     } 
     return img.getTextureData().consumePixmap(); 
    } 

    public float getX() { 
     return x; 
    } 

    public void setX(int x) { 
     this.x = x; 
    } 

    public float getY() { 
     return y; 
    } 

    public void setY(int y) { 
     this.y = y; 
    } 

    public float getWidth() { 
     return width; 
    } 

    public void setWidth(int width) { 
     this.width = width; 
    } 

    public float getHeight() { 
     return height; 
    } 

    public void setHeight(int height) { 
     this.height = height; 
    } 

    @Override 
    public void draw(Batch batch, float alpha){ 
     batch.draw(img, x, y, width, height); 
    } 

} 
+0

发布您的代码。你如何设置像素?现代硬件的设计不是逐个设置像素。您需要在位图中构建完整的填充图像并将其复制到图形设备。 – Gene 2014-11-03 13:23:24

+0

我用一些代码更新了我的问题 – RdlP 2014-11-03 13:56:56

回答

0

做这样的事情时,一个常见的错误是,你正试图更新屏幕的位图,它由很多减慢过程下来,因为该应用程序正在尝试更新屏幕。 此问题的解决方案是将屏幕复制到位图中,在该位图上执行填充算法,并在完成时将结果复制回屏幕。 如果您提供一些代码,我们可以检查您的方法。

+0

我用一些代码更新了我的问题 – RdlP 2014-11-03 13:57:11