如何使用缩放效果填充位图中的颜色

时间:2016-09-29 09:08:34

标签: android touch pinchzoom image-scaling flood-fill

我正在使用具有着色功能的应用程序。用户可以对此图像执行平移和缩放。我正在使用this库为图像添加缩放效果。

但问题是当我缩放图像时,我无法对图像的特定区域进行着色。在小视图中,它工作得很完美,但是当我在区域上进行缩放时,它会将颜色填充到不同区域而不是触摸区域。

原因只是因为即使我在顶部放大图像也不会缩放原始图像。我搜索并发现this回答这是我遇到的同样问题,但我不知道在activity.java文件中何处以及如何使用它。

这是我的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;
    }
}

以下是我用于缩放的ImageTouchView.java

如果有人能帮助我,我真的很感激。

0 个答案:

没有答案