2011-06-06 86 views
4

我有一个应用程序,扭曲了一个位图与鱼眼畸变的一个圆圈。圆似乎旋转180度以及扭曲。有任何想法吗?我不知道为什么在过滤器类中。谢谢马特。圆形鱼眼畸变扭曲前旋转270度或逆时针旋转90度?

import java.io.BufferedInputStream; 
import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStream; 

import com.tecmark.HorizontalSlider.OnProgressChangeListener; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.BitmapShader; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.PorterDuffXfermode; 
import android.graphics.PorterDuff.Mode; 
import android.graphics.Shader.TileMode; 
import android.os.Environment; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageView; 

public class TouchView extends View{ 


    private File tempFile; 
    private byte[] imageArray; 
    private Bitmap bgr; 
    private Bitmap bm; 
    private Bitmap bgr2 = null;; 
    private Paint pTouch; 
    private int centreX = 1; 
    private int centreY = 1; 
    private int radius = 50; 
    private int Progress; 
    private static final String TAG = "*********TouchView"; 
    private Filters f = null; 

    public TouchView(Context context) { 
     super(context); 
     // TouchView(context, null); 
    } 




    public TouchView(Context context, AttributeSet attr) { 
     super(context,attr); 




     tempFile = new File(Environment.getExternalStorageDirectory(). 
       getAbsolutePath() + "/"+"image.jpg"); 

     imageArray = new byte[(int)tempFile.length()]; 


    try{ 

      InputStream is = new FileInputStream(tempFile); 
      BufferedInputStream bis = new BufferedInputStream(is); 
      DataInputStream dis = new DataInputStream(bis); 


      int i = 0; 

      while (dis.available() > 0) { 
      imageArray[i] = dis.readByte(); 
      i++; 
      } 

      dis.close(); 

     } catch (Exception e) { 

       e.printStackTrace(); 
      } 



     BitmapFactory.Options bfo = new BitmapFactory.Options(); 
     bfo.inSampleSize = 1; 

     bm = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo); 
     bgr = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig()); 
     bgr = bm.copy(bm.getConfig(), true); 
     bgr2 = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig()); 



     f = new Filters(); 
     //bgr2 = f.barrel(bgr,0.00022F); 

     pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);   
     pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
     pTouch.setColor(Color.TRANSPARENT); 
     pTouch.setStyle(Paint.Style.STROKE); 


    }// end of touchView constructor 


    public void findCirclePixels(){ 



    /* for (int i=centreX-50; i < centreX+50; ++i) { 
      for (int y=centreY-50; y <centreY+50 ; ++y) { 

    if(Math.sqrt(Math.pow(i - centreX, 2) + (Math.pow(y - centreY, 2))) <= radius){ 

        bgr.setPixel(i,y,Color.rgb(Progress+50,Progress,Progress+100)); 
       } 
      } 
     }*/ 
     float prog = (float)Progress/2000000; 
     bgr2 = f.barrel(bgr,prog); 

     }// end of changePixel() 




    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 

     switch (ev.getAction()) { 

      case MotionEvent.ACTION_DOWN: { 

       centreX = (int) ev.getX(); 
       centreY = (int) ev.getY(); 
       findCirclePixels(); 
       invalidate(); 

       break; 
      } 

      case MotionEvent.ACTION_MOVE: { 

        centreX = (int) ev.getX(); 
        centreY = (int) ev.getY(); 
        findCirclePixels(); 
        invalidate(); 
        break; 

      }   

      case MotionEvent.ACTION_UP: 

       break; 

     } 
     return true; 
    }//end of onTouchEvent 





    public void initSlider(final HorizontalSlider slider) 
    { 
     Log.e(TAG, "******setting up slider*********** "); 
     slider.setOnProgressChangeListener(changeListener); 
    } 



    private OnProgressChangeListener changeListener = new OnProgressChangeListener() { 


     @Override 
     public void onProgressChanged(View v, int progress) { 
      // TODO Auto-generated method stub 

      setProgress(progress); 
      Log.e(TAG, "***********progress = "+Progress); 

     } 
    }; 





    @Override 
    public void onDraw(Canvas canvas){ 
     super.onDraw(canvas); 


     canvas.drawBitmap(bgr2, 0, 0, null); 
     canvas.drawCircle(centreX, centreY, radius,pTouch); 



    }//end of onDraw 




    protected void setProgress(int progress2) { 
     this.Progress = progress2; 
     findCirclePixels(); 
     invalidate(); 

    } 


} 

