Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master non native #756

Open
wants to merge 55 commits into
base: develop
Choose a base branch
from
Open

Master non native #756

wants to merge 55 commits into from

Conversation

wj576038874
Copy link

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);
    }
    }

}

p1nkydev and others added 30 commits March 25, 2019 10:39
Fixed crash in UCrop.getOutputCropAspectRatio(data)
prepared for new "non-native" release: redesign + fixes
…es_to_master

# Conflicts:
#	build.gradle
#	gradle.properties
#	gradle/wrapper/gradle-wrapper.properties
#	sample/build.gradle
#	ucrop/build.gradle
#	ucrop/src/main/java/com/yalantis/ucrop/UCropActivity.java
#	ucrop/src/main/java/com/yalantis/ucrop/UCropFragment.java
#	ucrop/src/main/res/drawable/ucrop_ic_crop.xml
#	ucrop/src/main/res/drawable/ucrop_ic_crop_unselected.xml
#	ucrop/src/main/res/drawable/ucrop_ic_rotate.xml
#	ucrop/src/main/res/drawable/ucrop_ic_rotate_unselected.xml
#	ucrop/src/main/res/drawable/ucrop_ic_scale.xml
#	ucrop/src/main/res/drawable/ucrop_ic_scale_unselected.xml
#	ucrop/src/main/res/layout/ucrop_controls.xml
#	ucrop/src/main/res/layout/ucrop_layout_rotate_wheel.xml
#	ucrop/src/main/res/values/colors.xml
#	ucrop/src/main/res/values/styles.xml
…s_to_master

Feature/merge non native updates to master
…02_non_native

Implement color applying for scale and angle texts, fixing color appl…
Fixed high-resolution crash.
Fixed image saving on Android Q.
Fix for using uCrop with SAF (Storage Access Framework) on Android 10 and newer.
Sample app changed for context file testing. Added a "choose file destination" button and some other associated controls.
Updated okhttp dependency for uCrop
Added custom OkHttpClient for sample due to outdated random pic url
added instruction for README.md
fabio-blanco and others added 25 commits May 21, 2021 15:01
…against null pointer exceptions and minor performance improvements
…-destination-file

# Conflicts:
#	ucrop/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java
…af-destination-file

Fix for problems with input and output File Uri with "content" schema and Android 10 SAF new requirements.
Removed redundant jcenter mention from README.md
Handled content case in ResultActivity
Code style correction
Updated dependencies, resolve unexpected error on result screen
Signed-off-by: dmorozov <dmytro.morozov@yalantis.net>
- change fallback for EXTRA_ASPECT_RATIO_X and EXTRA_ASPECT_RATIO_Y to "-1" as "0" has special meaning
- fix usage of useSourceImageAspectRatio (now properly hides mWrapperStateAspectRatio)
- fix setTargetAspectRatio at processOptions due to Float.NaN (allows custom aspect ratio definitions with default ratio set to x=CropImageView.DEFAULT_ASPECT_RATIO and y=CropImageView.DEFAULT_ASPECT_RATIO)
- fix sanity check at setAspectRatioOptions
…tegration

Improve/non native/2.2.8 prs integration
Signed-off-by: dmorozov <dmytro.morozov@yalantis.net>
- Correct the vector drawable path due to bad rendering

Signed-off-by: dmorozov <dmytro.morozov@yalantis.net>
- Update README.md
- Update version to 2.2.8 in gradle

Signed-off-by: dmorozov <dmytro.morozov@yalantis.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet