2011-06-06 3 views
4

J'ai une application qui déforme un cercle sur un bitmap avec une distorsion fisheye. le cercle semble être tourné de 180 degrés et déformé. Des idées? il n'y a aucune idée de pourquoi dans la classe de filtre. merci Matt.distorsion fisheye circulaire tournée de 270 degrés dans le sens des aiguilles d'une montre ou de 90 degrés dans le sens inverse des aiguilles d'une montre avant d'être déformée?

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

Pourriez-vous indiquer les parties pertinentes de ce code? C'est beaucoup à lire. –

+0

@Mayra désolé à ce sujet, je viens d'inclure le code TouchView pour montrer comment le bitmap est créé. cette classe appelle la méthode de canon du filtre. L'effet fonctionne, je ne vois rien dans le code du filtre qui ferait tourner l'effet. désolé d'être si vague. – turtleboy

Répondre

1

Etes-vous sûr qu'il n'est pas tourné de 90 ° et reflété? Cela pourrait être causé par la transposition de vos axes X et Y. Par exemple, je vois que vous appelez buf.getPixel(y, x) malgré Bitmap's getPixel en prenant x et y plutôt que y et x.

+0

salut, oui j'ai changé ces args autour parce que je recevais une erreur indiquant que ERROR/AndroidRuntime (30816): Causé par: java.lang.IllegalArgumentException: y doit être turtleboy

+0

Je vois dans 'sampleImage' que vous comparez" idx0 "(qui semble être la valeur X) avec getHeight() et" idx1 "(qui semble être la valeur Y) avec getWidth(). Essayez de corriger cela, et sinon traitez simplement votre code pour vous assurer que vos calculs sont corrects. – Anomie

+0

Salut, c'était les méthodes getRadialX() et getRadialY qui nécessitaient la commutation des arguments i et j. cela fonctionne maintenant, donc vous étiez assez proche pour moi avec des arguments de commutation. Merci. – turtleboy

0

Juste une supposition, mais comme une rotation de 180 degrés autour de (0,0) est une réflexion en x = 0 plus une réflexion en y = 0, je me demande si votre xscale et yscale qui sortent négatifs. Je n'ai pas suivi la logique plus en profondeur, mais peut-être que faire un pas dans le débogueur ou consigner ces valeurs pourrait jeter quelque chose en l'air.

+0

stone Salut, j'ai pris une autre photo d'un visage cette fois et j'aurais pu avoir les degrés de rotation faux. il semble que l'effet au milieu du bitmap a été tourné de 270 degrés dans le sens des aiguilles d'une montre ou de 90 degrés dans le sens inverse des aiguilles d'une montre si cela a du sens. J'ai déconnecté les valeurs de xscale et yscale et ils ont des valeurs de 0.3754959 et 0.43945822, donc sont tous les deux positifs. merci – turtleboy

0

@Thiago Voici le code mis à jour comme promis. il tourne @ environ 15 secondes pour parcourir le bitmap. Je pense d'abord à afficher l'image de la caméra puis à utiliser une deuxième superposition de bitmap en haut. la superposition je pourrais réduire à la taille de l'effet, puis placez cela sur l'image originale. De cette façon, je ne bouclerai que sur 1/3 des pixels. Je ne suis pas sûr si cela va fonctionner :) Avoir un jeu avec elle.

.

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 
Questions connexes