import android.graphics.Bitmap; 
import android.util.Log; 

class Filters{ 
    float xscale; 
    float yscale; 
    float xshift; 
    float yshift; 
    int [] s; 
    private String TAG = "Filters"; 
    public Filters(){ 

     Log.e(TAG, "***********inside constructor"); 
    } 

    public Bitmap barrel (Bitmap input, float k){ 
     Log.e(TAG, "***********inside barrel method "); 
     float centerX=input.getWidth()/2; //center of distortion 
     float centerY=input.getHeight()/2; 

     int width = input.getWidth(); //image bounds 
     int height = input.getHeight(); 

     Bitmap dst = Bitmap.createBitmap(width, height,input.getConfig()); //output pic 
     Log.e(TAG, "***********dst bitmap created "); 
      xshift = calc_shift(0,centerX-1,centerX,k); 
      float newcenterX = width-centerX; 
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

      yshift = calc_shift(0,centerY-1,centerY,k); 
      float newcenterY = height-centerY; 
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

      xscale = (width-xshift-xshift_2)/width; 
      yscale = (height-yshift-yshift_2)/height; 
      Log.e(TAG, "***********about to loop through bm"); 
      /*for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       dst.setPixel(i, j, color); 

       } 
      }*/ 

      int origPixel; 

      for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       origPixel= input.getPixel(i,j); 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       if(Math.sqrt(Math.pow(i - centerX, 2) + (Math.pow(j - centerY, 2))) <= 85){ 
       dst.setPixel(i, j, color); 
       }else{ 
        dst.setPixel(i,j,origPixel); 
       } 
       } 
      } 
     return dst; 
    } 

    void sampleImage(Bitmap arr, float idx0, float idx1) 
    { 
     s = new int [4]; 
     if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
     s[0]=0; 
     s[1]=0; 
     s[2]=0; 
     s[3]=0; 
     return; 
     } 

     float idx0_fl=(float) Math.floor(idx0); 
     float idx0_cl=(float) Math.ceil(idx0); 
     float idx1_fl=(float) Math.floor(idx1); 
     float idx1_cl=(float) Math.ceil(idx1); 

     int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
     int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
     int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
     int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 

     s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
     s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
     s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
     s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 
    } 

    int [] getARGB(Bitmap buf,int x, int y){ 
     int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
     int [] scalar = new int[4]; 
     scalar[0] = (rgb >>> 24) & 0xFF; 
     scalar[1] = (rgb >>> 16) & 0xFF; 
     scalar[2] = (rgb >>> 8) & 0xFF; 
     scalar[3] = (rgb >>> 0) & 0xFF; 
     return scalar; 
    } 

    float getRadialX(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float getRadialY(float x,float y,float cx,float cy,float k){ 
     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float thresh = 1; 

    float calc_shift(float x1,float x2,float cx,float k){ 
     float x3 = (float)(x1+(x2-x1)*0.5); 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     if(res1>-thresh && res1 < thresh) 
     return x1; 
     if(res3<0){ 
     return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
     return calc_shift(x1,x3,cx,k); 
     } 
    } 
} 
+0

您能指出该代码的相关部分吗?这是很多需要通读的。 – 2011-06-06 17:05:32

+0

@Mayra对不起,我只是包括TouchView代码来显示如何创建位图。该类称为过滤器的桶方法。效果确实起作用,我只是无法看到过滤器代码中会旋转效果的任何内容。抱歉如此模糊。 – turtleboy 2011-06-06 17:46:25

回答

1

你确定它没有被旋转90°和镜像吗?这可能是由于您的X和Y轴转置引起的。例如,我看到你打电话buf.getPixel(y, x),尽管Bitmap's getPixel取x和y而不是y和x。

+0

你好,是的,我改变了那些ARGS身边,因为我得到了一个错误,指出错误/ AndroidRuntime(30816):java.lang.IllegalArgumentException异常:致y必须是 turtleboy 2011-06-13 10:09:28

+0

我在'sampleImage'中看到,您正在使用getHeight()和“idx1”(它似乎是Y值)与getWidth()比较“idx0”(似乎是X值)。尝试解决这个问题,否则只是通过你的代码来确定你的数学是否正确。 – Anomie 2011-06-13 12:42:11

+0

嗨,这是需要我和j参数切换的getRadialX()和getRadialY方法。它现在可以工作,所以你已经足够接近我的切换参数。谢谢。 – turtleboy 2011-06-18 15:18:36

0

只是一个猜测,但作为180度左右旋转(0,0)是在X = 0的反射加上Y = 0的反映,我不知道你xscaleyscale都出来负面。我没有更深入地跟踪逻辑,但是可能在调试器中逐步完成,或者记录这些值可能会引发一些问题。

+0

石头嗨,我这次又拍了一张脸的照片,而且我的旋转角度可能是错的。看起来像位图中间的效果或者顺时针旋转了270度,或者如果这是合理的,则是逆向旋转90度。我注销了xscale和yscale的值,它们的值为0.3754959和0.43945822,所以都是正值。感谢 – turtleboy 2011-06-12 15:29:27

0

@Thiago这是根据承诺更新的代码。它运行@大约15秒来遍历位图。我正在考虑首先显示相机图像,然后在顶部使用第二个位图叠加层。覆盖我可以减少到效果的大小,然后将其放置在原始图像上。这样我只会循环超过1/3的像素。我不确定这是否会奏效:)玩一玩。

