У меня есть приложение для редактирования фотографий. Все, что он делает, это добавить изображения на базовую фотографию. Выходная фотография более низкое, чем исходная фотография, которую снимает камера. Это ожидается, но, возможно, я смогу улучшить то, что у меня есть. Это то же качество в 500px, что и 1000px, что очень важно ... Я вижу, что я ограничиваю качество где-то, кроме пикселей. Исходные фотографии в галерее камеры - файлы JPG. Вот все, что я делаю, чтобы получить фотографию, создать растровое изображение и сохранить ее. Можете ли вы рассказать мне, где в коде качество фотографии может снизиться?Качество изображения - Android
открытая галерея Цель:
Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 1);
OnActivityResult() для выбранной фотографии:
if (intent != null && resultcode == RESULT_OK)
{
mProfilePicPath = ih.getSelectedImageFilePathFromGallery(this.getApplicationContext(), intent);
mPortraitPhoto = ih.decodeSampledBitmapFromImagePath(mProfilePicPath,
GlobalConstants.PROFILE_PICTURE_RESOLUTION,
GlobalConstants.PROFILE_PICTURE_RESOLUTION);
}
public String getSelectedImageFilePathFromGallery(Context ctx,
Intent intent) {
Uri selectedImage = intent.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = ctx.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
public Bitmap decodeSampledBitmapFromImagePath(String imagePath, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Log.d("Image dims", imageType + ", " + imageHeight + ", " + imageWidth + "size.");
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap portraitPhoto = ImageHelper.convertToPortraitOrientation(options, imagePath);
return portraitPhoto;
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height/2;
final int halfWidth = width/2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight/inSampleSize) > reqHeight
&& (halfWidth/inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
public static Bitmap convertToPortraitOrientation(BitmapFactory.Options options, String path) {
Uri actualUri = Uri.parse(path);
float degree = 0;
Bitmap bmp = BitmapFactory.decodeFile(path, options);
try {
ExifInterface exif = new ExifInterface(actualUri.getPath());
String exifOrientation = exif
.getAttribute(ExifInterface.TAG_ORIENTATION);
if (bmp != null) {
degree = getDegree(exifOrientation);
if (degree != 0)
bmp = createRotatedBitmap(bmp, degree);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bmp;
}
public static Bitmap createRotatedBitmap(Bitmap bm, float degree) {
Bitmap bitmap = null;
if (degree != 0) {
Matrix matrix = new Matrix();
matrix.preRotate(degree);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), matrix, true);
}
return bitmap;
}
public File createProfilePicSaveFileInternal(Context ctx) {
//mBackgroundImage.setImageBitmap(ih.decodeSampledBitmapFromImagePath(mProfilePicPath, 500, 500));
String path = ctx.getFilesDir() + File.separator + "My Folder";
File outputDir= new File(path);
outputDir.mkdirs();
File newFile = new File(path + "/" + mName + ".jpg");
return newFile;
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public void saveImage(Bitmap bitmap, Context ctx, File newFile) {
FileOutputStream fos;
newFile.setReadable(true, false);
try {
fos = new FileOutputStream(newFile);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
ctx.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
}
при нажатии кнопки:
File newInternalFile = ih.createProfilePicSaveFileInternal(this.getApplicationContext());
boolean s = newInternalFile.exists();
long length = newInternalFile.length();
ih.saveImage(mPortraitPhoto, this.getApplicationContext(), newInternalFile);
mPortraitPhoto = null;
public File createProfilePicSaveFileInternal(Context ctx) {
//mBackgroundImage.setImageBitmap(ih.decodeSampledBitmapFromImagePath(mProfilePicPath, 500, 500));
String path = ctx.getFilesDir() + File.separator + "My Folder";
File outputDir= new File(path);
outputDir.mkdirs();
File newFile = new File(path + "/" + mName + ".jpg");
return newFile;
}
После моего изображения первый сохранен, Я получаю это сохраненное изображение в его истинном виде, делая это (inSampleSize теперь 1):
public Bitmap getPortraitBitmapNotSampled(String imagePath){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Log.d("Dressing room photo dims", imageType + ", " + imageHeight + ", " + imageWidth + "size.");
// Calculate inSampleSize
options.inSampleSize = 1;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap portraitPhoto = ImageHelper.convertToPortraitOrientation(options, imagePath);
return portraitPhoto;
}
Я в конечном итоге принимает снимок экрана, чтобы получить выходное изображение так:
public Bitmap takeScreenshot() {
View v = findViewById(R.id.DressBig);
v.setDrawingCacheEnabled(true);
return v.getDrawingCache();
}
Затем окончательный сохранить:
private void saveClicked(){
finishedOutfit = takeScreenshot();
File newFile = ih.createOutfitSaveFileExternal();
File newInternalFile = ih.createOutfitSaveFileInternal(this.getApplicationContext());
ih.saveImage(finishedOutfit, this.getApplicationContext(), newFile);
ih.saveImage(finishedOutfit, this.getApplicationContext(), newInternalFile);
String newFilePath = newInternalFile.toString();
String newExternalFilePath = newFile.toString();
Log.d("db file path: ", newFilePath);
Log.d("external file path: ", newExternalFilePath);
insertOutfitInDB(newFilePath, newExternalFilePath);
showImageSavedDialog();
}
Есть ли у вас примеры изображений «before» и «after»? Возможность увидеть потерю качества, о котором вы говорите, может дать некоторое представление о том, связано ли это с сжатием JPEG или каким-либо другим источником. – Glenn
@Glenn Спасибо.Сейчас я поставлю эти фотографии сравнения. Как вы думаете, я должен проверить, какой тип файла имеет галерея, и попытаться сохранить этот тип файла? – user3164083
Все зависит от того, чего вы пытаетесь достичь. Если вам нужен однородный набор изображений того же размера и формата, сохранение типа файла является контрпродуктивным. Если вы хотите сохранить одинаковое качество изображения, чтение и запись JPEG таким образом очень опасно, потому что вы повторно сжимаете уже сжатые данные, что никогда не бывает хорошей новостью. – Glenn