我缩小了一些位图并获得了低质量的结果。我尝试了Bitmap#createScaledBitmap和Canvas#drawBitmap方法。在第一个中设置过滤器参数,在第二个的Paint对象中设置过滤器标志,但没有显示出明显的差异。
我尝试了在这些问题中找到的解决方案:
Bad image quality after resizing/scaling bitmap
Quality problems when resizing an image at runtime
Drawing scaled bitmaps on a SurfaceView -- no antialiasing
还有其他人。
正如某人所说,createScaledBitmap或Paint对象中的过滤器标志启用了双三次插值算法。但是,它没有任何区别。使用GIMP cubic(实际上是双三次),得到的图像比Android实现要好得多。
此处的API级别为19。
答案 0 :(得分:0)
试试这个,愿它帮助你。
public static Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth)
{
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
float xScale = (float) newWidth / sourceWidth;
float yScale = (float) newHeight / sourceHeight;
float scale = Math.max(xScale, yScale);
//get the resulting size after scaling
float scaledWidth = scale * sourceWidth;
float scaledHeight = scale * sourceHeight;
//figure out where we should translate to
float dx = (newWidth - scaledWidth) / 2;
float dy = (newHeight - scaledHeight) / 2;
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
Canvas canvas = new Canvas(dest);
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
matrix.postTranslate(dx, dy);
canvas.drawBitmap(source, matrix, null);
return dest;
}
答案 1 :(得分:0)
试试这个..
private Bitmap performResize(Bitmap bitmap, int requiredWidth,
int requiredHeight) {
int imageWidth = bitmap.getWidth();
int imageHeight = bitmap.getHeight();
float differenceWidth = requiredWidth - imageWidth;
float percentage = differenceWidth / imageWidth * 100;
float estimatedheight = imageHeight + (percentage * imageHeight / 100);
float estimatedwidth = requiredWidth;
if (estimatedheight < requiredHeight) {
float incresePercentage = (float) (requiredHeight - estimatedheight);
percentage += (incresePercentage / imageHeight * 100);
estimatedheight = imageHeight + (percentage * imageHeight / 100);
estimatedwidth = imageWidth + (percentage * imageWidth / 100);
}
bitmap = ScalingUtilities.performResize(bitmap, (int) estimatedheight,
(int) estimatedwidth);
if (bitmap.getHeight() < requiredHeight) // if calculate height is
// smaller then the required
// Height
{
} else {
int xCropPosition = (int) ((bitmap.getWidth() - requiredWidth) / 2);
int yCropPosition = (int) ((bitmap.getHeight() - requiredHeight) / 2);
bitmap = Bitmap.createBitmap(bitmap, xCropPosition, yCropPosition,
(int) requiredWidth, (int) requiredHeight);
}
return bitmap;
}
实用程序文件
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
/**
* Class containing static utility methods for bitmap decoding and scaling
*
* @author Andreas Agvard (andreas.agvard@sonyericsson.com)
*/
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, String path, 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.decodeFile(path, 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 static Bitmap performResize(Bitmap unscaledBitmap,int height,int width)
{
//Log.e("Scaling Bitmap",unscaledBitmap.toString() + " height" +height +" w="+width );
Bitmap scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, width, height, ScalingUtilities.ScalingLogic.FIT);
// if(scaledBitmap != null )
// scaledBitmap = ImageBlurUtility.fastblur(LiveWallpaperService.bitmap, LiveWallpaperService.imageBlurAmount);
//
unscaledBitmap.recycle();
return scaledBitmap;
}
public static Bitmap updateImageFromGallary(Context ctx,String imgPath,int reqWidth, int reqHeight)
{
Bitmap cameraBitmap=null;
try
{
cameraBitmap = decodeSampledBitmapFromResource(ctx.getResources(),imgPath,reqWidth,reqHeight);
//imgEdit.setImageBitmap(cameraBitmap);
}
catch(OutOfMemoryError outMemeoryError)
{
// Toast.makeText(this, "Unable to Load Image", Toast.LENGTH_SHORT).show();
}
return cameraBitmap;
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, String path,int reqWidth, int reqHeight)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPurgeable = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
//options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
//return BitmapFactory.decodeResource(res, resId, options);
// return BitmapFactory.decodeFile(path, options);
return BitmapFactory.decodeFile(path, options);
}
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)
{
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public static float convertDpToPixel(float dp, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return px;
}
/**
* This method converts device specific pixels to density independent pixels.
*
* @param px A value in px (pixels) unit. Which we need to convert into db
* @param context Context to get resources and device specific display metrics
* @return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
public static int convertToPx(int input,Context context) {
// Get the screen's density scale
final float scale = context.getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
Log.e("textSize","textSize scale value "+scale);
return (int) (input * scale + 0.5f);
}
}