Autore Topic: Immagine da usare come filtro sopra una surfaceview....  (Letto 2041 volte)

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
Immagine da usare come filtro sopra una surfaceview....
« il: 01 Agosto 2012, 00:21:00 CEST »
0
Allora ragazzi mi serve una mano, sto creando un apk che gestisce la telecamera tramite un surfaceview...ho creato il tutto è funziona anche lo swicth con la camera front e back ed i tasti cattura immagine e flash...

mo ho creato un button effetti filtri

Codice (Java): [Seleziona]
mSurfaceView.setBackgroundResource(R.drawable.filter_01);
in questo caso cliccando setto il background della surfaceview, è un filtro creato in photoshop funziona nel senso che esce e sotto posso scattare la foto.
ma nel momento che scatto e vado a visionare la foto nella gallery mi esce la foto senza questo filtro...
vorrei sapere come si fa ad usare un immagine tipo overleys da mettere sopra alla surfaceview...spero di essere stato chiaro nella spiegazione...attendo risposte grazie in anticipo..... :-P

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #1 il: 01 Agosto 2012, 01:41:27 CEST »
0
Quel overlay viene fatto dalla GPU nel modelli di fascia alta o dalla povera CPU per quelli di fascia bassa ed esiste solo nel display del telefono, quando salvi nella gallery API di Android salva solo overlay della camera.

