Autore Topic: Metodo di resize immagine "Matrix" e centrarlo nello schermo..  (Letto 1003 volte)

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
0
ciao a tutti,
ho un problemino spero da poco...vorrei ridimensionare un'immagine su un relative layout e uso il metodo "matrix" con efficacia..l'unica cosa è che non riesco a far si che l'immagine sia al centro dello schermo (quando si rimpicciolisce va nell'angolo in alto a sinistra....)

Codice: [Seleziona]
private class ScaleListener extends ScaleGestureDetector.
            SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            scale *= detector.getScaleFactor();
            scale = Math.max(0.1f, Math.min(scale, 5.0f));
            matrix.setScale(scale, scale);
            img.setImageMatrix(matrix);
            return true;
        }

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #1 il: 24 Marzo 2015, 16:41:59 CET »
0
La matrice effettua una trasformazione "pulita" di coordinate... se tu effettui solo uno scale questo verrà fatto attorno al punto di coordinate 0, 0 (in alto a sinistra)
Prova ad usare setScale con 4 parametri, gli altri due sono il pivot (centro di rotazione).

Ciao.

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #2 il: 24 Marzo 2015, 20:01:52 CET »
0
ok... ho guardato come usare il setscale come dici tu e sul sito android dice di usarlo così:
Codice: [Seleziona]
        setScale(float sx, float sy, float px, float py)
Set the matrix to scale by sx and sy, with a pivot point at (px, py).

ma non mi quadra una cosa...come faccio a sapere qual'è il centro preciso dello schermo?
intendo dire...la mia app girerà sul mio telefono, un galaxy s5, che ha una risoluzione di 1080x1920, quindi ho provato a mettere
Codice: [Seleziona]
matrix.setScale(scale, scale, 960, 540);
si, si è spostato quasi al centro ma scala verso destra ed in basso, non in maniera lineare in tutte le direzioni...
dove sbaglio?

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #3 il: 25 Marzo 2015, 15:58:34 CET »
0
Non ti interessa il centro dello schermo.
In realtà io quel metodo in particolare non l'ho mai usato, ma credo che tu debba mettere il centro dell'immagine che stai scalando.

Io in passato l'ho fatto più "a mano" generando la matrice con 3 step.

 - traslazione di -meta_immagine
 - scale
 - traslazione di +meta_immagine*scale

Ciao

P.S. Se vuoi anche che sia centrata, il terzo step dovrebbe essere
  - traslazione di +metà_ImageView

Ti copincollo il codice che ho usato io, che però ha in mezzo anche una rotazione, ma credo che il metodo con pivot, faccia la stessa cosa
Codice (Java): [Seleziona]
        rotationMatrix.reset();
        rotationMatrix.postTranslate(-imageWidth / 2.0f, -imageHeight / 2.0f);
        rotationMatrix.postRotate((float) angle);
        rotationMatrix.postScale(scale, scale);
        rotationMatrix.postTranslate(frameWidth / 2, frameHeight / 2 );
        imageView.setImageMatrix(rotationMatrix);
« Ultima modifica: 25 Marzo 2015, 16:02:49 CET da arlabs »

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #4 il: 25 Marzo 2015, 20:47:39 CET »
0
Codice: [Seleziona]
rotationMatrix.reset();
        rotationMatrix.postTranslate(-imageWidth / 2.0f, -imageHeight / 2.0f);
        rotationMatrix.postRotate((float) angle);
        rotationMatrix.postScale(scale, scale);
        rotationMatrix.postTranslate(frameWidth / 2, frameHeight / 2 );
        imageView.setImageMatrix(rotationMatrix);

non ho capito una cosa...come mai prima usi prima "imageWidth / 2.0f, -imageHeight / 2.0f);" e dopo lo scale usi "frameWidth / 2, frameHeight / 2 "?

Grazie mille!!

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #5 il: 25 Marzo 2015, 21:39:00 CET »
0
Perché vuoi portare il centro dell'immagine nel centro della view.

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #6 il: 26 Marzo 2015, 19:35:20 CET »
0
Scusa.. intendevo dire perché in uno usi -xxxxxx /2.0F e nell'altro invece xxxxxx / 2 (Quindi in uno usi il meno e soprattutto il 2.0F mentre nell'altro usi il /2) grazie

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #7 il: 27 Marzo 2015, 10:22:50 CET »
0
Per nessun motivo, mi è venuto così.

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #8 il: 27 Marzo 2015, 17:09:05 CET »
0
Niente..per ora non riesco..
per capire dove sbaglio ho inserito due textview (cx e cy) che dovrebbero visualizzare le dimensioni in tempo reale dell'immagine che viene scalata (imageView1) ma non so perchè mi restituisce sempre cx=1920 e cy=1080, anche se viene scalata correttamente..

