Uploaded image for project: 'Apache Cordova'
  1. Apache Cordova
  2. CB-14

CameraLauncher Plugin enhancement for loading big image files to avoid OutOfMemory exceptions

VotersWatch issueWatchersLinkUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    Description

      Currently the CameraLauncher plugin of Phonegap (or Apache Callback) is using Android default API for stream decoding.
      It will be very easy to get crash by throwing out the OutOfMemory exceptions while loading bigger image files.

      So I add a new method called safeDecodeStream for better stream decoding.

      safeDecodeStream method
          /**
           * A safer decodeStream method
           * rather than the one of {@link BitmapFactory}
           * which will be easy to get OutOfMemory Exception
           * while loading a big image file.
           * 
           * @param uri
           * @param width
           * @param height
           * @return
           * @throws FileNotFoundException
           */
          protected Bitmap safeDecodeStream(Uri uri, int width, int height)
          throws FileNotFoundException{
      		int scale = 1;
      		BitmapFactory.Options options = new BitmapFactory.Options();
      		android.content.ContentResolver resolver = this.ctx.getContentResolver();
      		
      		if(width>0 || height>0){
      			// Decode image size without loading all data into memory
      			options.inJustDecodeBounds = true;
      			BitmapFactory.decodeStream(
      					new BufferedInputStream(resolver.openInputStream(uri), 16*1024),
      					null,
      					options);
      			
      			int w = options.outWidth;
      			int h = options.outHeight;
      			while (true) {
      				if ((width>0 && w/2 < width)
      						|| (height>0 && h/2 < height)){
      					break;
      				}
      				w /= 2;
      				h /= 2;
      				scale *= 2;
      			}
      		}
      
      		// Decode with inSampleSize option
      		options.inJustDecodeBounds = false;
      		options.inSampleSize = scale;
      		return BitmapFactory.decodeStream(
      				new BufferedInputStream(resolver.openInputStream(uri), 16*1024), 
      				null, 
      				options);
      	}  
      

      And then change all the codes which are invoking the Android decodeStream API directly to this method.
      e.g.

      usage example
      //Updated by Bright for safer decodeStream
      //android.content.ContentResolver resolver = this.ctx.getContentResolver();
      //bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
      bitmap = safeDecodeStream(uri, this.targetWidth, this.targetHeight);
      
      

      Attachments

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            bowserj Joey Robert Bowser
            itstarting Bright Zheng
            Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Slack

                Issue deployment