2010-11-17 41 views
27

Tôi cần phải giảm tỷ lệ hình ảnh đến từ luồng Mạng mà không làm giảm chất lượng.Android: thay đổi kích thước hình ảnh chất lượng cao/thu nhỏ

Tôi biết giải pháp này Strange out of memory issue while loading an image to a Bitmap object nhưng quá thô - inSampleSize là số nguyên và không cho phép kiểm soát tốt hơn các thứ nguyên kết quả. Tức là, tôi cần chia tỷ lệ hình ảnh thành các thứ nguyên h/w cụ thể (và giữ tỷ lệ khung hình).

Tôi không ngại có thuật toán bicubic/lancoz DIY trong mã của mình nhưng tôi không thể tìm thấy bất kỳ ví dụ nào có thể hoạt động trên Android vì tất cả đều dựa trên Java2D (JavaSE).

EDIT: Ive đã đính kèm nguồn nhanh. Bản gốc là chụp màn hình HD 720x402. Vui lòng bỏ qua 2 hình thu nhỏ hàng đầu. Hình ảnh lớn hàng đầu được thay đổi kích thước tự động bởi android (như một phần của bố cục) thành khoảng 130x72. Nó đẹp và sắc nét. Những hình ảnh dưới được thay đổi kích cỡ với API và có artifacting nghiêm trọng

alt text

Tôi cũng đã thử bằng cách sử dụng BitmapFactory và, như tôi đã nói ở trên, nó có hai vấn đề - có cách nào để mở rộng quy mô để chính xác kích thước và quy mô hình ảnh bị mờ.

Bất kỳ ý tưởng nào về cách khắc phục artifcating?

Xin cảm ơn, 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); 
    } 

} 

Và cách bố trí

<?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

i không nghĩ rằng hình ảnh trên thực sự rộng 130px. http://icons-search.com/img/fasticon/fast_emoticons_lnx.zip/fast_emoticons_lnx-Icons-128X128-smile_1.png-128x128.png rộng 128 px .... – Quamis

+0

xem [hướng dẫn này] (http://developer.android.com/training/displaying-bitmaps/index.html) về giải mã hình ảnh. –

+0

Xin chào! Đối mặt với cùng một vấn đề, bạn có tìm thấy giải pháp không? – Dehimb

Trả lời

8

Hình ảnh lớn đầu chỉ đơn giản là thu nhỏ lại để 450px bởi cách bố trí như vậy không có hiện vật.

Các tạo tác của kết quả hình ảnh lớn ở dưới cùng từ việc chia tỷ lệ rộng xuống còn 130px và sau đó lên lại khoảng 450px theo bố cục. Vì vậy, các hiện vật được thực hiện bởi quy mô của bạn. Hãy thử

Bitmap resized = getResizedBitmap(original, 450); 

trong mã của bạn và nó sẽ ổn. Tuy nhiên, bạn cũng cần phải điều chỉnh chiều rộng màn hình của điện thoại.

9

Bạn có thể sử dụng BitmapFactory.Options với BitmapFactory.decode function (s),
sử dụng inDensityinTargetDensity

Ví dụ: bạn có 1600x1200 kích thước của hình ảnh và muốn thay đổi kích thước để 640x480
sau đó 'inDensity'=5'inTargetDensity'=2 (1600x2 bằng 640x5).

Hy vọng trợ giúp này.

+0

Thật không may, điều này tạo ra downscaling hàng xóm gần nhất. Như tôi đã tìm ra, để giữ tỷ lệ giảm xuống bằng bicubic, chỉ inSampleSize mới được phép thay đổi. – goRGon

4

Tóm lại, thuật toán Downscaling tốt (hàng xóm không gần như) bao gồm 2 bước sau:

  1. downscale sử dụng BitmapFactory.Options :: inSampleSize-> BitmapFactory.decodeResource() càng gần càng tốt với độ phân giải mà bạn cần nhưng không thấp hơn nó
  2. có được độ phân giải chính xác bằng cách downscaling một chút bằng Canvas :: drawBitmap()

Dưới đây là giải thích chi tiết như thế nào SonyMobile giải quyết nhiệm vụ này: http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/

đây là mã nguồn của utils quy mô SonyMobile: http://developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/

Các vấn đề liên quan