Android camera 如何保存image

1. Capture image 的保存

Camera 接收到onJpegPicture callback 后,

mActivity.getMediaSaveService().addImage(
	 jpegData, title, date, mLocation, width, height,
	orientation, exif, mOnMediaSavedListener, mContentResolver);
	
// Animate capture with real jpeg data instead of a preview frame.
mUI.animateCapture(jpegData, orientation, mMirror);

add Image:

122     public void addImage(final byte[] data, String title, Location loc,                                                                                     
123             int width, int height, int orientation, ExifInterface exif,
124             OnMediaSavedListener l, ContentResolver resolver) {
125         addImage(data, title, System.currentTimeMillis(), loc, width, height,
126                 orientation, exif, l, resolver);
127     } 

 97     public void addImage(final byte[] data, String title, long date, Location loc,
 98             int width, int height, int orientation, ExifInterface exif,
 99             OnMediaSavedListener l, ContentResolver resolver) {
100         if (isQueueFull()) {
101             Log.e(TAG, "Cannot add image when the queue is full");
102             return;
103         }
104         ImageSaveTask t = new ImageSaveTask(data, title, date,
105                 (loc == null) ? null : new Location(loc),
106                 width, height, orientation, exif, resolver, l);
107 
108         mMemoryUse += data.length;
109         if (isQueueFull()) {
110             onQueueFull();
111         }
112         t.execute();
113     }

 412     public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) {                                                                   
 413         // Decode jpeg byte array and then animate the jpeg
 414         DecodeTask task = new DecodeTask(jpegData, orientation, mirror);
 415         task.execute();
 416     }

接下来创建AsyncTask来完成后台保存工作和decoder工作


AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.

When an asynchronous task is executed, the task goes through 4 steps:

  1. onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
  2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
  3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
  4. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
接下来分别分析ImageSaveTask和DecodeTask

157     private class ImageSaveTask extends AsyncTask <Void, Void, Uri> {
183         @Override
184         protected void onPreExecute() {
185             // do nothing.
186         }
187 
188         @Override
189         protected Uri doInBackground(Void... v) {
190             Uri uri = null;
191             if (width == 0 || height == 0) {
192                 // Decode bounds
193                 BitmapFactory.Options options = new BitmapFactory.Options();
194                 options.inJustDecodeBounds = true;
195                 BitmapFactory.decodeByteArray(data, 0, data.length, options);
196                 width = options.outWidth;
197                 height = options.outHeight;
198             }
199             uri = Storage.addImage(
200                     resolver, title, date, loc, orientation, exif, data, width, height);
201             uriMap.put(title,uri);
202             mMemoryUse -= data.length;
203             return uri;
204         }
205 
206         @Override
207         protected void onPostExecute(Uri uri) {
208             if (listener != null && uri != mDeleteUri) listener.onMediaSaved(uri);
209             //if Queue is not Full and the previously status is different with it, the queue avaiable
210             if (!isQueueFull() && isQueueFull() != mPreviouslyFull) onQueueAvailable();
211         }
212     }
ImageSaveTask:

step1. add Image

step2: generate Uri

step3: Mediasaved --save the uri

184     private class DecodeTask extends AsyncTask<Void, Void, Bitmap> {
 195         @Override
 196         protected Bitmap doInBackground(Void... params) {
 197             // Decode image in background.
 198             Bitmap bitmap = CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR);
 199             if (mOrientation != 0 || mMirror) {
 200                 Matrix m = new Matrix();
 201                 if (mMirror) {
 202                     // Flip horizontally
 203                     m.setScale(-1f, 1f);
 204                 }
 205                 m.preRotate(mOrientation);
 206                 return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m,
 207                         false);
 208             }
 209             return bitmap;
 210         }
 211 
 212         @Override
 213         protected void onPostExecute(Bitmap bitmap) {
 214             //If detect blink, don't show animation
 215             if (!mModule.getBlinkFlag()) {
 216                 mPreviewThumb.setImageBitmap(bitmap);
 217                 mAnimationManager.startCaptureAnimation(mPreviewThumb);
 218             }
 219         }
 220     }              


781     public static Bitmap downSample(final byte[] data, int downSampleFactor) {
782         final BitmapFactory.Options opts = new BitmapFactory.Options();
783         // Downsample the image
784         opts.inSampleSize = downSampleFactor;
785         return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
786     }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值