import android.graphics.Bitmap; 
import android.os.Debug; 
import android.util.Log; 

class Filters{ 
    private float xscale; 
    private float yscale; 
    private float xshift; 
    private float yshift; 
    private int [] s; 
    private int [] scalar; 
    private int [] s1; 
    private int [] s2; 
    private int [] s3; 
    private int [] s4; 
    private String TAG = "Filters"; 

    public Filters(){ 

     Log.e(TAG, "***********inside filter constructor"); 
     s = new int[4]; 
     scalar = new int[4]; 
     s1 = new int[4]; 
     s2 = new int[4]; 
     s3 = new int[4]; 
     s4 = new int[4]; 
    } 

    public Bitmap barrel (Bitmap input, float k,float cenx, float ceny){ 
     //Log.e(TAG, "***********INSIDE BARREL METHOD "); 


     //float centerX=input.getWidth()/2; //center of distortion 
     //float centerY=input.getHeight()/2; 
     float centerX=cenx; 
     float centerY=ceny; 

     int width = input.getWidth(); //image bounds 
     int height = input.getHeight(); 

     Bitmap dst = Bitmap.createBitmap(width, height,input.getConfig()); //output pic 

      xshift = calc_shift(0,centerX-1,centerX,k); 

      float newcenterX = width-centerX; 
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k); 

      yshift = calc_shift(0,centerY-1,centerY,k); 

