Android 在ImageView中保存时,从自定义相机拍摄图像会被拉伸
我使用此代码在Imageview中保存pic,但在Imageview中保存数据时图像会被拉伸。相机预览是完美的,单击右键图像,但当我在imageview中设置该图像时,该图像被隐藏Android 在ImageView中保存时,从自定义相机拍摄图像会被拉伸,android,android-camera,android-imageview,Android,Android Camera,Android Imageview,我使用此代码在Imageview中保存pic,但在Imageview中保存数据时图像会被拉伸。相机预览是完美的,单击右键图像,但当我在imageview中设置该图像时,该图像被隐藏 public void onPicTaken(byte[] data) { if (data != null) { int screenWidth = getResources().getDisplayMetrics().widthPixels; int screen
public void onPicTaken(byte[] data) {
if (data != null) {
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Notice that width and height are reversed
Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
int w = scaled.getWidth();
int h = scaled.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
}else{// LANDSCAPE MODE
//No need to reverse width and height
Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth,screenHeight , true);
bm=scaled;
}
ivCaptureImagePreview.setImageBitmap(bm);
ivCaptureImagePreview.setVisibility(View.VISIBLE);
}
}
使用此选项可以防止图像拉伸并保持图像的纵横比
android:scaleType="fitXY" // or desired scale type
android:adjustViewBounds="true"
ui图像视图设置
<ImageView
android:id="@id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
用于从相机或图像选择器获取结果,并在imageView中显示。此处此.myInterfaceImage
:
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode)
{
case REQUEST_PICK_IMAGE:
if(resultCode == Activity.RESULT_OK)
{
selectedImageUri = data.getData();
initImage(selectedImageUri);
}
break;
case REQUEST_TAKE_IMAGE:
if(resultCode == Activity.RESULT_OK)
{
initImage(selectedImageUri);
}
break;
}
}
protected void initImage(Uri selectedImageUri_) {
try {
ParcelFileDescriptor parcelFileDescriptor = getContext().getContentResolver().openFileDescriptor(selectedImageUri_, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap source = BitmapFactory.decodeFileDescriptor(fileDescriptor);
float ratio = (float)source.getWidth() / (float)source.getHeight();
// here perhaps limit the size of the image
int height = Math.min(getContext().getResources().getDisplayMetrics().heightPixels, source.getHeight());
int width = (int)(ratio*height);
Bitmap result = Bitmap.createScaledBitmap(source, width, height, false);
this.interfaceImage.setImageBitmap(result);
if (result != source) {
source.recycle();
}
} catch (Exception ex) {
System.out.println("File not found");
}
}
这就是我在我的测试应用程序中使用它的方式,它可以工作,我没有任何方向问题。我在纵向模式下测试了纵向和横向图片,在横向模式下测试了纵向和横向图片。在拍摄图像之前,我改变了方向
如果您使用的是定制相机,且方向与上述代码错误,只需添加此项即可
<ImageView
android:id="@id/img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
需要做两件事:
camera.setDisplayOrientation(结果)代码>
int-mRotation=getCameraRadisPlayOrientation();
Camera.Parameters=Camera.getParameters();
参数。设置旋转(旋转)//设置旋转以保存图片
摄像头。设置显示方向(结果)//设置预览摄影机的旋转
设置参数(参数)代码>
public void onPicTaken(byte[] data) {
if (data != null) {
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
int screenWidth = getResources().getDisplayMetrics().widthPixels;
float ratio = (float)bm.getWidth() / (float)bm.getHeight();
int screenHeight = (int)(ratio*screenWidth)
Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
if (scaled != bm) {
source.recycle();
}
ivCaptureImagePreview.setImageBitmap(scaled);
ivCaptureImagePreview.setVisibility(View.VISIBLE);
}
}
希望能有所帮助。在您的意向通话中使用此putExtra
intent.putExtra("outputX", 80);
intent.putExtra("outputY", 80);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 20);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, Utility.REQUEST_FOR_CAMERA);
我在我的一个项目中使用此功能,请检查它是否对您有用
public static Bitmap Preview(String path) {
//SCALE IMAGE
int SCALE = 4;
try {
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = SCALE;
Bitmap bitmap = BitmapFactory.decodeFile(path, o2);
OutputStream os = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
os.flush();
os.close();
File file = new File(path);
while (file.length() > 800000) {
SCALE += 2;
o2.inSampleSize = SCALE;
bitmap = BitmapFactory.decodeFile(path, o2);
os = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
os.flush();
os.close();
file = new File(path);
}
bitmap = BitmapFactory.decodeFile(path, o2);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
使用以下类创建缩放位图
public class ScalingUtilities
{
/**
* Utility function for decoding an image resource. The decoded bitmap will
* be optimized for further scaling to the requested destination dimensions
* and scaling logic.
*
* @param res The resources object containing the image data
* @param resId The resource id of the image data
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Decoded bitmap
*/
public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic);
Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);
return unscaledBitmap;
}
/**
* Utility function for creating a scaled version of an existing bitmap
*
* @param unscaledBitmap Bitmap to scale
* @param dstWidth Wanted width of destination bitmap
* @param dstHeight Wanted height of destination bitmap
* @param scalingLogic Logic to use to avoid image stretching
* @return New scaled bitmap object
*/
public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}
/**
* ScalingLogic defines how scaling should be carried out if source and
* destination image has different aspect ratio.
*
* CROP: Scales the image the minimum amount while making sure that at least
* one of the two dimensions fit inside the requested destination area.
* Parts of the source image will be cropped to realize this.
*
* FIT: Scales the image the minimum amount while making sure both
* dimensions fit inside the requested destination area. The resulting
* destination dimensions might be adjusted to a smaller size than
* requested.
*/
public static enum ScalingLogic {
CROP, FIT
}
/**
* Calculate optimal down-sampling factor given the dimensions of a source
* image, the dimensions of a destination area and a scaling logic.
*
* @param srcWidth Width of source image
* @param srcHeight Height of source image
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Optimal down scaling sample size for decoding
*/
public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
} else {
return srcHeight / dstHeight;
}
} else {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcHeight / dstHeight;
} else {
return srcWidth / dstWidth;
}
}
}
/**
* Calculates source rectangle for scaling bitmap
*
* @param srcWidth Width of source image
* @param srcHeight Height of source image
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Optimal source rectangle
*/
public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.CROP) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
final int srcRectWidth = (int)(srcHeight * dstAspect);
final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
} else {
final int srcRectHeight = (int)(srcWidth / dstAspect);
final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
}
} else {
return new Rect(0, 0, srcWidth, srcHeight);
}
}
/**
* Calculates destination rectangle for scaling bitmap
*
* @param srcWidth Width of source image
* @param srcHeight Height of source image
* @param dstWidth Width of destination area
* @param dstHeight Height of destination area
* @param scalingLogic Logic to use to avoid image stretching
* @return Optimal destination rectangle
*/
public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
} else {
return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
}
} else {
return new Rect(0, 0, dstWidth, dstHeight);
}
}
}
并在函数中使用该类,如下所示
public void onPicTaken(byte[] data) {
if (data != null) {
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int screenHeight = getResources().getDisplayMetrics().heightPixels;
Bitmap bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Notice that width and height are reversed
Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT);
int w = scaled.getWidth();
int h = scaled.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
}else{// LANDSCAPE MODE
//No need to reverse width and height
Bitmap scaled = ScalingUtilities.createScaledBitmap(bm, screenHeight, screenWidth, ScalingLogic.FIT);
bm=scaled;
}
ivCaptureImagePreview.setImageBitmap(bm);
ivCaptureImagePreview.setVisibility(View.VISIBLE);
}
}
使用
位图缩放位图。createScaledBitmap(bm、屏幕高度、屏幕宽度、true)
不会保持纵横比,因为这会拉伸位图的宽度和高度以匹配目标
一个选项是手动计算目标高度,这样就不会发生裁剪:
double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
int targetHeight = (int) (screenWidth * aspectRatio);
然后在createScaledBitmap()中使用targetHeight
而不是screenHeight
作为高度参数
此外,确保加载位图的imageview具有适当的缩放类型(例如,调整中心或中心裁剪)。如文档中所示; 在渲染之前,您必须调整位图的大小并重新缩放位图,以便可以将下面的代码用于位图工厂。选项:
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
它将图像定位转换为景观mode@NeerajSharma更新了我的代码,它在我的测试应用程序中运行良好。您的代码仅在横向模式下运行良好,而不是在红外纵向模式下运行。兄弟。@NeerajSharma您使用了我的全部代码吗。takeImageIntent和initImage在我的测试应用程序中运行良好。我应该添加屏幕截图吗?@NeerajSharma,因为我从其他问题中了解到您正在使用自定义相机。请参阅最后一节。如果您使用的是自定义相机,且方向错误。只需将此添加到代码中。但在保留比率的情况下,必须使用我的initImage函数。@SrujanBarai其矩阵方法在矩阵对象matrix mtx=new matrix()上调用它;mtx.旋转后(90);