2013-08-20 1 views
4

나는 색칠하기 책으로 앱을 만들고 있습니다. 라이브러리 byronsanchez/coloring-book-android을 발견했습니다.이 라이브러리를 사용하여 색칠을 잘 할 수 있습니다. 그러나, 나는 동일한 것을 위해 줌을 구현할 필요가있다. 확대 목적으로 ScaleImageView을 사용했습니다.Android : 확대/축소 후 비트 맵에서 색상을 채우는 방법?

제가 직면 한 문제는 이미지를 확대하면 특정 이미지 영역에 색상을 지정할 수 없다는 것입니다. 이미지가 확대되지 않은 경우 다른 영역에 대해서는 잘 맞았 음을 감지하지만 확대 한 후에는 영역을 터치하는 동안 다른 영역에 색상이 채워집니다.

일부 솔루션을 검색했지만 내 코드에서 구현하는 방법을 이해할 수 없습니다. Here은 내가 해결책을 찾고있는 동안 내가 만난 해답 중 하나입니다. 이미 코드에서 스케일링 함수가 있다고 생각하지만 여전히 작동하지 않습니다.

약간의 예를 들어 설명해주십시오. 나는 정말로 여기에 붙어있어, 내가 도움이 좀 필요해, 고마워 !!! 여기

@Override 
public boolean onTouch(View paramView, MotionEvent event) 
{ 
    try 
    { 
     int action = event.getAction(); 
     switch (action & MotionEvent.ACTION_MASK) 
     { 
      case MotionEvent.ACTION_DOWN: 
       //ScaleImageView img = (ScaleImageView) findViewById(R.id.iv_coloring_figure); 
       BitmapDrawable drawable = (BitmapDrawable) mImage.getDrawable(); 
       bmp = drawable.getBitmap(); 
       Rect imageBounds = new Rect(); 
       mImage.getDrawingRect(imageBounds); 

       // original height and width of the bitmap 
       int intrinsicHeight = drawable.getIntrinsicHeight(); 
       int intrinsicWidth = drawable.getIntrinsicWidth(); 

       // height and width of the visible (scaled) image 
       int scaledHeight = imageBounds.height(); 
       int scaledWidth = imageBounds.width(); 

       // Find the ratio of the original image to the scaled image Should normally be equal unless a disproportionate scaling (e.g. fitXY) is used. 
       float heightRatio = (float) intrinsicHeight/scaledHeight; 
       float widthRatio = (float) intrinsicWidth/scaledWidth; 

       // do whatever magic to get your touch point 
       // MotionEvent event; 

       // get the distance from the left and top of the image bounds 
       float scaledImageOffsetX = event.getX() - imageBounds.left; 
       float scaledImageOffsetY = event.getY() - imageBounds.top; 

       // scale these distances according to the ratio of your scaling 
       // For example, if the original image is 1.5x the size of the scaled image, and your offset is (10, 20), your original image offset values should be (15, 30). 
       int originalImageOffsetX = Math.round(scaledImageOffsetX * widthRatio); 
       int originalImageOffsetY = Math.round(scaledImageOffsetY * heightRatio); 
       int oldColor = bmp.getPixel(originalImageOffsetX, originalImageOffsetY); 

       arrX.add(originalImageOffsetX); 
       arrY.add(originalImageOffsetY); 
       Log.e("arrX", "originalImageOffsetX is " + arrX); 
       Log.e("arrY", "originalImageOffsetY is " + arrY); 
       index = arrX.size(); 

       int newColor = 0; 
       Log.e("sel", "sel color"+selColor); 
       if(selColor == null) 
        { 
         Toast.makeText(getApplicationContext(), "Please select a color to fill!", Toast.LENGTH_LONG).show(); 
        } 
       newColor = Color.parseColor(selColor); 

       if (oldColor != newColor && oldColor != Color.BLACK) 
       { 
        FloodFill floodfill = new FloodFill(bmp, oldColor, newColor); 
        floodfill.fill(originalImageOffsetX, originalImageOffsetY); 
        mImage.invalidate(); 
       } 
       break; 
      default: 
       break; 
     } 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace();; 
    } 

    return false; 
} 

내가 확대 사용하고있는 코드는 다음과 같습니다

는 여기에 비트 맵의 ​​색상을 작성하고 내 코드입니다. 또한