Codice: [Seleziona]
package com.example.marco.cefakereveal;


import java.io.IOException;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.graphics.Matrix;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.ImageView;
import android.widget.TextView;

public class CE_Fake_Reveal extends Activity implements SurfaceHolder.Callback{

    ImageView img;
    private Matrix matrix = new Matrix();
    private float scale = 1f;
    private ScaleGestureDetector SGD;
    TextView cx;
    TextView cy;

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_ce__fake__reveal);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        img = (ImageView)findViewById(R.id.imageView1);
        cx = (TextView)findViewById(R.id.couno);
        cy = (TextView)findViewById(R.id.codue);

        getWindow().setFormat(PixelFormat.UNKNOWN);
        surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        SGD = new ScaleGestureDetector(this,new ScaleListener());

    }



    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
// TODO Auto-generated method stub
        if(previewing){
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {
                camera.setPreviewDisplay(surfaceHolder);
                Camera.Parameters parameters = camera.getParameters();
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                camera.setParameters(parameters);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        SGD.onTouchEvent(ev);

        return true;
    }

    private class ScaleListener extends ScaleGestureDetector.
            SimpleOnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            scale *= detector.getScaleFactor();
            scale = Math.max(0.1f, Math.min(scale, 5.0f));
            matrix.setScale(scale, scale);
            img.setImageMatrix(matrix);
            cx.setText(String.valueOf(img.getWidth()));
            cy.setText(String.valueOf(img.getHeight()));

            return true;

        }
    }


}

Qua c'è il codice xml:
Codice: [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:weightSum="1">

    <SurfaceView
        android:id="@+id/camerapreview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

    <ImageView
        android:id="@+id/imageView1"

        android:scaleType="matrix"
        android:src="@drawable/ce"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Cx"
        android:id="@+id/couno"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Cy"
        android:id="@+id/codue"
        android:layout_below="@+id/couno"
        android:layout_alignParentStart="true" />


</RelativeLayout>

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #9 il: 27 Marzo 2015, 17:37:24 CET »
0
Innanzitutto non hai usato la setScale con pivot, né fatto la doppia traslazione che ho fatto io. Quindi non può funzionare.
Il metodo con la matrice è molto a basso livello. la trasformazione è fra le coordinate pixel dell'immagine e le coordinate pixel della View.
Quindi devi conoscerle. Tu quindi non le hai nemmeno lette.
Se vuoi far fare al Framwork e toglierti d'impiccio puoi usare una ScaleDrawable (ScaleDrawable | Android Developers)
[EDIT] Lascia perdere gli ScaleDrawable, non gli puoi modificare lo scale da codice, a quanto pare.


Secondo la ImageView è centrata in mezzo al layout con wrapContent, quindi sarà, immagino. Piccolina.
Se vuoi poterla scalare fino a coprire tutt la la SurfaceView devi farla uguale a quella.
Quindi usa fill_parent;

Codice (XML): [Seleziona]
    <ImageView
       android:id="@+id/imageView1"

       android:scaleType="matrix"
       android:src="@drawable/ce"
       android:layout_height="fill_parent"
       android:layout_width="fill_parent" />

P.S. Attenzione nella onCreate, non sono ancora state misurate le View, quindi non puoi leggerne le dimensioni (ti torna 0). Puoi usare un OnLayoutChangeListener che viene invocato appena una View è stata misurata ed è visibile.
« Ultima modifica: 27 Marzo 2015, 17:48:08 CET da arlabs »

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #10 il: 27 Marzo 2015, 20:32:29 CET »
0
Allora confermo, non ci ho capito niente..riparto dall'inizio, ma ho bisogno di capire una cosa:
imageWidth, imageHeight, frameWidth e frameHeight.
Cosa sono e come li recupero?

grazie mille per la pazienza!

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #11 il: 30 Marzo 2015, 11:36:45 CEST »
0
Io ho usato questo codice:
Codice (Java): [Seleziona]
        final float imageWidth = (float)imageView.getDrawable().getIntrinsicWidth();
        final float imageHeight = (float)imageView.getDrawable().getIntrinsicHeight();
        float frameHeight = imageView.getHeight();
        float frameWidth = imageView.getWidth();

Ti ripeto che questo non lo puoi fare nella OnCreate (nemmeno nella OnResume).
Se il tuo metodo di aggiornamento si chiama, ad esempio updateScale, metti questo pezzo di codice nella OnCreate:

Codice (Java): [Seleziona]
            img.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
                {
                    updateScale();
                }
            });

