在ImageView中保存时,从自定义相机拍摄图像会被拉伸

时间:2016-02-29 07:28:34

标签: android android-camera android-imageview

我正在使用此代码在Imageview中保存图片,但在imageview中的dsave时图像被拉伸。相机预览是完美的,然后单击右图像,但是当我在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);
    }

}

7 个答案:

答案 0 :(得分:5)

使用以下类创建缩放位图

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

}

答案 1 :(得分:1)

UIImageView设置

<ImageView
    android:id="@id/img"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter" />

此问题的测试应用

对于从相机获取图片,我使用以下方法:

private void pickImageIntent()
{
    Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    getCurrentActivity().startActivityForResult(pickPhoto, REQUEST_PICK_IMAGE);
}

private void takeImageIntent()
{
    try
    {
        File outputDir = getCurrentActivity().getExternalCacheDir();
        File outputFile = File.createTempFile("prefix", "extension", outputDir);
        selectedImageUri = Uri.fromFile(outputFile);

        Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        takePicture.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageUri);
        getCurrentActivity().startActivityForResult(takePicture, REQUEST_TAKE_IMAGE);
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

从相机或图像选取器获取结果,并在imageView中显示。这里this.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");
    }
}

这就是我在My Test Application中使用它的方式,它起作用我没有任何方向问题。我在人像模式下使用人像和风景图片进行了测试,在风景模式下使用人像和风景图片进行了测试并且在获得图像之前我改变了方向。

如果您使用的是自定义相机并且上方代码的方向错误,只需添加

需要做两件事:

  1. 相机预览需要与您的旋转相同。通过

    设置

    camera.setDisplayOrientation(result);

  2. 将拍摄的照片保存为相机预览。通过Camera.Parameters完成此操作。

    int mRotation = getCameraDisplayOrientation(); Camera.Parameters parameters = camera.getParameters(); parameters.setRotation(mRotation); //set rotation to save the picture camera.setDisplayOrientation(result); //set the rotation for preview camera camera.setParameters(parameters);

  3. 然后您可以使用没有方向性的功能

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

    希望有所帮助。

答案 2 :(得分:0)

使用它可以防止图像拉伸并保持图像的纵横比

$statementResult->content->getStatements();

答案 3 :(得分:0)

我在我的项目中使用此功能,请检查它是否对您有用。

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

答案 4 :(得分:0)

您可以在xml中设置scaleType

<ImageView
        android:id="@+id/iv_imageview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter" />

在Java代码中,您可以像这样实现相同的

ImageView mImageView = (ImageView) findViewById(R.id.iv_imageview); 
mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); 

答案 5 :(得分:0)

正如您在文档 enter link description here 中所见; 您必须在渲染之前调整位图的大小和缩放比例,以便您可以将以下代码用于 BitmapFactory.Options

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

答案 6 :(得分:-1)

在你的相机意图调用中使用此putExtra

s <- unlist(lapply(posText, function(x) { str_split(x, "\n") }))

tagPOS <-  function(x, ...) {
  s <- as.String(x)
  word_token_annotator <- Maxent_Word_Token_Annotator()
  a2 <- Annotation(1L, "sentence", 1L, nchar(s))
  a2 <- annotate(s, word_token_annotator, a2)
  a3 <- annotate(s, Maxent_POS_Tag_Annotator(), a2)
  a3w <- a3[a3$type == "word"]
  POStags <- unlist(lapply(a3w$features, `[[`, "POS"))
  POStagged <- paste(sprintf("%s/%s", s[a3w], POStags), collapse = " ")
  list(POStagged = POStagged, POStags = POStags)
}

tagged_str <-  tagPOS(s)