uCrop icon indicating copy to clipboard operation
uCrop copied to clipboard

Master non native

Open wj576038874 opened this issue 3 years ago • 0 comments

package com.yalantis.ucrop.task;

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.net.Uri; import android.os.AsyncTask; import android.util.Log;

import androidx.annotation.NonNull; import androidx.annotation.Nullable;

import com.yalantis.ucrop.callback.BitmapLoadCallback; import com.yalantis.ucrop.model.ExifInfo; import com.yalantis.ucrop.util.BitmapLoadUtils;

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okio.BufferedSource; import okio.Okio; import okio.Sink;

/**

  • Creates and returns a Bitmap for a given Uri(String url).

  • inSampleSize is calculated based on requiredWidth property. However can be adjusted if OOM occurs.

  • If any EXIF config is found - bitmap is transformed properly. */ public class BitmapLoadTask extends AsyncTask<Void, Void, BitmapLoadTask.BitmapWorkerResult> {

    private static final String TAG = "BitmapWorkerTask";

    private final Context mContext; private Uri mInputUri; private Uri mOutputUri; private final int mRequiredWidth; private final int mRequiredHeight;

    private final BitmapLoadCallback mBitmapLoadCallback;

    public static class BitmapWorkerResult {

     Bitmap mBitmapResult;
     ExifInfo mExifInfo;
     Exception mBitmapWorkerException;
    
     public BitmapWorkerResult(@NonNull Bitmap bitmapResult, @NonNull ExifInfo exifInfo) {
         mBitmapResult = bitmapResult;
         mExifInfo = exifInfo;
     }
    
     public BitmapWorkerResult(@NonNull Exception bitmapWorkerException) {
         mBitmapWorkerException = bitmapWorkerException;
     }
    

    }

    public BitmapLoadTask(@NonNull Context context, @NonNull Uri inputUri, @Nullable Uri outputUri, int requiredWidth, int requiredHeight, BitmapLoadCallback loadCallback) { mContext = context; mInputUri = inputUri; mOutputUri = outputUri; mRequiredWidth = requiredWidth; mRequiredHeight = requiredHeight; mBitmapLoadCallback = loadCallback; }

    @Override @NonNull protected BitmapWorkerResult doInBackground(Void... params) { if (mInputUri == null) { return new BitmapWorkerResult(new NullPointerException("Input Uri cannot be null")); }

     try {
         processInputUri();
     } catch (NullPointerException | IOException e) {
         return new BitmapWorkerResult(e);
     }
    
     final BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     try {
         BitmapFactory.decodeStream(mContext.getContentResolver().openInputStream(mInputUri) ,null, options);
     } catch (FileNotFoundException e) {
         e.printStackTrace();
     }
     options.inSampleSize = BitmapLoadUtils.calculateInSampleSize(options, mRequiredWidth, mRequiredHeight);
     options.inJustDecodeBounds = false;
    
     Bitmap decodeSampledBitmap = null;
    
     boolean decodeAttemptSuccess = false;
     while (!decodeAttemptSuccess) {
         try {
             InputStream stream = mContext.getContentResolver().openInputStream(mInputUri);
             try {
                 decodeSampledBitmap = BitmapFactory.decodeStream(stream, null, options);
                 if (options.outWidth == -1 || options.outHeight == -1) {
                     return new BitmapWorkerResult(new IllegalArgumentException("Bounds for bitmap could not be retrieved from the Uri: [" + mInputUri + "]"));
                 }
             } finally {
                 BitmapLoadUtils.close(stream);
             }
             decodeAttemptSuccess = true;
         } catch (OutOfMemoryError error) {
             Log.e(TAG, "doInBackground: BitmapFactory.decodeFileDescriptor: ", error);
             options.inSampleSize *= 2;
         } catch (IOException e) {
             Log.e(TAG, "doInBackground: ImageDecoder.createSource: ", e);
             return new BitmapWorkerResult(new IllegalArgumentException("Bitmap could not be decoded from the Uri: [" + mInputUri + "]", e));
         }
     }
    
     if (decodeSampledBitmap == null) {
         return new BitmapWorkerResult(new IllegalArgumentException("Bitmap could not be decoded from the Uri: [" + mInputUri + "]"));
     }
    
     int exifOrientation = BitmapLoadUtils.getExifOrientation(mContext, mInputUri);
     int exifDegrees = BitmapLoadUtils.exifToDegrees(exifOrientation);
     int exifTranslation = BitmapLoadUtils.exifToTranslation(exifOrientation);
    
     ExifInfo exifInfo = new ExifInfo(exifOrientation, exifDegrees, exifTranslation);
    
     Matrix matrix = new Matrix();
     if (exifDegrees != 0) {
         matrix.preRotate(exifDegrees);
     }
     if (exifTranslation != 1) {
         matrix.postScale(exifTranslation, 1);
     }
     if (!matrix.isIdentity()) {
         return new BitmapWorkerResult(BitmapLoadUtils.transformBitmap(decodeSampledBitmap, matrix), exifInfo);
     }
    
     return new BitmapWorkerResult(decodeSampledBitmap, exifInfo);
    

    }

    private void processInputUri() throws NullPointerException, IOException { String inputUriScheme = mInputUri.getScheme(); Log.d(TAG, "Uri scheme: " + inputUriScheme); if ("http".equals(inputUriScheme) || "https".equals(inputUriScheme)) { try { downloadFile(mInputUri, mOutputUri); } catch (NullPointerException | IOException e) { Log.e(TAG, "Downloading failed", e); throw e; } } else if ("content".equals(inputUriScheme)) { try { copyFile(mInputUri, mOutputUri); } catch (NullPointerException | IOException e) { Log.e(TAG, "Copying failed", e); throw e; } } else if (!"file".equals(inputUriScheme)) { Log.e(TAG, "Invalid Uri scheme " + inputUriScheme); throw new IllegalArgumentException("Invalid Uri scheme" + inputUriScheme); } }

    private void copyFile(@NonNull Uri inputUri, @Nullable Uri outputUri) throws NullPointerException, IOException { Log.d(TAG, "copyFile");

     if (outputUri == null) {
         throw new NullPointerException("Output Uri is null - cannot copy image");
     }
    
     InputStream inputStream = null;
     OutputStream outputStream = null;
     try {
         inputStream = mContext.getContentResolver().openInputStream(inputUri);
         outputStream = new FileOutputStream(new File(outputUri.getPath()));
         if (inputStream == null) {
             throw new NullPointerException("InputStream for given input Uri is null");
         }
    
         byte buffer[] = new byte[1024];
         int length;
         while ((length = inputStream.read(buffer)) > 0) {
             outputStream.write(buffer, 0, length);
         }
     } finally {
         BitmapLoadUtils.close(outputStream);
         BitmapLoadUtils.close(inputStream);
    
         // swap uris, because input image was copied to the output destination
         // (cropped image will override it later)
         mInputUri = mOutputUri;
     }
    

    }

    private void downloadFile(@NonNull Uri inputUri, @Nullable Uri outputUri) throws NullPointerException, IOException { Log.d(TAG, "downloadFile");

     if (outputUri == null) {
         throw new NullPointerException("Output Uri is null - cannot download image");
     }
    
     OkHttpClient client = new OkHttpClient();
    
     BufferedSource source = null;
     Sink sink = null;
     Response response = null;
     try {
         Request request = new Request.Builder()
                 .url(inputUri.toString())
                 .build();
         response = client.newCall(request).execute();
         source = response.body().source();
    
         OutputStream outputStream = mContext.getContentResolver().openOutputStream(outputUri);
         if (outputStream != null) {
             sink = Okio.sink(outputStream);
             source.readAll(sink);
         } else {
             throw new NullPointerException("OutputStream for given output Uri is null");
         }
     } finally {
         BitmapLoadUtils.close(source);
         BitmapLoadUtils.close(sink);
         if (response != null) {
             BitmapLoadUtils.close(response.body());
         }
         client.dispatcher().cancelAll();
    
         // swap uris, because input image was downloaded to the output destination
         // (cropped image will override it later)
         mInputUri = mOutputUri;
     }
    

    }

    @Override protected void onPostExecute(@NonNull BitmapWorkerResult result) { if (result.mBitmapWorkerException == null) { mBitmapLoadCallback.onBitmapLoaded(result.mBitmapResult, result.mExifInfo, mInputUri.getPath(), (mOutputUri == null) ? null : mOutputUri.getPath()); } else { mBitmapLoadCallback.onFailure(result.mBitmapWorkerException); } }

}

wj576038874 avatar May 18 '21 03:05 wj576038874