Ciao.

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #12 il: 01 Aprile 2015, 21:49:11 CEST »
0
Ok, ho capito, più o meno...
non ho capito però cosa intendi per metodo di aggiornamento.. :-(

nel mio codice qual'è??

Codice: [Seleziona]
package com.example.marco.cefakereveal;


import java.io.IOException;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.graphics.Matrix;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.ImageView;
import android.widget.TextView;


public class CE_Fake_Reveal extends Activity implements SurfaceHolder.Callback{

    ImageView img;
    private Matrix matrix = new Matrix();
    private float scale = 0.2f;
    private ScaleGestureDetector SGD;
    TextView cx;
    TextView cy;
    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    final float imageWidth = (float)img.getDrawable().getIntrinsicWidth();
    final float imageHeight = (float)img.getDrawable().getIntrinsicHeight();
    float frameHeight = img.getHeight();
    float frameWidth = img.getWidth();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_ce__fake__reveal);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        img = (ImageView)findViewById(R.id.imageView1);
        cx = (TextView)findViewById(R.id.couno);
        cy = (TextView)findViewById(R.id.codue);

        getWindow().setFormat(PixelFormat.UNKNOWN);
        surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        SGD = new ScaleGestureDetector(this,new ScaleListener());


        img.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
            {
                cosacimetto();
            }
        });
    }



    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        SGD.onTouchEvent(ev);

        return true;
    }






    private class ScaleListener extends ScaleGestureDetector.
            SimpleOnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector detector) {


            scale *= detector.getScaleFactor();
            scale = Math.max(0.03f, Math.min(scale, 0.2f));
          //  matrix.setScale(scale, scale);
            matrix.reset();
            matrix.postTranslate(-imageWidth / 2.0f, -imageHeight / 2.0f);
            matrix.postScale(scale, scale);
            matrix.postTranslate(frameWidth / 2, frameHeight / 2 );
            img.setImageMatrix(matrix);
            cx.setText(String.valueOf(scale));


            return true;

        }
    }






/* *************************************************/
/* Ora inizia il codice che riguarda la fotocamera */
/* *************************************************/





    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
// TODO Auto-generated method stub
        if(previewing){
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {
                camera.setPreviewDisplay(surfaceHolder);
                Camera.Parameters parameters = camera.getParameters();
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                camera.setParameters(parameters);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }




}

Offline arlabs

  • Utente normale
  • ***
  • Post: 434
  • Respect: +49
    • Mostra profilo
  • Dispositivo Android:
    GalaxyS6, Nexus5
  • Play Store ID:
    AR Labs
  • Sistema operativo:
    Windows 10
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #13 il: 02 Aprile 2015, 10:27:45 CEST »
+1
Nel tuo codice non c'è.
Puoi creare un metodo updateScale da chiamare nella ScaleListener.onScale

Lo stesso metodo dovresti chiamarlo in inizializzazione dell'Activity, ma non direttamente, nella onLayoutChange.

Questo tuo metodo potrebbe sembrare qualcosa del tipo:

Codice (Java): [Seleziona]
void updateScale()
{
        final float imageWidth = (float)img.getDrawable().getIntrinsicWidth();
        final float imageHeight = (float)img.getDrawable().getIntrinsicHeight();
        float frameHeight = img.getHeight();
        float frameWidth = img.getWidth();

        matrix.reset();
        matrix.postTranslate(-imageWidth / 2.0f, -imageHeight / 2.0f);
        matrix.postScale(scale, scale);
        matrix.postTranslate(frameWidth / 2.0f, frameHeight / 2.0f );
        img.setImageMatrix(matrix);
}

Poi nella OnCreate metti:
Codice (Java): [Seleziona]
        scale = 1.0f;

        img.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
            {
                updateScale();
            }
        });

La tua onScale invece diventa:

Codice (Java): [Seleziona]
        @Override
        public boolean onScale(ScaleGestureDetector detector) {

            scale *= detector.getScaleFactor();
            scale = Math.max(0.03f, Math.min(scale, 0.2f));

            updateScale();
           
            cx.setText(String.valueOf(scale));

            return true;
        }


Ciao

Offline smartgatto

  • Utente junior
  • **
  • Post: 97
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S5
  • Sistema operativo:
    Windows 7
Re:Metodo di resize immagine "Matrix" e centrarlo nello schermo..
« Risposta #14 il: 03 Aprile 2015, 10:50:29 CEST »
0
Perfetto, ora sono riuscito a far funzionare tutto!!
Grazie 10.000 !!!