      float newcenterY = height-centerY; 
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k); 

      xscale = (width-xshift-xshift_2)/width; 

      yscale = (height-yshift-yshift_2)/height; 



      /*for(int j=0;j<dst.getHeight();j++){ 
       for(int i=0;i<dst.getWidth();i++){ 
       float x = getRadialX((float)i,(float)j,centerX,centerY,k); 
       float y = getRadialY((float)i,(float)j,centerX,centerY,k); 
       sampleImage(input,x,y); 
       int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       dst.setPixel(i, j, color); 

       } 
      }*/ 

      int origPixel = 0; 
      int []arr = new int[input.getWidth()*input.getHeight()]; 
      int color = 0; 

      int p = 0; 
      int i = 0; 
      long startLoop = System.currentTimeMillis(); 

      for(int j=0;j<dst.getHeight();j++){ 
       for(i=0;i<dst.getWidth();i++,p++){ 
       origPixel= input.getPixel(i,j); 

       float x = getRadialX((float)j,(float)i,centerX,centerY,k); 


       float y = getRadialY((float)j,(float)i,centerX,centerY,k); 

       sampleImage(input,x,y); 

       color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff); 
    //   System.out.print(i+" "+j+" \\"); 

       //if(Math.sqrt(Math.pow(i - centerX, 2) + (Math.pow(j - centerY, 2))) <= 150){ 
       if( Math.pow(i - centerX, 2) + (Math.pow(j - centerY, 2)) <= 12500){ 
       //dst.setPixel(i, j, color); 
        arr[p]=color; 
        //Log.e(TAG, "***********arr = " +arr[i]+" i = "+i); 
       }else{ 
        //dst.setPixel(i,j,origPixel); 
        arr[p]=origPixel; 

       } 
       } 
      } 
      long endLoop = System.currentTimeMillis(); 
      long dur = endLoop - startLoop; 
      Log.e(TAG, "loop took "+dur+"ms"); 

     Bitmap dst2 = Bitmap.createBitmap(arr,width,height,input.getConfig()); 
     return dst2; 

    }// end of barrel() 




    void sampleImage(Bitmap arr, float idx0, float idx1) 
    { 

     // s = new int [4]; 
     if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){ 
     s[0]=0; 
     s[1]=0; 
     s[2]=0; 
     s[3]=0; 
     return; 
     } 

     float idx0_fl=(float) Math.floor(idx0); 
     float idx0_cl=(float) Math.ceil(idx0); 
     float idx1_fl=(float) Math.floor(idx1); 
     float idx1_cl=(float) Math.ceil(idx1); 

    /* float idx0_fl=idx0; 
     float idx0_cl=idx0; 
     float idx1_fl=idx1; 
     float idx1_cl=idx1;*/ 

    /* int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
     int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
     int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
     int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl);*/ 

     s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl); 
     s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl); 
     s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl); 
     s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl); 

     float x = idx0 - idx0_fl; 
     float y = idx1 - idx1_fl; 

     s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y)); 
     s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y)); 
     s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y)); 
     s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y)); 


    } 

    int [] getARGB(Bitmap buf,int x, int y){ 

     int rgb = buf.getPixel(y, x); // Returns by default ARGB. 
     // int [] scalar = new int[4]; 
     scalar[0] = (rgb >>> 24) & 0xFF; 
     scalar[1] = (rgb >>> 16) & 0xFF; 
     scalar[2] = (rgb >>> 8) & 0xFF; 
     scalar[3] = (rgb >>> 0) & 0xFF; 
     return scalar; 
    } 

    float getRadialX(float x,float y,float cx,float cy,float k){ 

     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float getRadialY(float x,float y,float cx,float cy,float k){ 

     x = (x*xscale+xshift); 
     y = (y*yscale+yshift); 
     float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy))); 
     return res; 
    } 

    float thresh = 1; 

    float calc_shift(float x1,float x2,float cx,float k){ 

     float x3 = (float)(x1+(x2-x1)*0.5); 
     float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx))); 
     float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx))); 

     if(res1>-thresh && res1 < thresh) 
     return x1; 
     if(res3<0){ 
     return calc_shift(x3,x2,cx,k); 
     } 
     else{ 
     return calc_shift(x1,x3,cx,k); 
     } 
    } 



}// end of filters class