'Image must be resized' 当相机尺寸超过 15Megapixel 时从 phone 捕获图像时出错

'Image must be resized' error when the image is captured from phone when the camera size is more than 15Megapixel

嗨 Stack Overflow 团队,

以下是 PhotoEditor Android 应用程序的 java 代码,用于捕获图像并将图像保存在 phone

以下是 MainActivity.java 文件:

package com.example.photoeditor;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ImageView;
import com.adobe.creativesdk.aviary.AdobeImageIntent;

public class MainActivity extends AppCompatActivity {
  public static final String IMAGE_URI = "IMAGE_URI_KEY";

  private static final String TAG = "MainActivity";
  private static final int IMAGE_EDITOR_RESULT = 1;

  private ImageView mEditedImageView;

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mEditedImageView = (ImageView) findViewById(R.id.edited_image_view);

    Bundle extras = getIntent().getExtras();
    if (extras != null) {
      Uri imageUri = Uri.parse(getIntent().getExtras().getString(IMAGE_URI));
      Intent imageEditorIntent = new AdobeImageIntent.Builder(this).setData(imageUri).build();
      startActivityForResult(imageEditorIntent, IMAGE_EDITOR_RESULT);
      finish(); // Comment this out to receive edited image
    }
  }

  // Do something with the edited image
  @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
      switch (requestCode) {
        case IMAGE_EDITOR_RESULT:
          Uri editedImageUri = data.getParcelableExtra(AdobeImageIntent.EXTRA_OUTPUT_URI);
          Log.d(TAG, "editedImageUri: " + editedImageUri.toString());
          Bundle extra = data.getExtras();
          if (extra != null) {
            boolean changed = extra.getBoolean(AdobeImageIntent.EXTRA_OUT_BITMAP_CHANGED);
            Log.d(TAG, "Image edited: " + changed);
            if (changed) {
              mEditedImageView.setImageURI(editedImageUri);
            }
          }
          break;

        default:
          throw new IllegalArgumentException("Unexpected request code");
      }
    }
  }

  public static Intent getIntent(Context context, Bundle bundle) {
    Intent intent = new Intent(context, MainActivity.class);
    if (bundle != null) {
      intent.putExtras(bundle);
    }
    return intent;
  }
}

以下是 HomeActivity.java 文件:

package com.example.photoeditor;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.Objects;

import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

public class HomeActivity extends AppCompatActivity {
  private static final String TAG = "HomeActivity";
  private static final int GALLERY_RESULT = 1;
  private static final int CAMERA_RESULT = 2;
  private static final String FILE_PROVIDER_AUTHORITY = "com.example.photoeditor";
  private static final int CAMERA_PERMISSION_REQ_CODE = 1001;
  private static final int STORAGE_PERMISSION_REQ_CODE = 1002;
  private String mCapturedImagePath;

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);
  }

  public void openCamera(View view) {
    // check for camera permission if not granted before
    if (ContextCompat.checkSelfPermission(this, CAMERA) != PERMISSION_GRANTED) {
      String[] cameraPermission = { CAMERA };
      ActivityCompat.requestPermissions(this, cameraPermission, CAMERA_PERMISSION_REQ_CODE);
    } else {
      dispatchImageCaptureIntent();
    }
  }

  public void openGallery(View view) {
    // check for storage permission if not granted before
    if (ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
      String[] storagePermissions = { READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE };
      ActivityCompat.requestPermissions(this, storagePermissions, STORAGE_PERMISSION_REQ_CODE);
    } else {
      dispatchGalleryIntent();
    }
  }

  private void dispatchGalleryIntent() {
    Intent galleryIntent = new Intent(Intent.ACTION_PICK, Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(galleryIntent, GALLERY_RESULT);
  }

  private void dispatchImageCaptureIntent() {
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (cameraIntent.resolveActivity(getPackageManager()) != null) {
      File photoFile = null;
      try {
        photoFile = createImageFile();
      } catch (IOException e) {
        e.printStackTrace();
      }

      if (photoFile != null) {
        Uri photoFileUri = FileProvider.getUriForFile(this, FILE_PROVIDER_AUTHORITY, photoFile);
        Log.d(TAG, "dispatchImageCaptureIntent:photoFileUri: " + photoFile.toString());
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFileUri);
        startActivityForResult(cameraIntent, CAMERA_RESULT);
      }
    }
  }

  @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
      @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
      case CAMERA_PERMISSION_REQ_CODE:
        if (grantResults[0] == PERMISSION_GRANTED) {
          dispatchImageCaptureIntent();
        } else {
          Toast.makeText(this, "Required camera permission not granted", Toast.LENGTH_SHORT).show();
        }
        break;

      case STORAGE_PERMISSION_REQ_CODE:
        if (grantResults[0] == PERMISSION_GRANTED) {
          dispatchGalleryIntent();
        } else {
          Toast.makeText(this, "Required storage permission not granted", Toast.LENGTH_SHORT)
              .show();
        }
        break;

      default:
        throw new IllegalArgumentException("Unexpected request code");
    }
  }

  private File createImageFile() throws IOException {
    String timeStamp = DateFormat.getDateTimeInstance().format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(imageFileName, ".jpg", storageDir);
    mCapturedImagePath = image.getAbsolutePath();
    return image;
  }

  private Bundle uriToBundle(Uri imageUri) {
    Bundle bundle = new Bundle();
    bundle.putString(MainActivity.IMAGE_URI, imageUri.toString());
    return bundle;
  }

  @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
      if (requestCode == GALLERY_RESULT) {
        Uri imageUri = data.getData();
        startActivity(MainActivity.getIntent(this, uriToBundle(Objects.requireNonNull(imageUri))));
      } else if (requestCode == CAMERA_RESULT) {
        File imageFile = new File(mCapturedImagePath);
        Uri imageUri = Uri.fromFile(imageFile);
        startActivity(MainActivity.getIntent(this, uriToBundle(imageUri)));
      }
    } else {
      Toast.makeText(this, "Image not loaded.", Toast.LENGTH_SHORT).show();
    }
  }

  public static Intent getIntent(Context context) {
    return new Intent(context, HomeActivity.class);
  }
}