Se vuoi la sovrapposizione finale devi fare tu i calcoli e non sono semplici (l'immagine della fotocamera non è RGB) e sa fatto in Java sono lenti.

P.S. Ti prego non dire: "filtro creato in photoshop" ma la massimo: "una immagine creata con i filtri di Photoshop".
adb logcat | tee /tmp/logcat | grep TAG

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #2 il: 01 Agosto 2012, 02:09:55 CEST »
0
una immagine creata con i filtri di Photoshop :D infatti hai ragione!

c'è qualke guida qualke tutorial....a riguardo?

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #3 il: 01 Agosto 2012, 09:51:33 CEST »
0
Non ho mai visto tutorial completi sull'argomenti.

Qui trovi una versione Java per convertire una immagine RAW presa dalla fotocamera YUV in RGB:

http://stackoverflow.com/questions/9325861/converting-yuv-rgbimage-processing-yuv-during-onpreviewframe-in-android

è lenta, Java non ha i tipi non segnati quindi obbliga il programmatore a gestire i numeri in modo particolare rallentando ulteriormente l'esecuzione del codice. Se cerchi esistono versioni in C molto più veloci ma sei obbligato ad usare NDK di Android.

Le sovrapposizioni delle immagini puoi usare "Canvas.drawBitmap", stando attento ad usare immagini con la stessa dimensione e di abilitare il calcolo con il canale alpha.
adb logcat | tee /tmp/logcat | grep TAG

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #4 il: 01 Agosto 2012, 20:42:40 CEST »
0
non voglio uscire fuori topic...mo perchè non ci sto capendo nulla...

Codice (Java): [Seleziona]
PictureCallback pictureCallback = new PictureCallback(){
           
               
                public void onPictureTaken(byte[] _data, Camera _camera) {
               
                        Bitmap bmp;
                        bmp = BitmapFactory.decodeByteArray(_data, 0, _data.length);
                       
                        //quando vado a visualizzare la foto nella gallery width e height sono impostate di default
                        //e la rotazione risulta 0
                       


                        int m_w = 480;
                        int m_h = 800;
                        Matrix matrix = new Matrix();
                        matrix.postRotate(90);
                        Bitmap.createBitmap(bmp, 0, 0, m_w, m_h, matrix, true);
                   
                int imageNum = 0;
                File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Camera");
                imagesFolder.mkdirs();
                String fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
                File output = new File(imagesFolder, fileName);
               
                while (output.exists()){
                    imageNum++;
                    fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
                    output = new File(imagesFolder, fileName);
               
                }
               
                OutputStream outStream = null;
               
                try {
                 
                 outStream = new FileOutputStream(output);
                 bmp.compress(Bitmap.CompressFormat.JPEG, 85, outStream);
                 outStream.flush();
                 outStream.close();
                 Log.i("CameraActivity", "bmp saved_"+ bmp.getHeight() + "x" + bmp.getWidth());
                 
                }
                catch(Exception e){
                Log.e("CameraActivity", e.getLocalizedMessage());      
                }
               
                Toast.makeText(CameraActivity.this, "IMAGE SAVED", Toast.LENGTH_LONG).show();
               
               
                mCamera.startPreview();
« Ultima modifica: 01 Agosto 2012, 20:45:17 CEST da xwilly84 »

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #5 il: 02 Agosto 2012, 00:54:41 CEST »
0
Usi la Camera.PictureCallback la quale dalle prove che ho fatto ritorna già una JPEG. Con la Camera.PreviewCallback ritorna i dati RAW non elaborati senza nessuna perdita. Vedo che decodifichi il JPEG in una bitmap per poi codificarlo di nuovo in JPEG, è come fare la fotocopia di una fotocopia, perdi informazione, Il JPEG è un algoritmo a perdita. Se vedi questo esempio, nel evento onPictureTaken il file JPEG è il dato ricevuto:

Android Camera API - Tutorial

Comunque se vuoi usare il JPEG e la decodifichi con BitmapFactory.decodeByteArray non ottieni la bitmap originale della camera. Ottieni una immagine con del rumore aggiunto dall'algoritmo di compressione JPEG. Dalla bitmap che ottieni puoi disegnarci sopra con Canvas.drawBitmap con una immagine con il canale alpha. Un esempio di utilizzo:

About Android: Combine two images in android java

P.S. Nel tuo codice quel while può bloccare il thread principale, è meglio fare questi tipi di elaborazioni in un thread separato di lavoro.
adb logcat | tee /tmp/logcat | grep TAG

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #6 il: 04 Agosto 2012, 03:41:02 CEST »
0
Allora ho seguito il tuo consiglio gestisco separatamente tramite AsyncTask il salvataggio della foto in questo modo


Codice (Java): [Seleziona]
PictureCallback pictureCallback = new PictureCallback(){
            public void onPictureTaken(byte[] _data, Camera _camera) {
               
                   
                    new SavePhotoTask().execute(_data);
                   
                    Toast.makeText(CameraActivity.this, "IMAGE SAVED", Toast.LENGTH_LONG).show();
                   
                    mCamera.startPreview();
                 
            }
               
        };


Ho creato la classe che estende AsyncTask, in questo caso l'applicazione non si blocca ed il while che mi verifica se esiste il file non da problemi...tutto regolare ;-)

Codice (Java): [Seleziona]
class SavePhotoTask extends AsyncTask<byte[], String, String> {
           
                @Override
            protected String doInBackground(byte[]... jpeg) {
             
                        int imageNum = 0;
            File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Camera");
            imagesFolder.mkdirs();
            String fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
            File output = new File(imagesFolder, fileName);
           
               
           
            while (output.exists()){
                imageNum++;
                fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
                output = new File(imagesFolder, fileName);
           
            }
           
            OutputStream outStream = null;     
           
                try {
                 
                 outStream = new FileOutputStream(output);
                 outStream.write(jpeg[0]);
                 outStream.flush();
                 outStream.close();
                 Log.i("CameraActivity", "bmp saved ");
                 
                }
                catch(Exception e){
                Log.e("CameraActivity", e.getMessage());       
                }
               
               

              return(null);
            }
          }



Ho modificato anche il metodo switch camera che richiamo anche in onResume è va una meraviglia...per adesso prendo PictureSize  e PreviewSize tramite get(0) quelli di default

Codice (Java): [Seleziona]
public static Camera showCamera(){
           
               
           
            if (camera_open==0){
                 
                try {
                        mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
                        mCamera.setDisplayOrientation(90);
                       
                        p = mCamera.getParameters();
                                List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
                                List<Camera.Size> pictureSizes = p.getSupportedPictureSizes();
                                Camera.Size preSizes = previewSizes.get(0);
                                Camera.Size picSizes = pictureSizes.get(0);
                               
                                p.setPreviewSize(preSizes.width, preSizes.height);
                        p.setPictureSize(picSizes.width, picSizes.height);
                                p.setRotation(90);
                            mCamera.setParameters(p);
                            Log.i("CameraActivity", "PreviewSizes_Back " + preSizes.width + " x " + preSizes.height);
                            Log.i("CameraActivity", "PictureSize_Back " + picSizes.width + " x " + picSizes.height);
                    }
                    catch (Exception e){
                        Log.e("CameraActivity", e.getLocalizedMessage());
                    }
                   
            }else if (camera_open==1){
                       
                 try {
                             mCamera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);
                             mCamera.setDisplayOrientation(90);
                             
                             p = mCamera.getParameters();
                             List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
                                 List<Camera.Size> pictureSizes = p.getSupportedPictureSizes();
                                 Camera.Size preSizes = previewSizes.get(0);
                                 Camera.Size picSizes = pictureSizes.get(0);
                                 
                                 p.setPreviewSize(preSizes.width, preSizes.height);
                         p.setPictureSize(picSizes.width, picSizes.height);
                             p.setRotation(270);
                             mCamera.setParameters(p);
                             Log.i("CameraActivity", "PreviewSizes_Front " + preSizes.width + " x " + preSizes.height);
                             Log.i("CameraActivity", "PictureSize_Front " + picSizes.width + " x " + picSizes.height);
                           
                            }
                            catch (Exception e){
                             Log.e("CameraActivity", e.getMessage());
                            }
               
               
                }
                return mCamera;
           
           
           
        }

Adesso il metodo Bitmap mi fa perdere info, se io con un click su un button es: "Overlays" setto il background della mia SurfaceView funziona....quindi ho la mia immagine drawable che si vede in tempo reale sopra la preview, ma mi chiedo, come posso al momento del salvataggio della foto applicare questa modifica sulla foto scattata?

Grazie per le tue risposte ;-)

Offline iceweasel

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 878
  • Respect: +147
    • Mostra profilo
  • Dispositivo Android:
    LGE P990 - Google Nexus 5
  • Sistema operativo:
    Linux Debian Sid
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #7 il: 04 Agosto 2012, 14:10:22 CEST »
0
Se studi l'esempio del SDK sulla camera:

GrepCode: com.example.android.apis.graphics.CameraPreview (.java) - Class - Source Code View

c'è un metodo che cerca la risoluzione migliore disponibile.

Decidi tu se usare la Camera.PictureCallback (JPEG) o la Camera.PreviewCallback (RAW) per prendere l'immagine, dopo devi fare le elaborazioni previste con i Canvas come descritto in precedenza.

adb logcat | tee /tmp/logcat | grep TAG

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
R: Immagine da usare come filtro sopra una surfaceview....
« Risposta #8 il: 04 Agosto 2012, 17:12:56 CEST »
0
Mi sa che conviene usare in Raw che come hai detto tu per esperienza non perdo info, perche si lavorando cmq con jpg con quello che dovrei fare io rischio di perdere la qualità della foto...provo anche a seguire la guida per trovare la risoluzione migliore.


Inviato dal mio Nexus S con Tapatalk 2

Offline xwilly84

  • Nuovo arrivato
  • *
  • Post: 19
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Play Store ID:
    Orange Mobile
  • Sistema operativo:
    Win 7 x64
Re:Immagine da usare come filtro sopra una surfaceview....
« Risposta #9 il: 08 Agosto 2012, 04:14:22 CEST »
0
ormai mi sto incasinando non so come fare....

Codice (Java): [Seleziona]
class SavePhotoTask extends AsyncTask<byte[], String, String> {
           
                @Override
            protected String doInBackground(byte[]... jpeg) {
             
                        int imageNum = 0;
            File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Camera");
            imagesFolder.mkdirs();
            String fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
            File output = new File(imagesFolder, fileName);
           
               
           
            while (output.exists()){
                imageNum++;
                fileName = "bmp_" + String.valueOf(imageNum) + ".jpg";
                output = new File(imagesFolder, fileName);
           
            }
           
            OutputStream outStream = null;      
           
                try {
                 
                 outStream = new FileOutputStream(output);
                 //qua salvo il mio file, come posso salvare in con bmp così ci posso applicare il metodo canvas col metodo iniziale
                 //quello che creavo la copia della foto mi dava errore
                 outStream.write(jpeg[0]);
                 outStream.flush();
                 outStream.close();
                 Log.i("CameraActivity", "bmp saved ");
                 
                }
                catch(Exception e){
                Log.e("CameraActivity", e.getMessage());        
                }
               
               

              return(null);
            }
          }