0

So I understand the error. I'm trying to adjust the UI with a thread that isn't the main UI thread. But that's inherently the problem. Doing image processing (in this case greyscaling multiple bitmaps) is a CPU intensive task. Therefore, wouldn't me trying to launch a thread that deals with image processing be the right thing to do? Or is my thought just an ideal thought that simply isn't possible because of the valid error I am receiving? Is there a work around that I'm unaware of?

Actual error message: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

//Package declaration
//Many import statements

public class PhotoViewer extends Activity implements OnClickListener {

private Button refresh_;
private Button grey_;

private ImageView image1_;
private ImageView image2_;
private ImageView image3_;
private ImageView image4_;

private GreyBitmaps gMap_;

private Bitmap bMap1_;
private Bitmap bMap2_;
private Bitmap bMap3_;
private Bitmap bMap4_;

private int num_;
private boolean makeGrey_;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_photos);

    // this GreyBitmaps class creates the other thread
    gMap_ = new GreyBitmaps();

    refresh_ = (Button) findViewById(R.id.refresh);
    grey_ = (Button) findViewById(R.id.grey);

    image1_ = (ImageView) findViewById(R.id.view1);
    image2_ = (ImageView) findViewById(R.id.view2);
    image3_ = (ImageView) findViewById(R.id.view3);
    image4_ = (ImageView) findViewById(R.id.view4);

    refresh_.setOnClickListener(this);
    grey_.setOnClickListener(this);

    makeGrey_ = false;
    getPhotos();
    setBitmap();
    //num_ =0;
}


public void onClick(View v) {
    Log.d("onClick", "Begin");
    if(v == refresh_){
        refreshPhoto();
    }else if (v == grey_){
        greyPhoto();
    }
    Log.d("onClick", "end");
}

protected void onResume(){
    super.onResume();
    gMap_.resume();

}
protected void onPause(){
    super.onPause();
    gMap_.pause();
}

private void refreshPhoto(){
    getPhotos();
}

private void greyPhoto(){
    makeGrey_ = true;
}

private void getPhotos(){
    bMap1_ = BitmapFactory.decodeResource(getResources(), R.drawable.p1);
    bMap2_ = BitmapFactory.decodeResource(getResources(), R.drawable.p2);
    bMap3_ = BitmapFactory.decodeResource(getResources(), R.drawable.p3);
    bMap4_ = BitmapFactory.decodeResource(getResources(), R.drawable.p4);
}

private void setBitmap(){
    image1_.setImageBitmap(bMap1_);
    image2_.setImageBitmap(bMap2_);
    image3_.setImageBitmap(bMap3_);
    image4_.setImageBitmap(bMap4_);
}

private Bitmap goGrey(Bitmap bmIn){
    final double gs_red = 0.299;
    final double gs_green = 0.587;
    final double gs_blue = 0.114;

    int width = bmIn.getWidth();
    int height = bmIn.getHeight();

    Bitmap bmOut = Bitmap.createBitmap(width, height, bmIn.getConfig());
    int a, r, g, b;
    int pix;

    for(int x = 0; x<width; x++){
        for(int y = 0; y<height; y++){
            pix = bmIn.getPixel(x, y);
            a = Color.alpha(pix);
            r = Color.red(pix);
            g = Color.green(pix);
            b = Color.blue(pix);
            r = g = b = (int) (gs_blue*b +gs_green*g +gs_red*r);

            //write out
            bmOut.setPixel(x, y, Color.argb(a, r, g, b));
        }
    }
    return bmOut;
}

public class GreyBitmaps implements Runnable{
    Thread t = null;
    boolean isActive = false;

    public void run() {
        Log.d("Runnable", "running");
        //num_ = 100;
        while(isActive) {
            Log.d("Runnable", "running2");
            num_ = 200;
            setBitmap();
            try {
                Thread.sleep(100);
                if (makeGrey_) {
                    goGrey(bMap1_);
                    goGrey(bMap2_);
                    goGrey(bMap3_);
                    goGrey(bMap4_);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void pause(){
        isActive = false;
        while(true){
            try{
                t.join();
            }catch (InterruptedException e) {
                e.printStackTrace();
                Log.e("Error", "Failed to join thread");
            }
            break;
        }
        t = null;

    }

    public void resume(){
        isActive = true;
        t = new Thread(this);
        t.start();
    }
}

}

user2589339
  • 91
  • 10

1 Answers1

0

Call your setBitmap() method in runOnUiThread thread.

See this link for runOnUiThread method implementation https://stackoverflow.com/a/11140429/4384828

Community
  • 1
  • 1
Sanjay Hirani
  • 406
  • 2
  • 6
  • 18