/* * Copyright 2013 Chris Banes * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.zhaojian.jolly.model; import java.io.File; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.List; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.RectF; import android.location.Location; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore.Images.Thumbnails; import android.text.TextUtils; import com.zhaojian.jolly.selectphotos.SelectPhotoApplication; import com.zhaojian.jolly.utils.Utils; public class PhotoUpload { private static final HashMap<Uri, PhotoUpload> SELECTION_CACHE = new HashMap<Uri, PhotoUpload>(); public static final int STATE_UPLOAD_COMPLETED = 5; public static final int STATE_UPLOAD_ERROR = 4; public static final int STATE_UPLOAD_IN_PROGRESS = 3; public static final int STATE_UPLOAD_WAITING = 2; public static final int STATE_SELECTED = 1; public static final int STATE_NONE = 0; public static final String FIELD_STATE = "state"; static final String FIELD_URI = "uri"; static final String FIELD_COMPLETED_DETECTION = "tag_detection"; static final String FIELD_USER_ROTATION = "user_rotation"; static final String FIELD_FILTER = "filter"; static final String FIELD_CROP_L = "crop_l"; static final String FIELD_CROP_T = "crop_t"; static final String FIELD_CROP_R = "crop_r"; static final String FIELD_CROP_B = "crop_b"; static final String FIELD_ACCOUNT_ID = "acc_id"; static final String FIELD_TARGET_ID = "target_id"; static final String FIELD_QUALITY = "quality"; static final String FIELD_RESULT_POST_ID = "r_post_id"; static final String FIELD_CAPTION = "caption"; static final String FIELD_TAGS_JSON = "tags"; static final String FIELD_PLACE_NAME = "place_name"; static final String FIELD_PLACE_ID = "place_id"; static final String LOG_TAG = "PhotoUpload"; static final float CROP_THRESHOLD = 0.01f; // 1% static final int MINI_THUMBNAIL_SIZE = 300; static final float MIN_CROP_VALUE = 0.0f; static final float MAX_CROP_VALUE = 1.0f; public static PhotoUpload getSelection(Uri uri) { // Check whether we've already got a Selection cached PhotoUpload item = SELECTION_CACHE.get(uri); if (null == item) { item = new PhotoUpload(uri); SELECTION_CACHE.put(uri, item); } return item; } public static void clearCache() { SELECTION_CACHE.clear(); } public static void populateCache(List<PhotoUpload> uploads) { for (PhotoUpload upload : uploads) { SELECTION_CACHE.put(upload.getOriginalPhotoUri(), upload); } } public static PhotoUpload getSelection(Uri baseUri, long id) { return getSelection(Uri.withAppendedPath(baseUri, String.valueOf(id))); } private static boolean checkCropValues(float left, float top, float right, float bottom) { return Math.max(left, top) >= (MIN_CROP_VALUE + CROP_THRESHOLD) || Math.min(right, bottom) <= (MAX_CROP_VALUE - CROP_THRESHOLD); } private static float santizeCropValue(float value) { return Math.min(1f, Math.max(0f, value)); } /** * Uri and Database Key */ private Uri mFullUri; private String mFullUriString; /** * Edit Variables */ private boolean mCompletedDetection; private int mUserRotation; private float mCropLeft; private float mCropTop; private float mCropRight; private float mCropBottom; /** * Upload Variables */ private String mAccountId; private String mTargetId; private String mResultPostId; private int mState; private String mCaption; String tagJson; private String mPlaceName; private String mPlaceId; private Account mAccount; private int mProgress; private Bitmap mBigPictureNotificationBmp; private boolean mNeedsSaveFlag = false; PhotoUpload() { // NO-Arg for Ormlite } private PhotoUpload(Uri uri) { mFullUri = uri; mFullUriString = uri.toString(); reset(); } public boolean beenCropped() { return checkCropValues(mCropLeft, mCropTop, mCropRight, mCropBottom); } @Override public boolean equals(Object obj) { if (obj instanceof PhotoUpload) { return getOriginalPhotoUri().equals( ((PhotoUpload) obj).getOriginalPhotoUri()); } return false; } public boolean isValid(Context context) { final String path = Utils.getPathFromContentUri( context.getContentResolver(), getOriginalPhotoUri()); if (null != path) { File file = new File(path); return file.exists(); } return false; } public Account getAccount() { return mAccount; } public Bitmap getBigPictureNotificationBmp() { return mBigPictureNotificationBmp; } public String getCaption() { return mCaption; } public RectF getCropValues() { return new RectF(mCropLeft, mCropTop, mCropRight, mCropBottom); } public RectF getCropValues(final int width, final int height) { return new RectF(mCropLeft * width, mCropTop * height, mCropRight * width, mCropBottom * height); } public Bitmap getDisplayImage(Context context) { try { final int size = SelectPhotoApplication.getInstanse() .getSmallestScreenDimension(); Bitmap bitmap = Utils.decodeImage(context.getContentResolver(), getOriginalPhotoUri(), size); bitmap = Utils.rotate(bitmap, getExifRotation(context)); return bitmap; } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } public String getDisplayImageKey() { return "dsply_" + getOriginalPhotoUri(); } public Location getExifLocation(Context context) { final String filePath = Utils.getPathFromContentUri( context.getContentResolver(), getOriginalPhotoUri()); if (null != filePath) { return Utils.getExifLocation(filePath); } return null; } public int getExifRotation(Context context) { return Utils.getOrientationFromContentUri(context.getContentResolver(), getOriginalPhotoUri()); } public Uri getOriginalPhotoUri() { if (null == mFullUri && !TextUtils.isEmpty(mFullUriString)) { mFullUri = Uri.parse(mFullUriString); } return mFullUri; } public String getPlaceId() { return mPlaceId; } public String getResultPostId() { return mResultPostId; } public Bitmap getThumbnailImage(Context context) { if (ContentResolver.SCHEME_CONTENT.equals(getOriginalPhotoUri() .getScheme())) { return getThumbnailImageFromMediaStore(context); } final Resources res = context.getResources(); int size = MINI_THUMBNAIL_SIZE; try { Bitmap bitmap = Utils.decodeImage(context.getContentResolver(), getOriginalPhotoUri(), size); // bitmap = Utils.rotate(bitmap, getExifRotation(context)); return bitmap; } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } public String getThumbnailImageKey() { return "thumb_" + getOriginalPhotoUri(); } public int getTotalRotation(Context context) { return (getExifRotation(context) + getUserRotation()) % 360; } public int getUploadProgress() { return mProgress; } public File getUploadSaveFile() { File dir = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "photup"); if (!dir.exists()) { dir.mkdirs(); } return new File(dir, System.currentTimeMillis() + ".jpg"); } public int getUploadState() { return mState; } public String getUploadTargetId() { return mTargetId; } public int getUserRotation() { return mUserRotation % 360; } @Override public int hashCode() { return getOriginalPhotoUri().hashCode(); } public boolean hasPlace() { return null != mPlaceId && null != mPlaceName; } public void populateFromAccounts(HashMap<String, Account> accounts) { if (null == mAccount && !TextUtils.isEmpty(mAccountId)) { mAccount = accounts.get(mAccountId); } } public Bitmap processBitmap(Bitmap bitmap, final boolean fullSize, final boolean modifyOriginal) { return bitmap; } public boolean requiresFaceDetectPass() { return !mCompletedDetection; } public boolean requiresProcessing(final boolean fullSize) { return getUserRotation() != 0 || (fullSize && beenCropped()); } public boolean requiresSaving() { return mNeedsSaveFlag; } public void reset() { mState = STATE_NONE; mUserRotation = 0; mCaption = null; mCropLeft = mCropTop = MIN_CROP_VALUE; mCropRight = mCropBottom = MAX_CROP_VALUE; mCompletedDetection = false; setRequiresSaveFlag(); } public void resetSaveFlag() { mNeedsSaveFlag = false; } public void rotateClockwise() { mUserRotation += 90; setRequiresSaveFlag(); } public void setCaption(String caption) { if (TextUtils.isEmpty(caption)) { mCaption = null; } else { mCaption = caption; } setRequiresSaveFlag(); } public void setCropValues(RectF cropValues) { if (checkCropValues(cropValues.left, cropValues.top, cropValues.right, cropValues.bottom)) { mCropLeft = santizeCropValue(cropValues.left); mCropTop = santizeCropValue(cropValues.top); mCropRight = santizeCropValue(cropValues.right); mCropBottom = santizeCropValue(cropValues.bottom); } else { mCropLeft = mCropTop = MIN_CROP_VALUE; mCropRight = mCropBottom = MAX_CROP_VALUE; } setRequiresSaveFlag(); } public void setResultPostId(String resultPostId) { mResultPostId = resultPostId; setRequiresSaveFlag(); } public void setUploadProgress(int progress) { if (progress != mProgress) { mProgress = progress; } } public void setUploadState(final int state) { if (mState != state) { mState = state; switch (state) { case STATE_UPLOAD_ERROR: case STATE_UPLOAD_COMPLETED: mBigPictureNotificationBmp = null; break; case STATE_SELECTED: case STATE_UPLOAD_WAITING: mProgress = -1; break; } setRequiresSaveFlag(); } } @Override public String toString() { StringBuffer sb = new StringBuffer(); String caption = getCaption(); if (null != caption) { sb.append(caption).append(" "); } if (hasPlace()) { sb.append("(").append(mPlaceName).append(")"); } return sb.toString(); } private Bitmap getThumbnailImageFromMediaStore(Context context) { Resources res = context.getResources(); final int kind = Thumbnails.MINI_KIND; BitmapFactory.Options opts = new BitmapFactory.Options(); opts = new BitmapFactory.Options(); try { final long id = Long.parseLong(getOriginalPhotoUri() .getLastPathSegment()); Bitmap bitmap = Thumbnails.getThumbnail( context.getContentResolver(), id, kind, opts); bitmap = Utils.rotate(bitmap, getExifRotation(context)); return bitmap; } catch (Exception e) { return null; } } private void setRequiresSaveFlag() { mNeedsSaveFlag = true; } }