Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Pinch and Zoom on Android SurfaceView

I am using a SurfaceView to display a large image (usually bigger than the screen, but not always) in an Android App. This is really trivially simple graphics, and it is easy to implement scrolling using an OnTouchListener or GestureDetector. Graphics run in a Render loop, but performance seems to be more than adequate for all real devices (the emulator can be a bit of a pain, though).

I'm considering implementing Pinch and Zoom on the image as well, but I would prefer to avoid having to go to OpenGL, since I have very little experience with OpenGL and using OpenGL seems like pretty much overkill for something this simple.

It seems as if the android.graphics.Camera class might allow me to implement the zoom functionality that I would like.

Does anyone know of any good examples that show the implementation of a pinch-zoom like functionality on a basic Android SurfaceView?

Also if you have implemented something like this, any thoughts on performance? Is OpenGL worth the extra hassle, given that what is required here is so simple?


Is the question unclear here, or am I missing some blindingly obvious documentation/code on the Android developer site that I should have found?

like image 824
Michael A. Avatar asked May 04 '12 08:05

Michael A.


1 Answers

OK - having finally had time to really work and research on this for some length of time, I actually found a solution that solves the problem I had.

The solution relies on the BitmapRegionDecoder (API10+). What this does is allow the app to load in a part of a bitmap, rather than attempting to load the entire bitmap in one go.

The essence of the solution:

  1. A downsampled version of the entire bitmap is kept in memory. Because this version is downsampled, it can be kept there permanently.
  2. A thread loads in the current viewport (or a bit more) of the bitmap to memory continually (using BitmapRegionDecoder). As this is at most slightly larger than the screen, this should also fit comfortably in memory.
  3. The rendering thread draws the appropriate version to the Canvas; i.e., if you are zooming out or the bitmap is not available (e.g., because it is loading in the background), then the downsampled version is used.
  4. Pan, Fling, and Zoom are handled with GestureListeners.

Credit goes to John Lombardo for the first implementation of the idea I've found.

I open-sourced my own implementation along with some of my other utility classes at https://github.com/micabyte/android_game

It's a pretty recent implementation, so its not had the baptism of fire from real users at this time. However, I've run tests with displaying 8000x4000 pixel bitmaps and had no issues so far. Performance certainly seems adequate for my needs.

like image 163
Michael A. Avatar answered Dec 22 '22 01:12

Michael A.