pearmak
pearmak

Reputation: 5027

android bitmap from camera is just thumbnail size?

i am making an app of which it can initialize the camera and then after taking the photo, the photo could be imported and the user to further draw on it.

Coding:

Class A:

   public OnClickListener cameraButtonListener = new OnClickListener()   
   {
      @Override
      public void onClick(View v) 
          {  
               vibrate();
               Toast.makeText(Doodlz.this, R.string.message_initalize_camera, Toast.LENGTH_SHORT).show();
               Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
               startActivityForResult(cameraIntent, CAMERA_REQUEST);               
           }      
   }; 

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    super.onActivityResult(requestCode, resultCode, data);      

    if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) 
    {  
        Bitmap photo = (Bitmap) data.getExtras().get("data"); 
        Bitmap photocopy = photo.copy(Bitmap.Config.ARGB_8888, true);
        doodleView.get_camera_pic(photocopy);
    }
}

doodleView:

   public void get_camera_pic (Bitmap photocopy)
   {
    // get screen dimension first
      WindowManager wm = (WindowManager) context_new.getSystemService(Context.WINDOW_SERVICE);
      Display display = wm.getDefaultDisplay();
      final int screenWidth = display.getWidth();
      final int screenHeight = display.getHeight(); 
      bitmap = photocopy;
      bitmap = Bitmap.createScaledBitmap(bitmap, screenWidth, screenHeight, true);
      bitmapCanvas = new Canvas(bitmap);
      invalidate(); // refresh the screen      
   }

Question:

The photo can be successfully captured using the camera and return to doodleView for user. Yet since the imported image dimension is very small, just a thumbnail size!! (dont know why), so I tired scaling it up and then the resolution is very poor.

My question is that, how modify the above code so as to set the photo taken dimension be fitting to the screen's dimension and the returned photo be 1:1 of the screen instead of getting like a thumbnail one? (best to be fit 1:1 of screen, because if it is then importing as original photo size the photo dimension is then greater then the screen, it then need to scale down and distorted by different ratio of width and height ratio to fit full screen)

Thanks!!

Upvotes: 1

Views: 5379

Answers (2)

Mark Fidell
Mark Fidell

Reputation: 1123

This is normal for the default camera application. The way to get the full size image is to tell the camera activity to put the result into a file. First create a file and then start the camera application as follows:

outputFileName = createImageFile(".tmp");
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFileName));
startActivityForResult(takePictureIntent, takePhotoActionCode);

Then in your onActivityResult, you can get this image file back and manipulate it.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == takePhotoActionCode)
    {
        if (resultCode == RESULT_OK)
        {
            // NOTE: The intent returned might be NULL if the default camera app was used.
            // This is because the image returned is in the file that was passed to the intent.
                processPhoto(data);
        }
    }
}

processPhoto will look a bit like this:

    protected void processPhoto(Intent i)
    {
        int imageExifOrientation = 0;

// Samsung Galaxy Note 2 and S III doesn't return the image in the correct orientation, therefore rotate it based on the data held in the exif.

        try
        {


    ExifInterface exif;
        exif = new ExifInterface(outputFileName.getAbsolutePath());
        imageExifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                    ExifInterface.ORIENTATION_NORMAL);
    }
    catch (IOException e1)
    {
        e1.printStackTrace();
    }

    int rotationAmount = 0;

    if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_270)
    {
        // Need to do some rotating here...
        rotationAmount = 270;
    }
    if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_90)
    {
        // Need to do some rotating here...
        rotationAmount = 90;
    }
    if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_180)
    {
        // Need to do some rotating here...
        rotationAmount = 180;
    }       

    int targetW = 240;
    int targetH = 320; 

    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(outputFileName.getAbsolutePath(), bmOptions);
    int photoWidth = bmOptions.outWidth;
    int photoHeight = bmOptions.outHeight;

    int scaleFactor = Math.min(photoWidth/targetW, photoHeight/targetH);

    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap scaledDownBitmap = BitmapFactory.decodeFile(outputFileName.getAbsolutePath(), bmOptions);

    if (rotationAmount != 0)
    {
        Matrix mat = new Matrix();
        mat.postRotate(rotationAmount);
        scaledDownBitmap = Bitmap.createBitmap(scaledDownBitmap, 0, 0, scaledDownBitmap.getWidth(), scaledDownBitmap.getHeight(), mat, true);
    }       

    ImageView iv2 = (ImageView) findViewById(R.id.photoImageView);
    iv2.setImageBitmap(scaledDownBitmap);

    FileOutputStream outFileStream = null;
    try
    {
        mLastTakenImageAsJPEGFile = createImageFile(".jpg");
        outFileStream = new FileOutputStream(mLastTakenImageAsJPEGFile);
        scaledDownBitmap.compress(Bitmap.CompressFormat.JPEG, 75, outFileStream);
    }
    catch (Exception e)
    {
        e.printStackTrace();
            }
    }

One thing to note is that on Nexus devices the calling activity is not normally destroyed. However on Samsung Galaxy S III and Note 2 devices the calling activity is destroyed. Therefore the just storing the outputFileName as a member variable in the Activity will result in it being null when the camera app returns unless you remember to save it when the activity dies. It's good practice to do that anyhow, but this is a mistake that I've made before so I thought I'd mention it.

EDIT:

Regarding your comment, the createImageFile is a not in the standard API, it's something I wrote (or I may have borrowed :-), I don't remember), here is the method for createImageFile():

    private File createImageFile(String fileExtensionToUse) throws IOException 
{

    File storageDir = new File(
            Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES
            ), 
            "MyImages"
        );      

    if(!storageDir.exists())
    {
        if (!storageDir.mkdir())
        {
            Log.d(TAG,"was not able to create it");
        }
    }
    if (!storageDir.isDirectory())
    {
        Log.d(TAG,"Don't think there is a dir there.");
    }

    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "FOO_" + timeStamp + "_image";

    File image = File.createTempFile(
        imageFileName, 
        fileExtensionToUse, 
        storageDir
    );

    return image;
}    

Upvotes: 3

323go
323go

Reputation: 14274

To access the full image, you either need to access the intent URI by using data.getData() in your doodleView, or (better) provide your own URI for storing the image by passing it to the intent by supplying a URI in EXTRA_OUTPUT extra.

Upvotes: 1

Related Questions