2x1=10

because numbers are people, too
Persönliches
Fotografie
Programmierung
    • Android: Bitmap von SurfaceView erzeugen

      Um einen Screen­shot ein­er View zu erzeu­gen, wird gemein­hin emp­fohlen, den Draw­ing Cache der View zu miss­brauchen, indem man ihn gegebe­nen­falls erzwingt und dann kopiert:

      public class LameFooView extends SurfaceView {
      
      	@NotNull
      	public final Bitmap getScreenCopy() {
      		boolean cacheEnabled = isDrawingCacheEnabled();
      		if (!cacheEnabled) buildDrawingCache();
      
      		Bitmap cache = getDrawingCache(); // <-- there be dragons
      		Bitmap screenshot = new Bitmap(cache); 
      
      		// destroy the cache if it wasn't enabled, then return
      		if(!cacheEnabled) destroyDrawingCache();
      		return screenshot;
      	}
      
      }
      

      Aus Grün­den pur­er Gehäs­sigkeit lieferte der Aufruf von getDrawingCache() in mein­er vererbten SurvaceView allerd­ings immer null, wom­it die ganze Aktion gestor­ben war.

      Faszinieren­der­weise funk­tion­ierte stattdessen der Ansatz, die View erneut auf eine eigene Bitmap zu ren­dern, indem man der eige­nen draw()-Meth­ode ein raubkopiertes Canvas übergibt:

      public class AwesomeFooView extends SurfaceView {
      
      	@NotNull
      	public final Bitmap getScreenCopy() {
      		Bitmap bitmap = Bitmap.createBitmap(
      			getWidth(), 
      			getHeight(), 
      			Bitmap.Config.ARGB_8888
      			);
      
      		Canvas temporaryCanvas = new Canvas(bitmap);
      		draw(temporaryCanvas); // Voodoo.
      	
      		return bitmap;
      	}
      
      }
      

      Wer also vor einem ähn­lichen Prob­lem ste­ht — so geht es auch.

      Pro-Tipp

      Wie der Doku­men­ta­tion von View.draw() zu ent­nehmen ist, muss die View zum Zeit­punkt des Abpausens bere­its den Lay­out-Durch­gang durch­laufen haben. Dies lässt sich mit einem gewis­senhaften Aufruf von View.layout() erzwin­gen:

      measure(getWidth(), getHeight());
      layout(0, 0, getWidth(), getHeight());
      

      Prob­lem gelöst.

      November 2nd, 2011 GMT +2 von
      Markus
      2011-11-2T02:57:17+02:00 2011-11-2T05:44:19+02:00 · 3 Kommentare
      Bitmap Canvas
      Android

      3 Kommentare auf „Android: Bitmap von SurfaceView erzeugen“

      1. Jochen sagt:
        Samstag, August 25th, 2012 04:24 am GMT +2 um 04:24 Uhr

        Guten Mor­gen!

        Ich bin bere­its seit zwei Tagen nach ein­er Lösung, um einen Screen­shot von ein­er Sur­face­View zu machen, in der die Cam­era Pre­view angezeigt wird. Meine Sur­face­View habe ich in mein­er main.xml angelegt.

        Ich habe gele­sen, dass es schein­bar nicht möglich sein soll, von der Sur­face­View einen Screen­shot zu machen, aber wenn ich auf meinem Android Endgerät mit dem Hand­ballen über das Dis­play fahre, so erhalte ich ja auch einen Screen­shot.

        Hast Du ggf. eine Idee, wie ich das pro­gram­ma­tisch umset­zen kön­nte? Ich verzweifel so langsam daran.

        Ich benötige es, um ein Image von der Cam­era und divers­er Over­lays zu erhal­ten. Die Cam­era API bringt mich da nicht weit­er.

        Derzeit nehme ich ein Foto über die Cam­era API auf und erstelle gle­ichzeit­ig einen Screen­shot der Over­ly Ele­mente und füge diese dann mit­tel Can­vas zusam­men um sie dann als ein Bild zu speichern.…seeeehr langsam bzw. sehr Resource­na­gres­siv 🙁

        Wäre super, wenn Du einen Tipp hättest.

        Danke und Grüße Jochen

        Antworten
        • K. sagt:
          Freitag, September 14th, 2012 12:57 pm GMT +2 um 12:57 Uhr

          Hal­lo Jochen,

          hast du mit­tler­weile eine Lösung für das Prob­lem gefun­den?
          Ich habe näm­lich genau das gle­iche Prob­lem und komme ger­ade auch nicht wirk­lich weit­er.

          Wäre eine große Hil­fe.
          Danke

          Antworten
      2. Jochen Kapalla sagt:
        Sonntag, September 16th, 2012 10:50 am GMT +2 um 10:50 Uhr

        Hal­lo,

        ja ich habe bere­its eine Lösung gefun­den. Man muss die onPre­viewFrame über­schreiben und über YUV420 ver­wen­den.

        Die onPre­viewFrame über­schreibe ich ein­fach in mein­er onClick(View v) wenn ich die Cam­era Pre­view aktiviere:

        @Override
        public void onClick(View v) {
        	long ce = v.getId();
        
        	if (ce == R.id.open) {
        		 if (!previewing) {
        			previewing = true;
        			camera = Camera.open();
        			if (camera != null) {
        				try {
        					camera.setPreviewDisplay(surfaceHolder);
        					camera.setDisplayOrientation(90);
        						
        					Parameters para = camera.getParameters();
        					//para.setRotation(180);
        					para.setPreviewSize(1280, 768);
        					camera.setParameters(para);
        					camera.setPreviewCallback(new PreviewCallback() {
        						
        						@Override
        						public void onPreviewFrame(byte[] data, Camera camera) {
        							int width = camera.getParameters().getPreviewSize().width;
        							int height = camera.getParameters().getPreviewSize().height;
        							      
        							System.out.println("Breite: "+width+" Höhe: "+height);
        							int[] rgb = decodeYUV420SP(data, width, height);
        							bmp = Bitmap.createBitmap(rgb, width, height, Bitmap.Config.ARGB_8888);
        						}
        					});
        					
        					camera.startPreview();
        				} catch (Exception e) {
        					e.printStackTrace();
        				}
        			}
        		}
        	} else if (ce == R.id.capture) {
        		saveScreenshot();
        	}
        
        }
        

        Zusät­zlich musst Du dann auch noch decodeYUV420SP definieren. Das habe ich direkt unter der onClick() gemacht:

        public int[] decodeYUV420SP(byte[] yuv420sp, int width, int height) {
        	final int frameSize = width * height;
        	int rgb[] = new int[width * height];
        	for (int j = 0, yp = 0; j > 1) * width, u = 0, v = 0;
        		for (int i = 0; i < width; i++, yp++) {
        			int y = (0xff & ((int) yuv420sp[yp])) - 16;
        			if (y < 0)
        				y = 0;
        			if ((i & 1) == 0) {
        				v = (0xff & yuv420sp[uvp++]) - 128;
        				u = (0xff & yuv420sp[uvp++]) - 128;
        			}
        			int y1192 = 1192 * y;
        			int r = (y1192 + 1634 * v);
        			int g = (y1192 - 833 * v - 400 * u);
        			int b = (y1192 + 2066 * u);
        			r = r  262143 ? 262143 : r);
        			g = g  262143 ? 262143 : g);
        			b = b  262143 ? 262143 : b);
        			rgb[yp] = 0xff000000 | ((r <> 2) & 0xff00) | ((b >> 10) & 0xff);
        		}
        	}
        	return rgb;
        }
        

        Und meine Screen­shots spe­ichere ich so ab:

        public void saveScreenshot() {
        	File file = new File(mScreenshotPath + "/" + System.currentTimeMillis()
        			+ ".jpg");
        	FileOutputStream fos;
        	
        	try {
        		fos = new FileOutputStream(file);
        		bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        		fos.close();
        	} catch (Exception e) {
        		// TODO: handle exception
        	}
        }
        

        Wobei ich mScreen­shot­Path vor­ab definiert habe:

        private String mScreenshotPath = Environment.getExternalStorageDirectory() + "/MeineBilder";
        

        Der Ord­ner MeineBilder muss natür­lich auch noch existieren:

        private void createFolder() {
        	File dir = Environment.getExternalStorageDirectory();
        	File myDir = new File(dir, "MeineBilder");
        	if (myDir.exists() && myDir.isDirectory()) {
        
        	} else {
        		boolean created = myDir.mkdir();
        		System.out.println("Folder created : " + created);
        	}
        }
        

        Meine Sur­face­View habe mit­tels XML hinzuge­fügt in diesem Fall, aber ich glaube das spielt keine Rolle.

        Ich hoffe ich kon­nte Dir weit­er helfen 😉

        Grüße Jochen

        Antworten

      Hinterlasse einen Kommentar

      Hier klicken, um das Antworten abzubrechen.

    1. « newer
    2. 1
    3. …
    4. 34
    5. 35
    6. 36
    7. 37
    8. 38
    9. 39
    10. 40
    11. …
    12. 43
    13. older »
    • Kategorien

      • .NET
        • ASP.NET
        • Core
        • DNX
      • Allgemein
      • Android
      • Data Science
      • Embedded
      • FPGA
      • Humor
      • Image Processing
      • Kalman Filter
      • Machine Learning
        • Caffe
        • Hidden Markov Models
        • ML Summarized
        • Neural Networks
        • TensorFlow
      • Mapping
      • MATLAB
      • Robotik
      • Rust
      • Signal Processing
      • Tutorial
      • Version Control
    • Neueste Beiträge

      • Summarized: The E-Dimension — Why Machine Learning Doesn’t Work Well for Some Problems?
      • Use your conda environment in Jupyter Notebooks
      • Building OpenCV for Anaconda Python 3
      • Using TensorFlow’s Supervisor with TensorBoard summary groups
      • Getting an image into and out of TensorFlow
    • Kategorien

      .NET Allgemein Android ASP.NET Caffe Core Data Science DNX Embedded FPGA Hidden Markov Models Humor Image Processing Kalman Filter Machine Learning Mapping MATLAB ML Summarized Neural Networks Robotik Rust Signal Processing TensorFlow Tutorial Version Control
    • Tags

      .NET Accelerometer Anaconda Bitmap Bug Canvas CLR docker FPGA FRDM-KL25Z FRDM-KL26Z Freescale git Gyroscope Integration Drift Intent J-Link Linear Programming Linux Magnetometer Matlab Mono Naismith OpenCV Open Intents OpenSDA Optimization Pipistrello Player/Stage PWM Python Sensor Fusion Simulink Spartan 6 svn tensorflow Tilt Compensation TRIAD ubuntu Windows Xilinx Xilinx SDK ZedBoard ZYBO Zynq
    • Letzte Kommetare

      • Lecke Mio bei Frequency-variable PWM generator in Simulink
      • Vaibhav bei Use your conda environment in Jupyter Notebooks
      • newbee bei Frequency-variable PWM generator in Simulink
      • Markus bei Using TensorFlow’s Supervisor with TensorBoard summary groups
      • Toke bei Using TensorFlow’s Supervisor with TensorBoard summary groups
    • Blog durchsuchen

    • November 2011
      M D M D F S S
      « Apr   Nov »
       123456
      78910111213
      14151617181920
      21222324252627
      282930  
    • Self

      • Find me on GitHub
      • Google+
      • Me on Stack­Ex­change
      • Ye olde blog
    • Meta

      • Anmelden
      • Beitrags-Feed (RSS)
      • Kommentare als RSS
      • WordPress.org
    (Generiert in 0,373 Sekunden)

    Zurück nach oben.