以下是 activity_home XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.photoeditor.HomeActivity">

  <ImageView
      android:id="@+id/home_background"
      android:layout_width="250dp"
      android:layout_height="250dp"
      android:layout_centerInParent="true"
      android:contentDescription="@string/astronaut_content_desc"
      android:scaleType="centerCrop"
      android:src="@drawable/picture"/>

  <LinearLayout
      android:id="@+id/title_home"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_marginTop="75dp"
      android:gravity="center"
      tools:ignore="UseCompoundDrawables">

    <ImageView
        android:id="@+id/home_logo"
        android:layout_width="@dimen/logo_width"
        android:layout_height="@dimen/logo_height"
        android:contentDescription="@string/app_logo_content_desc"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        android:textColor="@color/whitePrimary"
        android:textSize="50sp"/>
  </LinearLayout>

  <LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentBottom="true"
      android:layout_below="@id/title_home"
      android:layout_centerHorizontal="true"
      android:layout_marginBottom="25dp"
      android:gravity="bottom">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="65dp">

      <ImageView
          android:id="@+id/camera_button_image"
          android:layout_width="40dp"
          android:layout_height="40dp"
          android:layout_centerHorizontal="true"
          android:contentDescription="@string/camera_button_content_desc"
          android:onClick="openCamera"
          android:src="@drawable/ic_camera_alt_white"/>

      <TextView
          android:id="@+id/camera_button_text"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@id/camera_button_image"
          android:layout_marginTop="7dp"
          android:onClick="openCamera"
          android:text="@string/camera_button_text"
          android:textColor="@color/whitePrimary"/>
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

      <ImageView
          android:id="@+id/gallery_button_image"
          android:layout_width="40dp"
          android:layout_height="40dp"
          android:layout_centerHorizontal="true"
          android:contentDescription="@string/gallery_button_content_desc"
          android:onClick="openGallery"
          android:src="@drawable/ic_phone_android_white"/>

      <TextView
          android:id="@+id/gallery_button_text"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@id/gallery_button_image"
          android:layout_marginTop="7dp"
          android:onClick="openGallery"
          android:text="@string/gallery_button_text"
          android:textColor="@color/whitePrimary"/>
    </RelativeLayout>

  </LinearLayout>

</RelativeLayout>

以下是 activity_main XML 文件:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context="com.example.photoeditor.MainActivity">

  <ImageView
      android:id="@+id/edited_image_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:adjustViewBounds="true"
      android:contentDescription="@string/edited_image_content_desc"/>

</LinearLayout>

问题是在捕获图像之后,然后在从应用程序编辑照片之后,然后当必须保存图像时,我发现图像没有保存在 phone

当我在 Android Studio 中看到 Logcat 时,我看到了这个警告:

2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor D/skia-encoders: [time] JPEG Decode 951
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: decode time: 952
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: bitmap.size: 5184x3880
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor I/moahd-jni: resize(15)
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: bitmap MP: 20, max MP: 15
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor W/moahd-jni: Image must be resized! 20MP -> 15MP
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: target: 15MP = (4477x3351), max size: 4477
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: original: 20MP = (5184x3880)
2018-10-27 23:59:57.250 2437-3574/com.example.photoeditor V/moahd-jni: maxWidth: 4477, maxHeight: 3351

所以只有当 phone 的相机尺寸超过 15Megapixel 时拍摄图像才会出现保存问题。

谁能帮忙提供可能的代码解决方案?

提前致谢

使用此代码调整大小并保存:

Bitmap image = (Bitmap) "your image";
image = Bitmap.createScaledBitmap(photo, 100, 100, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 60, bytes);

File file = new File(Environment.getExternalStorageDirectory()
        + File.separator + "name.jpg");
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();

60表示压缩质量:0是最高压缩质量低。 100 是最低压缩最高质量