Android:高质量图像resize/缩放

我需要缩小来自网络流的图像而不会降低质量。

我知道这个解决方案在将图像加载到Bitmap对象时奇怪的内存不足问题,但它太粗糙了 – inSampleSize是一个整数,并且不允许更精细地控制结果维度。 也就是说,我需要将图像缩放到特定的h / w尺寸(并保持纵横比)。

我不介意在我的代码中使用DIY bicubic / lancoz算法,但我找不到任何适用于Android的示例,因为它们都依赖于Java2D(JavaSE)。

编辑:我附上了一个快速的来源。 原来是720×402高清屏幕截图。 请忽略前2个缩略图。 Android(作为布局的一部分)将顶部大图像自动调整为大约130×72。 它很好而且清脆。 底部图像使用API​​resize并且具有严重的伪像

替代文字

我也试过使用BitmapFactory,正如我之前所说,它有两个问题 – 无法缩放到精确的大小,缩放的图像模糊。

关于如何修复艺术的任何想法?

谢谢,所以!

  package qp.test; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.os.Bundle; import android.widget.ImageView; public class imgview extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Bitmap original = BitmapFactory.decodeResource(getResources(), R.drawable.a000001570402); Bitmap resized = getResizedBitmap(original, 130); //Bitmap resized = getResizedBitmap2(original, 0.3f); System.err.println(resized.getWidth() + "x" + resized.getHeight()); ImageView image = (ImageView) findViewById(R.id.ImageViewFullManual); image.setImageBitmap(resized); } private Bitmap getResizedBitmap(Bitmap bm, int newWidth) { int width = bm.getWidth(); int height = bm.getHeight(); float aspect = (float)width / height; float scaleWidth = newWidth; float scaleHeight = scaleWidth / aspect; // yeah! // create a matrix for the manipulation Matrix matrix = new Matrix(); // resize the bit map matrix.postScale(scaleWidth / width, scaleHeight / height); // recreate the new Bitmap Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true); bm.recycle(); return resizedBitmap; } private Bitmap getResizedBitmap2(Bitmap bm, float scale) { /* float aspect = bm.getWidth() / bm.getHeight(); int scaleWidth = (int) (bm.getWidth() * scale); int scaleHeight = (int) (bm.getHeight() * scale); */ // original image is 720x402 and SampleSize=4 produces 180x102, which is // still too large BitmapFactory.Options bfo = new BitmapFactory.Options(); bfo.inSampleSize = 4; return BitmapFactory.decodeResource(getResources(), R.drawable.a000001570402, bfo); } } 

和布局

   <!--  -->      

你可以使用BitmapFactory.OptionsBitmapFactory.decode函数,
使用inDensityinTargetDensity

示例:您的图像尺寸为1600×1200 ,并希望调整为640×480
然后'inDensity'=5并且'inTargetDensity'=2 (1600×2等于640×5)。

希望这有帮助。

顶部大图像按布局缩小到450px,因此没有伪影。

底部大图像的瑕疵是通过布局将其缩小到130px宽然后再上升到大约450px。 所以工件是由你的缩放产生的。 尝试

 Bitmap resized = getResizedBitmap(original, 450); 

在你的代码中它应该没问题。 但是,您需要将其调整到手机的实际屏幕宽度。

简而言之,良好的缩减算法(不是最近邻居)包括两个步骤:

  1. 使用BitmapFactory.Options :: inSampleSize-> BitmapFactory.decodeResource()的缩减尽可能接近您需要但不低于它的分辨率
  2. 通过使用Canvas :: drawBitmap()降低一点点来获得精确的分辨率

以下是SonyMobile如何解决此任务的详细说明: http : //developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/

以下是SonyMobile scale utils的源代码: http : //developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/