Android: высококачественное изменение размера / масштабирования изображения - PullRequest
27 голосов
/ 17 ноября 2010

Мне нужно уменьшить изображение, поступающее из сетевого потока, без потери качества.

Мне известно об этом решении Странно нехватка памяти при загрузке изображения в объект Bitmap , нооно слишком грубое - inSampleSize является целым числом и не позволяет более точно контролировать результирующие размеры.То есть мне нужно масштабировать изображения до конкретных ч / б размеров (и сохраняя соотношение сторон).

Я не против иметь в своем коде алгоритм DIY Bicubic / Lancoz, но я не могу найти какие-либо примеры, которые могли бы работатьAndroid, так как все они используют Java2D (JavaSE).

РЕДАКТИРОВАТЬ: Я подключил быстрый источник.Оригинальный снимок экрана 720x402 HD.Пожалуйста, игнорируйте 2 верхних эскиза.Размер верхнего большого изображения автоматически изменяется с помощью Android (как часть макета) до 130x72.Это красиво и свежо.Размер нижнего изображения изменен с помощью API и имеет серьезные артефакты

alt text

Я также пытался использовать 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);
    }

}

И макет

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

Ответы [ 3 ]

9 голосов
/ 30 августа 2011

Вы можете использовать BitmapFactory.Options с BitmapFactory.decode функциями,
используя inDensity и inTargetDensity

Пример: у вас 1600x1200 размер изображения и вы хотите изменить размер до 640x480
затем 'inDensity'=5 и 'inTargetDensity'=2 (1600x2, равный 640x5).

Надеясь на помощь.

8 голосов
/ 25 апреля 2011

Верхнее большое изображение просто уменьшено до 450px по макету, поэтому никаких артефактов.

Артефакты нижнего большого изображения являются результатом его уменьшения до 130 пикселей в ширину, а затем снова до 450 пикселей в соответствии с макетом. Таким образом, артефакты сделаны вашим масштабированием. Попробуйте

Bitmap resized = getResizedBitmap(original, 450);

в вашем коде, и это должно быть хорошо. Тем не менее, вам также необходимо адаптировать его к ширине экрана телефона.

4 голосов
/ 21 апреля 2014

Вкратце, хороший алгоритм уменьшения масштаба (не похожий на ближайшего соседа) состоит из 2 шагов:

  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: http://developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...