3

I am working on an App with coloring function. User can perform pan and zooming on this image. I am using this library to add zoom effect on image.

But the issue is when I zoom the image, I am not able to color to specific areas of image. In small view it works perfect but after zooming when i touch on an area it fills color to different area instead of touching area.

The reason is only one that the original image laying under is not getting scaled even when I zoom the image on the top. I searched and found this answer this is the same issue which I have but I am not understanding where and how to use this in my activity.java file.

This is my ActivityClass

    package com.coloringbook;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Shader.TileMode;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.widget.LinearLayout.LayoutParams;
import com.coloringbook.R;
import com.onesignal.OneSignal;


public class Game extends Activity implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener {

    private TouchImageView image;
    Bitmap bm_iv;   //bitmap for image view for coloring
    int bm_iv_dx;   //sizes
    int bm_iv_dy;
    int[] pixels;   //of bm_iv; need to fill by color 

    final int[] colors_base = {0xff0000,0xff8000,0xffff00,0x80ff00,0x00ff00,0x00ff80,0x00ffff,0x0080ff,
            0x0000ff,0x8000ff,0xff00ff,0xff0080,0x888888}; //default palette
    final int btn_num = colors_base.length;
    int[] colors_gradient = new int[btn_num]; //gradient palette, will generate dynamically
    Bitmap bm_gradient; //to draw gradient and fill gradient buttons

    Bitmap[] bm_button_on = new Bitmap[btn_num*2]; //bitmaps for color buttons
    Bitmap[] bm_button_off = new Bitmap[btn_num*2];
    Bitmap[] bm_button_pressed = new Bitmap[btn_num*2];
    int size_button;    // size of color button, depend of screen resolution
    final int color_gradient_shift = 3; // to avoid dark colors

    int color_selected;         // index of current color
    int color_base_selected;    // index of base color
    static int bitmap_saved_counter; // to generate name to save on SD card




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Data.SetFullScreenMode(this);
        setContentView(R.layout.game);
        Data.ShowAdMob(this);

        image = (TouchImageView) findViewById(R.id.book);

        bm_gradient = Bitmap.createBitmap(btn_num+2+color_gradient_shift, 1, Config.ARGB_8888);

        LinearLayout ll_root = (LinearLayout)findViewById(R.id.mainLayout);
        ll_root.setOnLongClickListener( this );
        DisplayMetrics dm = getResources().getDisplayMetrics();

