|
4 | 4 |
|
5 | 5 | import android.annotation.SuppressLint;
|
6 | 6 | import android.content.Context;
|
| 7 | +import android.graphics.Bitmap; |
| 8 | +import android.graphics.Bitmap.CompressFormat; |
| 9 | +import android.graphics.BitmapFactory; |
| 10 | +import android.graphics.Rect; |
| 11 | +import android.net.Uri; |
7 | 12 | import android.os.Bundle;
|
| 13 | +import android.provider.MediaStore; |
8 | 14 | import android.text.TextUtils;
|
9 | 15 | import android.util.DisplayMetrics;
|
10 | 16 | import android.view.LayoutInflater;
|
|
43 | 49 | import fr.free.nrw.commons.utils.DialogUtil;
|
44 | 50 | import fr.free.nrw.commons.utils.ImageUtils;
|
45 | 51 | import fr.free.nrw.commons.utils.ViewUtil;
|
| 52 | +import io.reactivex.Observable; |
| 53 | +import io.reactivex.Scheduler; |
| 54 | +import io.reactivex.Single; |
| 55 | +import io.reactivex.SingleObserver; |
| 56 | +import io.reactivex.android.schedulers.AndroidSchedulers; |
46 | 57 | import io.reactivex.disposables.Disposable;
|
| 58 | +import io.reactivex.schedulers.Schedulers; |
| 59 | +import java.io.ByteArrayInputStream; |
| 60 | +import java.io.ByteArrayOutputStream; |
| 61 | +import java.io.File; |
| 62 | +import java.io.IOException; |
47 | 63 | import java.util.ArrayList;
|
48 | 64 | import java.util.Arrays;
|
49 | 65 | import java.util.List;
|
@@ -284,7 +300,15 @@ public void onImageProcessed(UploadItem uploadItem, Place place) {
|
284 | 300 | }
|
285 | 301 |
|
286 | 302 | descriptions = uploadItem.getDescriptions();
|
287 |
| - photoViewBackgroundImage.setImageURI(uploadItem.getMediaUri()); |
| 303 | + compositeDisposable |
| 304 | + .add(downSampleImage(uploadItem.getContentUri()) |
| 305 | + .subscribeOn(Schedulers.io()) |
| 306 | + .observeOn(AndroidSchedulers.mainThread()) |
| 307 | + .subscribe(bitmap -> { |
| 308 | + if (null != bitmap) { |
| 309 | + photoViewBackgroundImage.setImageBitmap(bitmap); |
| 310 | + } |
| 311 | + }, Timber::d)); |
288 | 312 | setDescriptionsInAdapter(descriptions);
|
289 | 313 | }
|
290 | 314 |
|
@@ -435,4 +459,61 @@ private void setDescriptionsInAdapter(List<Description> descriptions) {
|
435 | 459 | }
|
436 | 460 | }
|
437 | 461 |
|
| 462 | + /** |
| 463 | + * Downsample bitmap to handle OOM/Bitmap too large exception |
| 464 | + * |
| 465 | + * @param uri |
| 466 | + * @return |
| 467 | + */ |
| 468 | + private Single<Bitmap> downSampleImage(Uri uri) { |
| 469 | + Bitmap existing = null; |
| 470 | + try { |
| 471 | + existing = MediaStore.Images.Media |
| 472 | + .getBitmap(this.getContext().getContentResolver(), uri); |
| 473 | + } catch (IOException e) { |
| 474 | + e.printStackTrace(); |
| 475 | + } |
| 476 | + |
| 477 | + if (null == existing) { |
| 478 | + return Single.error(new Throwable("could not downsample")); |
| 479 | + } |
| 480 | + |
| 481 | + final int requiredHeight = getResources().getDisplayMetrics().heightPixels; |
| 482 | + final int requiredWidth = getResources().getDisplayMetrics().widthPixels; |
| 483 | + |
| 484 | + // Raw height and width of image |
| 485 | + final int height = existing.getHeight(); |
| 486 | + final int width = existing.getWidth(); |
| 487 | + int inSampleSize = 1; |
| 488 | + |
| 489 | + if (height > requiredHeight || width > requiredWidth) { |
| 490 | + |
| 491 | + final int halfHeight = height / 2; |
| 492 | + final int halfWidth = width / 2; |
| 493 | + |
| 494 | + // Calculate the largest inSampleSize value that is a power of 2 and keeps both |
| 495 | + // height and width larger than the requested height and width. |
| 496 | + while ((halfHeight / inSampleSize) >= requiredHeight |
| 497 | + && (halfWidth / inSampleSize) >= requiredWidth) { |
| 498 | + inSampleSize *= 2; |
| 499 | + } |
| 500 | + } |
| 501 | + |
| 502 | + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
| 503 | + existing.compress(CompressFormat.PNG, 0, byteArrayOutputStream); |
| 504 | + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( |
| 505 | + byteArrayOutputStream.toByteArray()); |
| 506 | + // First decode with inJustDecodeBounds=true to check dimensions |
| 507 | + final BitmapFactory.Options options = new BitmapFactory.Options(); |
| 508 | + Rect rect = new Rect(0, 0, 0, 0); |
| 509 | + options.inJustDecodeBounds = false; |
| 510 | + options.inSampleSize = inSampleSize; |
| 511 | + Bitmap modified = BitmapFactory.decodeStream(byteArrayInputStream, rect, options); |
| 512 | + if (modified != null) { |
| 513 | + return Single.just(modified); |
| 514 | + } else { |
| 515 | + return Single.error(new Throwable("could not downsample")); |
| 516 | + } |
| 517 | + } |
| 518 | + |
438 | 519 | }
|
0 commit comments