尝试使用Android应用将照片保存到存储空间时出现问题。该应用程序使用设备相机拍摄照片并将其作为PNG保存到设备。
出于某种原因,无论我做什么或存储图像的地方,质量都很差。该应用程序是一个非常大的现有项目,所以我想知道在将图像保存到设备时是否还有其他因素需要考虑,或者可能是另一种覆盖质量的方法。
这是由前一个开发人员编码的函数:
public String saveImageToDevice(Bitmap image) {
saveCanvasImage(image);
String root = Environment.getExternalStorageDirectory().toString()+"/Android/data/com.app.android";
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fname = "Image-"+ timeStamp +".png";
File file = new File (myDir, fname);
if (file.exists ()){
file.delete ();
}
try {
Toast.makeText(getActivity(), "Saving Image...", Toast.LENGTH_SHORT).show();
Log.i("Image saved", root+"/saved_images/"+fname);
FileOutputStream out = new FileOutputStream(file);
image.compress(CompressFormat.PNG, 100, out);
imageLocations.add(fname);
out.flush();
out.close();
//return myDir.getAbsolutePath() + "/" +fname;
return fname;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
这是我在网上的一个例子中尝试过的功能:
public void saveCanvasImage(Bitmap b) {
File f = new File(Environment.getExternalStorageDirectory().toString() + "/img.png");
try {
f.createNewFile(); // your mistake was at here
FileOutputStream fos = new FileOutputStream(f);
b.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
这两者都产生相同的非常差的图像。我在下面发布了一个前后段。 这就是相机预览的样子。
这是保存后生成的图像。
在与少数人交谈后,我收到了我的相机意图代码:
public void startCameraIntent(){
/*************************** Camera Intent Start ************************/
// Define the file-name to save photo taken by Camera activity
String fileName = "Camera_Example.png";
// Create parameters for Intent with filename
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
values.put(MediaStore.Images.Media.DESCRIPTION,"Image capture by camera");
// imageUri is the current activity attribute, define and save it for later usage
@SuppressWarnings("unused")
Uri imageUri = getActivity().getContentResolver().insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
/**** EXTERNAL_CONTENT_URI : style URI for the "primary" external storage volume. ****/
// Standard Intent action that can be sent to have the camera
// application capture an image and return it.
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
//intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // set the image file name
startActivityForResult( intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
/*************************** Camera Intent End ************************/
}
正如您所看到的,EXTRA_OUTPUT行已被注释掉,因为它导致崩溃并出现以下错误:
12-17 13:31:37.339: E/AndroidRuntime(16123): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=65537, result=-1, data=null} to activity {}: java.lang.NullPointerException
我也包含了我的onActivityresult代码:
public void onActivityResult( int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
int page = mViewPager.getCurrentItem();
NotesPagerFragment note = pages.get(page);
Log.i("Request Code", ""+requestCode);
//For the ImageCapture Activity
if ( requestCode == 1) {
if ( resultCode != 0) {
/*********** Load Captured Image And Data Start ****************/
Bitmap bp = (Bitmap) data.getExtras().get("data");
//add the image to the note through a function call
note.addImage(bp);
note.saveImageToDevice(bp);
//String imageId = convertImageUriToFile( imageUri,CameraActivity);
// Create and excecute AsyncTask to load capture image
// new LoadImagesFromSDCard().execute(""+imageId);
/*********** Load Captured Image And Data End ****************/
} else if ( resultCode == 0) {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
}
}
//For the deleting an Image
if (requestCode == 2) {
String location = (String) data.getExtras().get("imageLocation");
if(data.getExtras().get("back") != null){
//just going back, don't mind me
}else {
//Toast.makeText(this.getActivity(), "BOO", Toast.LENGTH_SHORT).show();
note.removeNoteImageFromView(location);
database.removeSingleNoteImageFromSystemByLocation(location);
}
}
}
答案 0 :(得分:3)
好的,经过Melquiades的大量帮助,我最终解决了这个问题。我遇到的问题是我的意图和onActivityResult正在检索图像的缩略图并将其缩放(因此质量很差)。
以下行负责获取缩略图预览(120px x 160px):
Bitmap bp = (Bitmap) data.getExtras().get("data");
为了访问完整的图像,我需要将EXTRA_OUTPUT添加到intent,如下所示:
public void startCameraIntent(){
/*************************** Camera Intent Start ************************/
File imageFile = new File(imageFilePath);
Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri
// Standard Intent action that can be sent to have the camera
// application capture an image and return it.
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri); // set the image file name
startActivityForResult( intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
/*************************** Camera Intent End ************************/
}
我还将我的imageFilePath声明为活动顶部的字符串:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFilePath = Environment.getExternalStorageDirectory().toString()+"/Android/data/com.my.app/Image-"+timeStamp+".png";
然后,我必须更改onActivityResult,以便它可以访问要使用的完整图像:
public void onActivityResult( int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
int page = mViewPager.getCurrentItem();
NotesPagerFragment note = pages.get(page);
Log.i("Request Code", ""+requestCode);
//For the ImageCapture Activity
if ( requestCode == 1) {
if ( resultCode != 0) {
/*********** Load Captured Image And Data Start ****************/
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
//rotate image by 90 degrees
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), rotateMatrix, false);
//add the image to the note through a function call
note.addImage(rotatedBitmap);
note.saveImageToDevice(rotatedBitmap);
//String imageId = convertImageUriToFile( imageUri,CameraActivity);
// Create and excecute AsyncTask to load capture image
// new LoadImagesFromSDCard().execute(""+imageId);
/*********** Load Captured Image And Data End ****************/
} else if ( resultCode == 0) {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
}
}
//For the deleting an Image
if (requestCode == 2) {
String location = (String) data.getExtras().get("imageLocation");
if(data.getExtras().get("back") != null){
//just going back, don't mind me
}else {
//Toast.makeText(this.getActivity(), "BOO", Toast.LENGTH_SHORT).show();
note.removeNoteImageFromView(location);
database.removeSingleNoteImageFromSystemByLocation(location);
}
}
}
这里的关键部分是:
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
此代码将您在imageFilePath中保存的图像解码为可用的位图。从这里你可以正常使用它。
有时候(显然这很常见)图像会旋转90°,如果需要,下一位代码会旋转回来:
//rotate image by 90 degrees
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), rotateMatrix, false);