public class ScaleImageView extends ImageView implements OnTouchListener { 
private Context mContext; 
private float MAX_SCALE = 2f; 

private Matrix mMatrix; 
private final float[] mMatrixValues = new float[9]; 

// display width height. 
private int mWidth; 
private int mHeight; 

private int mIntrinsicWidth; 
private int mIntrinsicHeight; 

private float mScale; 
private float mMinScale; 

private float mPrevDistance; 
private boolean isScaling; 

private int mPrevMoveX; 
private int mPrevMoveY; 
private GestureDetector mDetector; 

String TAG = "ScaleImageView"; 

public ScaleImageView(Context context, AttributeSet attr) { 
    super(context, attr); 
    this.mContext = context; 
    initialize(); 
} 

public ScaleImageView(Context context) { 
    super(context); 
    this.mContext = context; 
    initialize(); 
} 

@Override 
public void setImageBitmap(Bitmap bm) { 
    super.setImageBitmap(bm); 
    this.initialize(); 
} 

@Override 
public void setImageResource(int resId) { 
    super.setImageResource(resId); 
    this.initialize(); 
} 

private void initialize() { 
    this.setScaleType(ScaleType.MATRIX); 
    this.mMatrix = new Matrix(); 
    Drawable d = getDrawable(); 
    if (d != null) { 
     mIntrinsicWidth = d.getIntrinsicWidth(); 
     mIntrinsicHeight = d.getIntrinsicHeight(); 
     setOnTouchListener(this); 
    } 
    mDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() { 
     @Override 
     public boolean onDoubleTap(MotionEvent e) { 
      maxZoomTo((int) e.getX(), (int) e.getY()); 
      cutting(); 
      return super.onDoubleTap(e); 
     } 
    }); 

} 

@Override 
protected boolean setFrame(int l, int t, int r, int b) { 
    mWidth = r - l; 
    mHeight = b - t; 

    mMatrix.reset(); 
    int r_norm = r - l; 
    mScale = (float) r_norm/(float) mIntrinsicWidth; 

    int paddingHeight = 0; 
    int paddingWidth = 0; 
    // scaling vertical 
    if (mScale * mIntrinsicHeight > mHeight) { 
     mScale = (float) mHeight/(float) mIntrinsicHeight; 
     mMatrix.postScale(mScale, mScale); 
     paddingWidth = (r - mWidth)/2; 
     paddingHeight = 0; 
     // scaling horizontal 
    } else { 
     mMatrix.postScale(mScale, mScale); 
     paddingHeight = (b - mHeight)/2; 
     paddingWidth = 0; 
    } 
    mMatrix.postTranslate(paddingWidth, paddingHeight); 

    setImageMatrix(mMatrix); 
    mMinScale = mScale; 
    zoomTo(mScale, mWidth/2, mHeight/2); 
    cutting(); 
    return super.setFrame(l, t, r, b); 
} 

protected float getValue(Matrix matrix, int whichValue) { 
    matrix.getValues(mMatrixValues); 
    return mMatrixValues[whichValue]; 
} 

protected float getScale() { 
    return getValue(mMatrix, Matrix.MSCALE_X); 
} 

public float getTranslateX() { 
    return getValue(mMatrix, Matrix.MTRANS_X); 
} 

protected float getTranslateY() { 
    return getValue(mMatrix, Matrix.MTRANS_Y); 
} 

protected void maxZoomTo(int x, int y) { 
    if (mMinScale != getScale() && (getScale() - mMinScale) > 0.1f) { 
     // threshold 0.1f 
     float scale = mMinScale/getScale(); 
     zoomTo(scale, x, y); 
    } else { 
     float scale = MAX_SCALE/getScale(); 
     zoomTo(scale, x, y); 
    } 
} 

public void zoomTo(float scale, int x, int y) { 
    if (getScale() * scale < mMinScale) { 
     return; 
    } 
    if (scale >= 1 && getScale() * scale > MAX_SCALE) { 
     return; 
    } 
    mMatrix.postScale(scale, scale); 
    // move to center 
    mMatrix.postTranslate(-(mWidth * scale - mWidth)/2, -(mHeight * scale - mHeight)/2); 

    // move x and y distance 
    mMatrix.postTranslate(-(x - (mWidth/2)) * scale, 0); 
    mMatrix.postTranslate(0, -(y - (mHeight/2)) * scale); 
    setImageMatrix(mMatrix); 
} 

public void cutting() { 
    int width = (int) (mIntrinsicWidth * getScale()); 
    int height = (int) (mIntrinsicHeight * getScale()); 
    if (getTranslateX() < -(width - mWidth)) { 
     mMatrix.postTranslate(-(getTranslateX() + width - mWidth), 0); 
    } 
    if (getTranslateX() > 0) { 
     mMatrix.postTranslate(-getTranslateX(), 0); 
    } 
    if (getTranslateY() < -(height - mHeight)) { 
     mMatrix.postTranslate(0, -(getTranslateY() + height - mHeight)); 
    } 
    if (getTranslateY() > 0) { 
     mMatrix.postTranslate(0, -getTranslateY()); 
    } 
    if (width < mWidth) { 
     mMatrix.postTranslate((mWidth - width)/2, 0); 
    } 
    if (height < mHeight) { 
     mMatrix.postTranslate(0, (mHeight - height)/2); 
    } 
    setImageMatrix(mMatrix); 
} 

