Android:使用比双线性更好的重采样算法调整位图大小(如 Lanczos3)
Android: Bitmap resizing using better resampling algorithm than bilinear (like Lanczos3)
是否有任何方法或外部库可以使用 Lanczos(理想情况下)或至少使用双三次算法调整图像大小。在 Android 下? (当然越快越好,但质量优先,处理时间次之)
到目前为止我得到的一切都是这样的:
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
但是它使用双线性滤波器,输出质量很差。特别是如果您想保留细节(如细线或可读文本)。
Java 有许多不错的库,例如此处讨论的:
Java - resize image without losing quality
但是它总是依赖于Java awt classes like java.awt.image.BufferedImage
, 所以它不能在Android.
中使用
有没有一种方法可以更改 Bitmap.createScaledBitmap()
方法中的默认(双线性)过滤器或某些能够与 android.graphics.Bitmap
class 一起使用的库,例如 Morten Nobel's lib (或者使用一些原始表示,正如评论中的@Tron 所指出的那样)?
我最近将此写到 scale/crop 特定分辨率的图像并以质量压缩它:
public static void scaleImageToResolution(Context context, File image, int dstWidth, int dstHeight) {
if (dstHeight > 0 && dstWidth > 0 && image != null) {
Bitmap result = null;
try {
//Get Image Properties
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image.getAbsolutePath(), bmOptions);
int photoH = bmOptions.outHeight;
int photoW = bmOptions.outWidth;
bmOptions.inJustDecodeBounds = false;
bmOptions.inPurgeable = true;
//Smaller Image Size in Memory with Config
bmOptions.inPreferredConfig = Bitmap.Config.RGB_565;
//Is resolution not the same like 16:9 == 4:3 then crop otherwise fit
ScalingLogic scalingLogic = getScalingLogic(photoW, photoH,dstWidth, dstHeight);
//Get Maximum automatic downscaling that it's still bigger then this requested resolution
bmOptions.inSampleSize = calculateScalingSampleSize(photoW, photoH, dstWidth, dstHeight, scalingLogic);
//Get unscaled Bitmap
result = BitmapFactory.decodeFile(image.getAbsolutePath(), bmOptions);
//Scale Bitmap to requested Resolution
result = scaleImageToResolution(context, result, scalingLogic);
if (result != null) {
//Save Bitmap with quality
saveImageWithQuality(context, result, image);
}
} finally {
//Clear Memory
if (result != null)
result.recycle();
}
}
}
public static void saveImageWithQuality(Bitmap bitmap, String path, int compressQuality) {
try {
FileOutputStream fOut;
fOut = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, fOut);
fOut.flush();
fOut.close();
} catch (IOException ex) {
if (Logger.getRootLogger() != null)
Logger.getRootLogger().error(ex);
else
Log.e("saveImageWithQuality", "Error while saving compressed Picture: " + ex.getMessage() + StringUtils.newLine() + ex.getStackTrace().toString());
}
}
public static void saveImageWithQuality(Context context, Bitmap bitmap, File file) {
saveImageWithQuality(bitmap, file.getAbsolutePath(), getCompressQuality());
}
public static void saveImageWithQuality(Context context, Bitmap bitmap, String path) {
saveImageWithQuality(bitmap, path, getCompressQuality());
}
private static int calculateScalingSampleSize(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;
}
}
}
private static Bitmap scaleImageToResolution(Context context, Bitmap unscaledBitmap, ScalingLogic scalingLogic, int dstWidth, int dstHeight) {
//Do Rectangle of original picture when crop
Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
//Do Rectangle to fit in the source rectangle
Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
//insert source rectangle into new one
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
//Recycle the unscaled Bitmap afterwards
unscaledBitmap.recycle();
return scaledBitmap;
}
private static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.CROP) {
if (srcWidth >= srcHeight) {
//Horizontal
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
final int srcRectHeight = (int) (srcWidth / dstAspect);
final int scrRectTop = (srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
} else {
final int srcRectWidth = (int) (srcHeight * dstAspect);
final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
}
} else {
//Vertikal
final float srcAspect = (float) srcHeight / (float) srcWidth;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(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 = (srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
}
}
} else {
return new Rect(0, 0, srcWidth, srcHeight);
}
}
private static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
if (srcWidth > srcHeight) {
//Vertikal
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
return new Rect(0, 0, (int) (dstHeight * srcAspect), dstHeight);
} else {
return new Rect(0, 0, dstWidth, (int) (dstWidth / srcAspect));
}
} else {
//Horizontal
final float srcAspect = (float) srcHeight / (float) srcWidth;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
return new Rect(0, 0, (int) (dstHeight / srcAspect), dstHeight);
} else {
return new Rect(0, 0, dstWidth, (int) (dstWidth * srcAspect));
}
}
} else {
if (srcWidth >= srcHeight)
return new Rect(0, 0, dstWidth, dstHeight);
else
return new Rect(0, 0, dstHeight, dstWidth);
}
}
private static ScalingLogic getScalingLogic(int imageWidth, int imageHeight, int dstResolutionWidth, int dstResolutionHeight) {
if (imageWidth >= imageHeight) {
//Bild horizontal
final float srcAspect = (float) imageWidth / (float) imageHeight;
final float dstAspect = (float) dstResolutionWidth / (float) dstResolutionHeight;
if (!isResolutionEqual(srcAspect, dstAspect)) {
return ScalingLogic.CROP;
} else {
return ScalingLogic.FIT;
}
} else {
//Bild vertikal
final float srcAspect = (float) imageHeight / (float) imageWidth;
final float dstAspect = (float) dstResolutionWidth / (float) dstResolutionHeight;
if (!isResolutionEqual(srcAspect, dstAspect)) {
return ScalingLogic.CROP;
} else {
return ScalingLogic.FIT;
}
}
}
public enum PictureQuality {
High,
Medium,
Low
}
public enum ScalingLogic {
CROP,
FIT
}
//Does resolution match
private static boolean isResolutionEqual(float v1, float v2) {
// Falls a 1.999999999999 and b = 2.000000000000
return v1 == v2 || Math.abs(v1 - v2) / Math.max(Math.abs(v1), Math.abs(v2)) < 0.01;
}
public int getCompressQuality() {
if (Quality == PictureQuality.High)
return 100;
else if (Quality == PictureQuality.Medium)
return 50;
else if (Quality == PictureQuality.Low)
return 25;
else return 0;
}
它没有使用您提到的库,但它可以工作,我对此很满意。也许你也是。
不幸的是 Android 使用 android.graphics.Bitmap java 中不存在的 android.graphics.Bitmap
而 java 使用 java.awt.image.BufferedImage 而 android 中不存在 :-(
我没有 a ready to use library for android
但是如何将 java-awt 特定库移植到平台独立 java 库与 android 的平台特定处理程序的路径和awt/j2se
在 java 重新缩放库中,您必须隐藏所有 java-awt 特定 类(如 BufferedImage)在接口 IBitmap
后面并为 j2se 实现该接口并独立地 Android.
我已经成功完成 exif/icc/ipc 元数据处理并实现了接口 pixymeta-lib/.../IBitmap.java with implementation for j2se pixymeta-j2se-lib/.../j2se/BitmapNative.java and android pixymeta-android-lib/.../android/BitmapNative.java
所以我有这些包裹
- pixymeta-lib
- 转换后的平台独立库,其中所有 awt 引用都替换为
IBitmap
接口
- pixymeta-j2se-lib
- awt/j2se 执行
IBitmap
- pixymeta-android-lib
- android 执行
IBitmap
最有希望的IMO是使用libswscale (from FFmpeg), it offers Lanczos and many other filters. To access Bitmap
buffer from native code you can use jnigraphics。这种方法保证了良好的性能和可靠的结果。
编辑
Here 您可以找到使用建议方法的粗略演示应用程序。目前性能非常糟糕,因此应该进行调查以决定我们是否要采取一些措施来改进它。
这是我用来调整图像大小的代码..
Bitmap photo1 ;
private byte[] imageByteArray1 ;
BitmapFactory.Options opt1 = new BitmapFactory.Options();
opt1.inJustDecodeBounds=true;
BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),opt1);
// The new size we want to scale to
final int REQUIRED_SIZE=320;
// Find the correct scale value. It should be the power of 2.
int width_tmp=opt1.outWidth,height_tmp=opt1.outHeight;
int scale=2;
while(true){
if(width_tmp>REQUIRED_SIZE||height_tmp>REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
// Decode with inSampleSize
BitmapFactory.Options o2=new BitmapFactory.Options();
o2.inSampleSize=scale;
o2.inJustDecodeBounds=false;
photo1=BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),o2);
ByteArrayOutputStream baos1=new ByteArrayOutputStream();
photo1.compress(Bitmap.CompressFormat.JPEG,60,baos1);
imageByteArray1=baos1.toByteArray();
希望对你有所帮助..
如果您只是想以一种针对显示目的优化的方式对图像重新取样,您可以使用这个非常适合我的漂亮的小衬垫。
Bitmap bitmap = new BitmapDrawable(getResources(), yourBitmap).getBitmap();
这行代码可能看起来很奇怪,因为您正在将位图转换为 BitmapDrawable 并再次转换回位图,但 BitmapDrawable 默认为设备的像素密度(除非您使用不同的构造函数)。
如果您还需要调整大小,则只需将其分成两行并在将 BitmapDrawable 转换回位图之前使用 setBounds,如下所示:
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), yourBitmap);
bitmapDrawable.setBounds(left, top, right, bottom); //Make it a new size in pixels.
yourBitmap = bitmapDrawable.getBitmap(); //Convert it back to a bitmap optimised for display purposes.
位图可绘制对象可能被列为 depricated,但事实并非如此,只有某些构造函数被 depricated,而上述示例中的构造函数没有被 depricated。这也适用于 API 4
另外,android 文档在此处有一个可下载的示例:https://developer.android.com/topic/performance/graphics/load-bitmap.html
希望这对您有所帮助。
是否有任何方法或外部库可以使用 Lanczos(理想情况下)或至少使用双三次算法调整图像大小。在 Android 下? (当然越快越好,但质量优先,处理时间次之)
到目前为止我得到的一切都是这样的:
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
但是它使用双线性滤波器,输出质量很差。特别是如果您想保留细节(如细线或可读文本)。
Java 有许多不错的库,例如此处讨论的: Java - resize image without losing quality
但是它总是依赖于Java awt classes like java.awt.image.BufferedImage
, 所以它不能在Android.
有没有一种方法可以更改 Bitmap.createScaledBitmap()
方法中的默认(双线性)过滤器或某些能够与 android.graphics.Bitmap
class 一起使用的库,例如 Morten Nobel's lib (或者使用一些原始表示,正如评论中的@Tron 所指出的那样)?
我最近将此写到 scale/crop 特定分辨率的图像并以质量压缩它:
public static void scaleImageToResolution(Context context, File image, int dstWidth, int dstHeight) {
if (dstHeight > 0 && dstWidth > 0 && image != null) {
Bitmap result = null;
try {
//Get Image Properties
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image.getAbsolutePath(), bmOptions);
int photoH = bmOptions.outHeight;
int photoW = bmOptions.outWidth;
bmOptions.inJustDecodeBounds = false;
bmOptions.inPurgeable = true;
//Smaller Image Size in Memory with Config
bmOptions.inPreferredConfig = Bitmap.Config.RGB_565;
//Is resolution not the same like 16:9 == 4:3 then crop otherwise fit
ScalingLogic scalingLogic = getScalingLogic(photoW, photoH,dstWidth, dstHeight);
//Get Maximum automatic downscaling that it's still bigger then this requested resolution
bmOptions.inSampleSize = calculateScalingSampleSize(photoW, photoH, dstWidth, dstHeight, scalingLogic);
//Get unscaled Bitmap
result = BitmapFactory.decodeFile(image.getAbsolutePath(), bmOptions);
//Scale Bitmap to requested Resolution
result = scaleImageToResolution(context, result, scalingLogic);
if (result != null) {
//Save Bitmap with quality
saveImageWithQuality(context, result, image);
}
} finally {
//Clear Memory
if (result != null)
result.recycle();
}
}
}
public static void saveImageWithQuality(Bitmap bitmap, String path, int compressQuality) {
try {
FileOutputStream fOut;
fOut = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, fOut);
fOut.flush();
fOut.close();
} catch (IOException ex) {
if (Logger.getRootLogger() != null)
Logger.getRootLogger().error(ex);
else
Log.e("saveImageWithQuality", "Error while saving compressed Picture: " + ex.getMessage() + StringUtils.newLine() + ex.getStackTrace().toString());
}
}
public static void saveImageWithQuality(Context context, Bitmap bitmap, File file) {
saveImageWithQuality(bitmap, file.getAbsolutePath(), getCompressQuality());
}
public static void saveImageWithQuality(Context context, Bitmap bitmap, String path) {
saveImageWithQuality(bitmap, path, getCompressQuality());
}
private static int calculateScalingSampleSize(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;
}
}
}
private static Bitmap scaleImageToResolution(Context context, Bitmap unscaledBitmap, ScalingLogic scalingLogic, int dstWidth, int dstHeight) {
//Do Rectangle of original picture when crop
Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
//Do Rectangle to fit in the source rectangle
Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(), dstWidth, dstHeight, scalingLogic);
//insert source rectangle into new one
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
//Recycle the unscaled Bitmap afterwards
unscaledBitmap.recycle();
return scaledBitmap;
}
private static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.CROP) {
if (srcWidth >= srcHeight) {
//Horizontal
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
final int srcRectHeight = (int) (srcWidth / dstAspect);
final int scrRectTop = (srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
} else {
final int srcRectWidth = (int) (srcHeight * dstAspect);
final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
}
} else {
//Vertikal
final float srcAspect = (float) srcHeight / (float) srcWidth;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(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 = (srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
}
}
} else {
return new Rect(0, 0, srcWidth, srcHeight);
}
}
private static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight, ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
if (srcWidth > srcHeight) {
//Vertikal
final float srcAspect = (float) srcWidth / (float) srcHeight;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
return new Rect(0, 0, (int) (dstHeight * srcAspect), dstHeight);
} else {
return new Rect(0, 0, dstWidth, (int) (dstWidth / srcAspect));
}
} else {
//Horizontal
final float srcAspect = (float) srcHeight / (float) srcWidth;
final float dstAspect = (float) dstWidth / (float) dstHeight;
if (srcAspect < dstAspect || isResolutionEqual(srcAspect, dstAspect)) {
return new Rect(0, 0, (int) (dstHeight / srcAspect), dstHeight);
} else {
return new Rect(0, 0, dstWidth, (int) (dstWidth * srcAspect));
}
}
} else {
if (srcWidth >= srcHeight)
return new Rect(0, 0, dstWidth, dstHeight);
else
return new Rect(0, 0, dstHeight, dstWidth);
}
}
private static ScalingLogic getScalingLogic(int imageWidth, int imageHeight, int dstResolutionWidth, int dstResolutionHeight) {
if (imageWidth >= imageHeight) {
//Bild horizontal
final float srcAspect = (float) imageWidth / (float) imageHeight;
final float dstAspect = (float) dstResolutionWidth / (float) dstResolutionHeight;
if (!isResolutionEqual(srcAspect, dstAspect)) {
return ScalingLogic.CROP;
} else {
return ScalingLogic.FIT;
}
} else {
//Bild vertikal
final float srcAspect = (float) imageHeight / (float) imageWidth;
final float dstAspect = (float) dstResolutionWidth / (float) dstResolutionHeight;
if (!isResolutionEqual(srcAspect, dstAspect)) {
return ScalingLogic.CROP;
} else {
return ScalingLogic.FIT;
}
}
}
public enum PictureQuality {
High,
Medium,
Low
}
public enum ScalingLogic {
CROP,
FIT
}
//Does resolution match
private static boolean isResolutionEqual(float v1, float v2) {
// Falls a 1.999999999999 and b = 2.000000000000
return v1 == v2 || Math.abs(v1 - v2) / Math.max(Math.abs(v1), Math.abs(v2)) < 0.01;
}
public int getCompressQuality() {
if (Quality == PictureQuality.High)
return 100;
else if (Quality == PictureQuality.Medium)
return 50;
else if (Quality == PictureQuality.Low)
return 25;
else return 0;
}
它没有使用您提到的库,但它可以工作,我对此很满意。也许你也是。
不幸的是 Android 使用 android.graphics.Bitmap java 中不存在的 android.graphics.Bitmap 而 java 使用 java.awt.image.BufferedImage 而 android 中不存在 :-(
我没有 a ready to use library for android
但是如何将 java-awt 特定库移植到平台独立 java 库与 android 的平台特定处理程序的路径和awt/j2se
在 java 重新缩放库中,您必须隐藏所有 java-awt 特定 类(如 BufferedImage)在接口 IBitmap
后面并为 j2se 实现该接口并独立地 Android.
我已经成功完成 exif/icc/ipc 元数据处理并实现了接口 pixymeta-lib/.../IBitmap.java with implementation for j2se pixymeta-j2se-lib/.../j2se/BitmapNative.java and android pixymeta-android-lib/.../android/BitmapNative.java
所以我有这些包裹
- pixymeta-lib
- 转换后的平台独立库,其中所有 awt 引用都替换为
IBitmap
接口
- 转换后的平台独立库,其中所有 awt 引用都替换为
- pixymeta-j2se-lib
- awt/j2se 执行
IBitmap
- awt/j2se 执行
- pixymeta-android-lib
- android 执行
IBitmap
- android 执行
最有希望的IMO是使用libswscale (from FFmpeg), it offers Lanczos and many other filters. To access Bitmap
buffer from native code you can use jnigraphics。这种方法保证了良好的性能和可靠的结果。
编辑
Here 您可以找到使用建议方法的粗略演示应用程序。目前性能非常糟糕,因此应该进行调查以决定我们是否要采取一些措施来改进它。
这是我用来调整图像大小的代码..
Bitmap photo1 ;
private byte[] imageByteArray1 ;
BitmapFactory.Options opt1 = new BitmapFactory.Options();
opt1.inJustDecodeBounds=true;
BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),opt1);
// The new size we want to scale to
final int REQUIRED_SIZE=320;
// Find the correct scale value. It should be the power of 2.
int width_tmp=opt1.outWidth,height_tmp=opt1.outHeight;
int scale=2;
while(true){
if(width_tmp>REQUIRED_SIZE||height_tmp>REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
// Decode with inSampleSize
BitmapFactory.Options o2=new BitmapFactory.Options();
o2.inSampleSize=scale;
o2.inJustDecodeBounds=false;
photo1=BitmapFactory.decodeFile(imageUrl.get(imgCount).toString(),o2);
ByteArrayOutputStream baos1=new ByteArrayOutputStream();
photo1.compress(Bitmap.CompressFormat.JPEG,60,baos1);
imageByteArray1=baos1.toByteArray();
希望对你有所帮助..
如果您只是想以一种针对显示目的优化的方式对图像重新取样,您可以使用这个非常适合我的漂亮的小衬垫。
Bitmap bitmap = new BitmapDrawable(getResources(), yourBitmap).getBitmap();
这行代码可能看起来很奇怪,因为您正在将位图转换为 BitmapDrawable 并再次转换回位图,但 BitmapDrawable 默认为设备的像素密度(除非您使用不同的构造函数)。
如果您还需要调整大小,则只需将其分成两行并在将 BitmapDrawable 转换回位图之前使用 setBounds,如下所示:
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), yourBitmap);
bitmapDrawable.setBounds(left, top, right, bottom); //Make it a new size in pixels.
yourBitmap = bitmapDrawable.getBitmap(); //Convert it back to a bitmap optimised for display purposes.
位图可绘制对象可能被列为 depricated,但事实并非如此,只有某些构造函数被 depricated,而上述示例中的构造函数没有被 depricated。这也适用于 API 4
另外,android 文档在此处有一个可下载的示例:https://developer.android.com/topic/performance/graphics/load-bitmap.html
希望这对您有所帮助。