Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在ImageView中保存时,从自定义相机拍摄图像会被拉伸_Android_Android Camera_Android Imageview - Fatal编程技术网

Android 在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

我使用此代码在Imageview中保存pic,但在Imageview中保存数据时图像会被拉伸。相机预览是完美的,单击右键图像,但当我在imageview中设置该图像时,该图像被隐藏

    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(结果)

  • 将捕获的图片保存为相机预览。通过Camera.Parameters执行此操作

    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);