        size_button = dm.widthPixels/btn_num;
        int i;
        LinearLayout ll_base = new LinearLayout(this);
        ll_base.setOrientation(LinearLayout.HORIZONTAL);
        ll_base.setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));                    
        LinearLayout ll_gradient = new LinearLayout(this);
        ll_gradient.setOrientation(LinearLayout.HORIZONTAL);
        ll_gradient.setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT));                    
        for( i = 0; i < btn_num; i++){
            ImageButton ib = new ImageButton(this);
            ib.setId( Data.id_image_begin+i);
            ib.setPadding(0, 0, 0, 0);
            ib.setBackgroundDrawable(null);                
            ib.setOnClickListener(this);
            ll_base.addView(ib);

            ib = new ImageButton(this);
            ib.setId( Data.id_image_begin+i+btn_num);
            ib.setPadding(0, 0, 0, 0);
            ib.setBackgroundDrawable(null);                
            ib.setOnClickListener(this);
            ll_gradient.addView(ib);            
        }
        ll_root.addView(ll_base);
        ll_root.addView(ll_gradient);       
        UpdateButtons();
        InitImage("");
    }

    void InitImage( String filePath ){
        bm_iv = null;
        File file = new File(filePath);     
        if( file.isFile() ){
            Options opts = new Options();
            opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
            opts.inScaled = false;
            bm_iv = BitmapFactory.decodeFile( filePath, opts);            
        }
        if( bm_iv == null ){
            int id = getResources().getIdentifier( "book_"+ Data.image_index, "drawable", getPackageName());
            bm_iv = BitmapFactory.decodeResource( getResources(), id);
        }  
        bm_iv_dx = bm_iv.getWidth(); 
        bm_iv_dy = bm_iv.getHeight();
        DisplayMetrics dm = getResources().getDisplayMetrics();
        if( dm.widthPixels >= bm_iv_dx && dm.heightPixels >= bm_iv_dy ){
        }else{
            float scale_x = (float) bm_iv_dx/(float) dm.widthPixels;
            float scale_y = (float) bm_iv_dy/(float) dm.heightPixels;
            float scale = Math.max(scale_x, scale_y); 
            bm_iv_dx/=scale;
            bm_iv_dy/=scale;
            bm_iv = Bitmap.createScaledBitmap(bm_iv, bm_iv_dx, bm_iv_dy, true);
        }
        bm_iv = bm_iv.copy(Config.ARGB_8888, true); //need convert to mutable bitmap

        ImageView iv = (ImageView)findViewById(R.id.book);
        iv.setImageBitmap( bm_iv );

        pixels = new int[bm_iv_dx*bm_iv_dy];
        int x, y;
        //initialization black contours
        for( y = 0; y < bm_iv_dy; y++ ){
            for( x = 0; x < bm_iv_dx; x++ ){
                int color = bm_iv.getPixel(x, y);
                if(Color.red(color) <= 0x80 && Color.green(color) <= 0x80 && Color.blue(color) <= 0x80){
                    pixels[y*bm_iv_dx+x] = -1;
                }else{
                    pixels[y*bm_iv_dx+x] = 0;
                }
            }
        }
        iv.setOnTouchListener( this );      
    }

    static int ColorShader( int color, int devider){
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        r -= r/devider;
        g -= g/devider;
        b -= b/devider;
        return Color.argb(255, r, g, b);
    }

    boolean IsValidXY( int x, int y){
        if( 0 <= x && x < bm_iv_dx && 0 <= y && y < bm_iv_dy ){
            return true;
        }else{
            return false;
        }
    }

    boolean FillPixel( int x, int y, int color_fill ){
        if( IsValidXY(x,y) ){
            if( pixels[y*bm_iv_dx+x] == 0 ){
                pixels[y*bm_iv_dx+x] = color_fill;
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    //create rounded square solid color bitmap
    Bitmap GetButtonBitmap( int size_button, int color, int round, int border ){
        Bitmap bm = Bitmap.createBitmap( size_button, size_button, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(color);
        paint.setAlpha(255);
        paint.setStyle(Paint.Style.FILL);
        c.drawRoundRect(new RectF(border,border,size_button-border, size_button-border), round, round, paint);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1);
        paint.setColor(ColorShader(color,2));
        c.drawRoundRect(new RectF(border,border,size_button-border, size_button-border), round, round, paint);
        return bm;
    }

    //set images to all color buttons
    void SetButtons(){
        for( int i = 0; i < btn_num; i++){
            ImageButton ib = (ImageButton) findViewById(Data.id_image_begin+i);
            StateListDrawable states = new StateListDrawable();
            Drawable d = new BitmapDrawable( getResources(), bm_button_pressed[i]);
            states.addState(new int[] {android.R.attr.state_pressed}, d);
            d = new BitmapDrawable( getResources(), (color_selected == i) ? bm_button_on[i]:bm_button_off[i]);
            states.addState(new int[]{}, d );
            ib.setImageDrawable(states);

            ib = (ImageButton) findViewById(Data.id_image_begin+i+btn_num);
            states = new StateListDrawable();
            d = new BitmapDrawable( getResources(), bm_button_pressed[i+btn_num]);
            states.addState(new int[] {android.R.attr.state_pressed}, d);
            d = new BitmapDrawable( getResources(), (color_selected == i+btn_num) ? bm_button_on[i+btn_num]:bm_button_off[i+btn_num]);
            states.addState(new int[]{}, d );
            ib.setImageDrawable(states);            
        }
    }

    //regenerate gradient colors and create solid color bitmaps to image buttons 
    public void UpdateButtons(){
        //set gradient by base color        
        int i;      
        int color = 0xff000000|colors_base[color_base_selected];
        Canvas canvas = new Canvas(bm_gradient); 
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        LinearGradient shader = new LinearGradient(0, 0, bm_gradient.getWidth(), 0, new int[] { Color.BLACK, color, Color.WHITE }, null, TileMode.CLAMP);
        paint.setShader(shader);
        canvas.drawPaint(paint);
        for( i = 0; i < btn_num; i++){
            colors_gradient[i] = bm_gradient.getPixel(i+1+color_gradient_shift, 0);
        }

        int round = size_button/8;  //of square
        int border = size_button/16; //to small not selected buttons
        for( i = 0; i < btn_num; i++){
            bm_button_on[i] = GetButtonBitmap( size_button, colors_base[i], round, 0 );
            bm_button_off[i] = GetButtonBitmap( size_button, colors_base[i], round, border );
            bm_button_pressed[i] = GetButtonBitmap( size_button, ColorShader(colors_base[i],2), round, 0 );

            bm_button_on[ btn_num+i] = GetButtonBitmap( size_button, colors_gradient[i], round, 0 );
            bm_button_off[btn_num+i] = GetButtonBitmap( size_button, colors_gradient[i], round, border );
            bm_button_pressed[btn_num+i] = GetButtonBitmap( size_button, ColorShader(colors_gradient[i],2), round, 0 );
        }
        SetButtons();
    }



    @Override
    public void onClick( View v ) { //color buttons
        int index = v.getId() - Data.id_image_begin;
        color_selected = index;
        if( index < btn_num ){
            color_base_selected = index; 
            UpdateButtons();
        }else{
            SetButtons();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.game_menu, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected( MenuItem item ) {
        switch( item.getItemId() ){
            case R.id.load_image:
                startActivityForResult( new Intent( Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI), 0);             
                break;

            case R.id.save_to_galary:
                Images.Media.insertImage( getContentResolver(), bm_iv, getString(R.string.app_name)+(bitmap_saved_counter++), null);
                break;

            case R.id.set_as_wallpaper_landscape:
            case R.id.set_as_wallpaper_portrait:
                DisplayMetrics dm = getResources().getDisplayMetrics();
                Bitmap bm;

                int add_x, add_y;
                if( item.getItemId() == R.id.set_as_wallpaper_landscape ){
                    bm = Bitmap.createBitmap( dm.heightPixels*2, dm.widthPixels*2, Bitmap.Config.ARGB_8888);
                }else{
                    bm = Bitmap.createBitmap( dm.widthPixels*2, dm.heightPixels*2, Bitmap.Config.ARGB_8888);
                }
                add_x = (bm.getWidth() - bm_iv.getWidth())/2;
                add_y = (bm.getHeight() - bm_iv.getHeight())/2;

                bm.eraseColor( bm_iv.getPixel(0, 0) );
                Canvas canvas = new Canvas(bm);
                canvas.drawBitmap(bm_iv, add_x, add_y, null);

                WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
                try {
                    wm.setBitmap(bm);
                } catch (IOException e) {
                    Toast.makeText( this, "Upps. Can not set as wallpaper.", Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }
                break;
        }

        return true;
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent){
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
        if(resultCode == RESULT_OK){
            Uri selectedImage = imageReturnedIntent.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);
            cursor.close();
            InitImage(filePath);
        }
    }

    public boolean onLongClick( View view) { // on screen
        this.openOptionsMenu();
        return false;
    }

    @Override
    public void openOptionsMenu() { //need to work menu on some devices, fix the bug
        Configuration config = getResources().getConfiguration();
        if((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) > Configuration.SCREENLAYOUT_SIZE_LARGE) {
            int originalScreenLayout = config.screenLayout;
            config.screenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
            super.openOptionsMenu();
            config.screenLayout = originalScreenLayout;
        } else {
            super.openOptionsMenu();
        }
    }




    @Override
    public boolean onTouch(View v, MotionEvent event) { // on coloring book
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int x_touch = (int)event.getX();
            int y_touch = (int)event.getY();
            if( IsValidXY(x_touch,y_touch) == false || pixels[y_touch*bm_iv_dx+x_touch] == -1 ){ //touch on contour
                return false;
            }
            ImageView iv_touch = (ImageView)findViewById(R.id.book);
            int x,y;
            //clear
            for( y = 0; y < bm_iv_dy; y++ ){
                for( x = 0; x < bm_iv_dx; x++ ){
                    if(  pixels[y*bm_iv_dx+x] != -1 ){
                        pixels[y*bm_iv_dx+x] = 0;
                    }
                }
            }

            int color_fill = 0;
            if( color_selected < btn_num){
                color_fill = colors_base[color_selected];
            }else{
                color_fill = colors_gradient[color_selected-btn_num];
            }
            color_fill |= 0xff000000;
            pixels[y_touch*bm_iv_dx+x_touch] = color_fill;
            //filler
            int xx,yy;
            while( true ){
                boolean go = false;
                for( y = 0; y < bm_iv_dy; y++ ){
                    for( x = 0; x < bm_iv_dx; x++ ){
                        if( pixels[y*bm_iv_dx+x] == color_fill ){
                            go |= FillPixel(x,y-1,color_fill);
                            go |= FillPixel(x+1,y-1,color_fill);
                            go |= FillPixel(x+1,y,color_fill);
                            go |= FillPixel(x+1,y+1,color_fill);
                            go |= FillPixel(x,y+1,color_fill);
                            go |= FillPixel(x-1,y+1,color_fill);
                            go |= FillPixel(x-1,y,color_fill);
                            go |= FillPixel(x-1,y-1,color_fill);
                            if( IsValidXY(x-1,y) && pixels[y*bm_iv_dx+x-1] == color_fill ){
                                xx = x-2;
                                while( FillPixel(xx--,y,color_fill) ){}
                            }
                            if( IsValidXY(x+1,y) && pixels[y*bm_iv_dx+x+1] == color_fill ){
                                xx = x+2;
                                while( FillPixel(xx++,y,color_fill) ){}
                            }
                            if( IsValidXY(x,y-1) && pixels[(y-1)*bm_iv_dx+x] == color_fill ){
                                yy = y-2;
                                while( FillPixel(x,yy--,color_fill) ){}
                            }
                            if( IsValidXY(x,y+1) && pixels[(y+1)*bm_iv_dx+x] == color_fill ){
                                yy = y+2;
                                while( FillPixel(x,yy++,color_fill) ){}
                            }
                        }
                    }
                }
                if( go == false ){
                    break;
                }
            }

            //update pixels
            for( y = 0; y < bm_iv_dy; y++ ){
                for( x = 0; x < bm_iv_dx; x++ ){
                    if( pixels[y*bm_iv_dx+x] == color_fill ){
                        bm_iv.setPixel(x, y, color_fill);
                    }
                }
            }
            iv_touch.invalidate();
        }
        return false;
    }
}

Here is ImageTouchView.java which I am using for zoom

I really thankfull if anyone can help me.

Community
  • 1
  • 1
Raj
  • 37
  • 4
  • have you got the solution for the above problem, I want to implement something similar to coloring book with variety of black and white images – Jon Stark Dec 22 '17 at 11:06

0 Answers0