From bfab14264c6b8aee87d0383df8c00ca844c3bee4 Mon Sep 17 00:00:00 2001 From: jinwu Date: Fri, 21 Sep 2018 18:33:37 +0800 Subject: SnapdraongCamera:add HEIF support add option to allow user to save captured image with HEIF format. Change-Id: I267b783bf7e4f41f523ef2ac4fbb734657b8e827 CRs-Fixed: 2312764 --- src/com/android/camera/CaptureModule.java | 19 ++++++ src/com/android/camera/MediaSaveService.java | 68 ++++++++++++++++++++++ src/com/android/camera/SettingsActivity.java | 1 + src/com/android/camera/SettingsManager.java | 11 ++++ src/com/android/camera/Storage.java | 66 +++++++++++++++++++-- .../camera/imageprocessor/PostProcessor.java | 16 ++++- 6 files changed, 173 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java index 7bfee3041..0c93f9b73 100755 --- a/src/com/android/camera/CaptureModule.java +++ b/src/com/android/camera/CaptureModule.java @@ -31,6 +31,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.graphics.Point; @@ -2422,6 +2423,24 @@ public class CaptureModule implements CameraModule, PhotoController, byte[] bytes = getJpegData(image); + if (mSettingsManager.getSavePictureFormat() == + SettingsManager.HEIF_FORMAT) { + String value = mSettingsManager.getValue( + SettingsManager.KEY_JPEG_QUALITY); + int qualityNumber = getQualityNumber(value); + mActivity.getMediaSaveService().addHEIFImageFromJpeg(bytes, + title,date,null,image.getWidth(),image.getHeight(), + 0,null,mContentResolver, + mOnMediaSavedListener,qualityNumber,"heif"); + image.close(); + if (mLongshotActive) { + mLastJpegData = bytes; + } else { + mActivity.updateThumbnail(bytes); + } + return; + } + if (image.getFormat() == ImageFormat.RAW10) { mActivity.getMediaSaveService().addRawImage(bytes, title, "raw"); diff --git a/src/com/android/camera/MediaSaveService.java b/src/com/android/camera/MediaSaveService.java index 217f44f27..8394162db 100644 --- a/src/com/android/camera/MediaSaveService.java +++ b/src/com/android/camera/MediaSaveService.java @@ -163,6 +163,23 @@ public class MediaSaveService extends Service { t.execute(); } + public void addHEIFImageFromJpeg(byte[] data, String title, long date, Location loc, + int width, int height, int orientation, ExifInterface exif, + ContentResolver resolver, OnMediaSavedListener listener, + int qualitiy, String pictureFormat) { + if (isQueueFull()) { + Log.e(TAG, "Cannot add image when the queue is full"); + return; + } + HEIFImageSaveTask t = new HEIFImageSaveTask(data, title, date, loc, width, height, orientation, + exif, resolver, listener, qualitiy, pictureFormat); + mMemoryUse += data.length; + if (isQueueFull()) { + onQueueFull(); + } + t.execute(); + } + public void addClearsightImage(byte[] clearsight, GImage bayer, GDepth.DepthMap depthMap, String title, long date, Location loc, int width, int height, int orientation, ExifInterface exif, @@ -328,6 +345,57 @@ public class MediaSaveService extends Service { } } + private class HEIFImageSaveTask extends AsyncTask { + private byte[] data; + private String title; + private long date; + private Location loc; + private int width, height; + private int orientation; + private ExifInterface exif; + private ContentResolver resolver; + private OnMediaSavedListener listener; + private int quality; + private String pictureFormat; + + public HEIFImageSaveTask(byte[] data, String title, long date, Location loc, + int width, int height, int orientation, ExifInterface exif, + ContentResolver resolver, OnMediaSavedListener listener, + int quality,String pictureFormat) { + this.data = data; + this.title = title; + this.date = date; + this.loc = loc; + this.width = width; + this.height = height; + this.orientation = orientation; + this.exif = exif; + this.resolver = resolver; + this.listener = listener; + this.quality = quality; + this.pictureFormat = pictureFormat; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected Uri doInBackground(Void... params) { + return Storage.addHeifImage( + resolver,title,date,loc,orientation,exif,data, + width,height,quality,pictureFormat); + } + + @Override + protected void onPostExecute(Uri uri) { + boolean previouslyFull = isQueueFull(); + mMemoryUse -= data.length; + if (isQueueFull() != previouslyFull) onQueueAvailable(); + } + } + private class ImageSaveTask extends AsyncTask { private byte[] data; private String title; diff --git a/src/com/android/camera/SettingsActivity.java b/src/com/android/camera/SettingsActivity.java index e413090a4..e0330063a 100755 --- a/src/com/android/camera/SettingsActivity.java +++ b/src/com/android/camera/SettingsActivity.java @@ -452,6 +452,7 @@ public class SettingsActivity extends PreferenceActivity { private void initializePreferences() { updatePreference(SettingsManager.KEY_PICTURE_SIZE); + updatePreference(SettingsManager.KEY_PICTURE_FORMAT); updatePreference(SettingsManager.KEY_VIDEO_QUALITY); updatePreference(SettingsManager.KEY_EXPOSURE); updatePreference(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE); diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java index 7640cb53b..4346f2599 100755 --- a/src/com/android/camera/SettingsManager.java +++ b/src/com/android/camera/SettingsManager.java @@ -102,6 +102,8 @@ public class SettingsManager implements ListMenu.SettingsListener { public static final int SCENE_MODE_PROMODE_INT = SCENE_MODE_CUSTOM_START + 9; public static final int SCENE_MODE_DEEPZOOM_INT = SCENE_MODE_CUSTOM_START + 10; public static final int SCENE_MODE_DEEPPORTRAIT_INT = SCENE_MODE_CUSTOM_START + 11; + public static final int JPEG_FORMAT = 0; + public static final int HEIF_FORMAT = 1; public static final String SCENE_MODE_DUAL_STRING = "100"; public static final String SCENE_MODE_SUNSET_STRING = "10"; public static final String SCENE_MODE_LANDSCAPE_STRING = "4"; @@ -124,6 +126,7 @@ public class SettingsManager implements ListMenu.SettingsListener { public static final String KEY_CAMERA_ID = "pref_camera2_id_key"; public static final String KEY_SWITCH_CAMERA = "pref_camera2_switch_camera_key"; public static final String KEY_PICTURE_SIZE = "pref_camera2_picturesize_key"; + public static final String KEY_PICTURE_FORMAT = "pref_camera2_picture_format_key"; public static final String KEY_ISO = "pref_camera2_iso_key"; public static final String KEY_EXPOSURE = "pref_camera2_exposure_key"; public static final String KEY_TIMER = "pref_camera2_timer_key"; @@ -1693,11 +1696,19 @@ public class SettingsManager implements ListMenu.SettingsListener { return num_val; } + + public boolean isCamera2HDRSupport(){ String value = getValue(KEY_HDR); return value != null && value.equals("enable"); } + public int getSavePictureFormat() { + String value = getValue(SettingsManager.KEY_PICTURE_FORMAT); + if (value == null) return 0; + return Integer.valueOf(value); + } + public boolean isZSLInHALEnabled(){ String value = getValue(KEY_ZSL); String halZSLValue = mContext.getString(R.string.pref_camera2_zsl_entryvalue_hal_zsl); diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java index 13f65e14c..a71a88a47 100755 --- a/src/com/android/camera/Storage.java +++ b/src/com/android/camera/Storage.java @@ -18,14 +18,18 @@ package com.android.camera; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import android.annotation.TargetApi; import android.content.ContentResolver; import android.content.ContentValues; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.location.Location; import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.os.Handler; import android.os.StatFs; import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; @@ -35,6 +39,8 @@ import android.util.Log; import com.android.camera.data.LocalData; import com.android.camera.exif.ExifInterface; import com.android.camera.util.ApiHelper; +import androidx.heifwriter.HeifWriter; +import android.graphics.ImageFormat; public class Storage { private static final String TAG = "CameraStorage"; @@ -135,13 +141,24 @@ public class Storage { values.put(ImageColumns.TITLE, title); if (mimeType.equalsIgnoreCase("jpeg") || mimeType.equalsIgnoreCase("image/jpeg") || + mimeType.equalsIgnoreCase("heif") || mimeType == null) { - values.put(ImageColumns.DISPLAY_NAME, title + ".jpg"); + + if (mimeType.equalsIgnoreCase("heif")){ + values.put(ImageColumns.DISPLAY_NAME, title + ".heic"); + } else { + values.put(ImageColumns.DISPLAY_NAME, title + ".jpg"); + } + } else { values.put(ImageColumns.DISPLAY_NAME, title + ".raw"); } values.put(ImageColumns.DATE_TAKEN, date); - values.put(ImageColumns.MIME_TYPE, "image/jpeg"); + if (mimeType.equalsIgnoreCase("heif")) { + values.put(ImageColumns.MIME_TYPE, "image/heif"); + } else { + values.put(ImageColumns.MIME_TYPE, "image/jpeg"); + } // Clockwise rotation in degrees. 0, 90, 180, or 270. values.put(ImageColumns.ORIENTATION, orientation); values.put(ImageColumns.DATA, path); @@ -180,6 +197,40 @@ public class Storage { return size; } + public static Uri addHeifImage(ContentResolver resolver, String title, long date, + Location location, int orientation, ExifInterface exif, byte[] data, int width, + int height, int quality, String mimeType) { + String path = generateFilepath(title, mimeType); + Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length); + if (bitmap != null) { + try { + HeifWriter.Builder builder = + new HeifWriter.Builder(path,width, height,HeifWriter.INPUT_MODE_BITMAP); + builder.setQuality(quality); + builder.setMaxImages(1); + builder.setPrimaryIndex(0); + builder.setRotation(orientation); + HeifWriter heifWriter = builder.build(); + heifWriter.start(); + heifWriter.addBitmap(bitmap); + heifWriter.stop(3000); + heifWriter.close(); + } catch (IOException|IllegalStateException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + bitmap.recycle(); + } + File f = new File(path); + int size = 0; + if (f.exists() && f.isFile()) { + size = (int) f.length(); + } + return addImage(resolver, title, date, location, orientation, + size, path, width, height, mimeType); + } + // Overwrites the file and updates the MediaStore, or inserts the image if // one does not already exist. public static void updateImage(Uri imageUri, ContentResolver resolver, String title, long date, @@ -224,11 +275,16 @@ public class Storage { } public static String generateFilepath(String title, String pictureFormat) { - if (pictureFormat == null || pictureFormat.equalsIgnoreCase("jpeg")) { + if (pictureFormat == null || pictureFormat.equalsIgnoreCase("jpeg") + || pictureFormat.equalsIgnoreCase("heif")) { + String suffix = ".jpg"; + if (pictureFormat.equalsIgnoreCase("heif")) { + suffix = ".heic"; + } if (isSaveSDCard() && SDCard.instance().isWriteable()) { - return SDCard.instance().getDirectory() + '/' + title + ".jpg"; + return SDCard.instance().getDirectory() + '/' + title + suffix; } else { - return DIRECTORY + '/' + title + ".jpg"; + return DIRECTORY + '/' + title + suffix; } } else { return RAW_DIRECTORY + '/' + title + ".raw"; diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java index c227f32b2..f91f6b031 100755 --- a/src/com/android/camera/imageprocessor/PostProcessor.java +++ b/src/com/android/camera/imageprocessor/PostProcessor.java @@ -1278,9 +1278,19 @@ public class PostProcessor{ mController.showCapturedReview(bytes, orientation); } } else { - mActivity.getMediaSaveService().addImage( - bytes, title, date, null, image.getCropRect().width(), image.getCropRect().height(), - orientation, null, mController.getMediaSavedListener(), mActivity.getContentResolver(), "jpeg"); + if(SettingsManager.getInstance().getSavePictureFormat() == + SettingsManager.HEIF_FORMAT) { + String value = SettingsManager.getInstance().getValue( + SettingsManager.KEY_JPEG_QUALITY); + int qualityNumber = CaptureModule.getQualityNumber(value); + mActivity.getMediaSaveService().addHEIFImageFromJpeg(bytes,title,date,null, + image.getWidth(),image.getHeight(),orientation,null,mActivity.getContentResolver(), + mController.getMediaSavedListener(),qualityNumber,"heif"); + } else { + mActivity.getMediaSaveService().addImage( + bytes, title, date, null, image.getCropRect().width(), image.getCropRect().height(), + orientation, null, mController.getMediaSavedListener(), mActivity.getContentResolver(), "jpeg"); + } mController.updateThumbnailJpegData(bytes); image.close(); } -- cgit v1.2.3