2010-11-17 147 views
27

我需要缩小来自网络流的图像而不会丢失质量。Android:高质量图像大小调整/缩放

我知道这个解决方案Strange out of memory issue while loading an image to a Bitmap object,但它太粗糙 - inSampleSize是一个整数,不允许更好地控制生成的维度。也就是说,我需要将图像缩放到特定的h/w尺寸(并保持宽高比)。

我不具有我的代码DIY双三次/ lancoz算法的头脑,但我不能找到,将在Android上工作,因为他们都依赖于Java2D的(JavaSE的)任何例子。编辑: 我附上了一个快速的来源。原来是720x402高清屏幕捕捉。请忽略前两个缩略图。顶部大图像由android(作为布局的一部分)自动调整大约130x72。它很好,很脆。底部的图像的大小与API和有严重的伪像

alt text

我使用BitmapFactory和也试过,正如我刚才所说,它有两个问题 - 没有办法扩展到精确的尺寸和比例图像模糊。

任何想法如何解决artifcating?

谢谢,S.O.!

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

} 

并且布局

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    > 
<!-- <TextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="hullo" android:background="#00ff00" 
    /> 
    --> 
    <ImageView android:id="@+id/ImageViewThumbAuto" 
      android:layout_width="130dip" android:layout_height="72dip" 
      android:src="@drawable/a000001570402" /> 

    <ImageView android:id="@+id/ImageViewThumbManual" 
      android:layout_width="130dip" android:layout_height="72dip" 
      android:src="@drawable/a000001570402" 
      android:layout_toRightOf="@id/ImageViewThumbAuto" 
      /> 

<ImageView android:id="@+id/ImageViewFullAuto" android:layout_width="300dip" 
      android:layout_height="169dip" 
      android:scaleType="fitXY" 
      android:src="@drawable/a000001570402" 
      android:layout_below="@id/ImageViewThumbAuto" 
      /> 

<ImageView android:id="@+id/ImageViewFullManual" android:layout_width="300dip" 
      android:layout_height="169dip" 
      android:scaleType="fitXY" 
      android:src="@drawable/a000001570402" 
      android:layout_below="@id/ImageViewFullAuto" 
      /> 

</RelativeLayout> 
+0

我不要认为顶部图像实际上是130px宽。 http://icons-search.com/img/fasticon/fast_emoticons_lnx.zip/fast_emoticons_lnx-Icons-128X128-smile_1.png-128x128.png是128像素宽.... – Quamis 2011-04-20 09:20:03

+0

检查出[本教程](http:///developer.android.com/training/displaying-bitmaps/index.html)解码图像。 – 2013-01-18 14:14:48

+0

嗨!面对同样的问题,你找到解决方案吗? – Dehimb 2016-08-11 16:35:12

回答

8

顶部大的图像被简单地由布局按比例缩小到450像素,从而没有伪影。

底部大的图像结果的从再升比例缩小以130px宽,然后由布局大约450像素的伪影。所以工件是由你的缩放制成的。尝试

Bitmap resized = getResizedBitmap(original, 450); 
在你的代码

,它应该是罚款。但是,您需要将其适应手机的实际屏幕宽度。

9

您可以使用BitmapFactory.Options使用inDensityinTargetDensity

BitmapFactory.decode功能(S),
:你有1600x1200的大小的图片,并希望调整到640×480
然后'inDensity'=5'inTargetDensity'=2(1600x2等于640x5)。

希望这帮助。

+0

不幸的是,这会产生最近邻居的降尺度。正如我想到的,为了保持双三次降尺度,只允许改变inSampleSize。 – goRGon 2014-04-19 00:22:25

4

简言之,良好缩小算法(未近邻等)由2个步骤:

  1. 缩减使用BitmapFactory.Options :: inSampleSize-> BitmapFactory。decodeResource()尽可能接近到你所需要的分辨率,但不低于其
  2. 得到精确的分辨率,通过缩减使用帆布:: drawBitmap()有点

下面是详细的解释SonyMobile如何解决这个任务:http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/

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