private float distance(float x0, float x1, float y0, float y1) { 
    float x = x0 - x1; 
    float y = y0 - y1; 
    return FloatMath.sqrt(x * x + y * y); 
} 

private float dispDistance() { 
    return FloatMath.sqrt(mWidth * mWidth + mHeight * mHeight); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (mDetector.onTouchEvent(event)) { 
     return true; 
    } 
    int touchCount = event.getPointerCount(); 
    switch (event.getAction()) { 
    case MotionEvent.ACTION_DOWN: 
    case MotionEvent.ACTION_POINTER_1_DOWN: 
    case MotionEvent.ACTION_POINTER_2_DOWN: 
     if (touchCount >= 2) { 
      float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); 
      mPrevDistance = distance; 
      isScaling = true; 
     } else { 
      mPrevMoveX = (int) event.getX(); 
      mPrevMoveY = (int) event.getY(); 
     } 
    case MotionEvent.ACTION_MOVE: 
     if (touchCount >= 2 && isScaling) { 
      float dist = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1)); 
      float scale = (dist - mPrevDistance)/dispDistance(); 
      mPrevDistance = dist; 
      scale += 1; 
      scale = scale * scale; 
      zoomTo(scale, mWidth/2, mHeight/2); 
      cutting(); 
     } else if (!isScaling) { 
      int distanceX = mPrevMoveX - (int) event.getX(); 
      int distanceY = mPrevMoveY - (int) event.getY(); 
      mPrevMoveX = (int) event.getX(); 
      mPrevMoveY = (int) event.getY(); 
      mMatrix.postTranslate(-distanceX, -distanceY); 
      cutting(); 
     } 
     break; 
    case MotionEvent.ACTION_UP: 
    case MotionEvent.ACTION_POINTER_UP: 
    case MotionEvent.ACTION_POINTER_2_UP: 
     if (event.getPointerCount() <= 1) { 
      isScaling = false; 
     } 
     break; 
    } 
    return true; 
} 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    return super.onTouchEvent(event); 
} 
} 

나는 다음과 같이 내 활동에에서 onCreate에서 비트 맵을 그리기 오전 :

// Coloring Image 
    mImage = (ScaleImageView) findViewById(R.id.iv_coloring_figure); 
    BitmapDrawable drawable = (BitmapDrawable) mImage.getDrawable(); 
    bmp = drawable.getBitmap(); 
    _alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(_alteredBitmap); 
    Paint paint = new Paint(); 
    Matrix matrix = new Matrix(); 
    canvas.drawBitmap(bmp, matrix, paint); 
    mImage.setImageBitmap(_alteredBitmap); 
    mImage.setOnTouchListener(this); 

나는 또한 내가 확대를 위해 사용하고있는 사용자 정의 이미지 뷰에서 onTouch 방법 내부의 색상 코드를 설정하는 시도 ,하지만 여전히 작동하지 않습니다. 그 이유는 맨 위에있는 이미지를 확대해도 맨 아래에 놓여있는 원본 이미지가 축소되지 않는다는 것입니다. 정말이 문제에 대한 해결책이 필요합니다. 희망을 얻습니다. 다시 한 번 감사드립니다!

+0

색상을 채우기위한 onTouch (첫 번째 코드)에서 event.getX() 및 Y를 번역해야합니다. fixedX = (event.getX - mImage.getTranslateX())/mImage.getScale(). 그런 다음 event.getX 대신 fixedX를 사용하십시오. 당신이 필요하다면 확실하지 않다. + - */그냥 값을 로크하여 고정시켜야한다. – talkol

+0

@talkol 그래, 고마워. 나는 당신의 제안을 시도하고 트릭을했는지 알려 줄 것입니다! –

+0

@talkol 작동하지 않습니다! –

답변

0

최상위 비트 맵의 ​​매트릭스를 가져 와서 최하위 비트 맵으로 설정할 수 있습니다. 이 answer을 참조하면 이미지 행렬을 가져올 수 있습니다.

+1

참조 용으로 좋은 예제입니다. 그것이 저에게 효과가 있는지 알아보기 위해 노력할 것입니다. 감사! –

+0

또한 코드를 복사하여 작업하고 실제로 고정 코드를 제공 할 수 있는지 확인합니다. 일단 충분한 시간을 얻으면 나는 그것을 할 것입니다. –

관련 문제