web-dev-qa-db-ja.com

Android:高品質の画像のサイズ変更/スケーリング

品質を失うことなく、ネットワークストリームからの画像を縮小する必要があります。

私はこの解決策を知っています 画像をBitmapオブジェクトにロードする際の奇妙なメモリ不足の問題 しかし、それは粗すぎる-inSampleSizeは整数であり、結果の詳細な制御を許可しません寸法。つまり、画像を特定のh/w寸法にスケーリングする(そしてアスペクト比を維持する)必要があります。

私のコードにDIYバイキュービック/ランコズアルゴリズムが含まれていてもかまいませんが、Android)で動作する例は見つかりません。すべてJava2D(JavaSE)に依存しています。

編集:私はクイックソースを添付しました。オリジナルは720x402 HDスクリーンキャプチャです。上位2つのサムネイルは無視してください。上の大きな画像は、Android(レイアウトの一部として)によって約130x72に自動的にサイズ変更されます。これは見栄えがよく鮮明です。下の画像はAPIでサイズ変更され、アーティファクトが大きくなります

alt text

私はまた、BitmapFactoryを使用してみましたが、前述したように、2つの問題があります。正確なサイズにスケーリングする方法がなく、スケーリングされたイメージがぼやけています。

アーティファクトを修正する方法に関するアイデアはありますか?

ありがとう、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>
27
Saideira

BitmapFactory.OptionsBitmapFactory.decode関数と共に使用できます。
inDensityおよびinTargetDensityを使用

例:1600x12画像のサイズがあり、サイズを640x48に変更したい場合
次に'inDensity'=5および'inTargetDensity'=2(1600x2は640x5に等しい)。

この助けを願っています。

9
Anonymous

一番上の大きな画像は、レイアウトによって単純に450pxに縮小されるため、アーチファクトはありません。

下の大きな画像のアーティファクトは、レイアウトによって幅を130pxに縮小し、その後再び約450pxに拡大した結果です。したがって、アーティファクトはスケーリングによって作成されます。試す

Bitmap resized = getResizedBitmap(original, 450);

あなたのコードでそれはうまくいくはずです。ただし、電話の実際の画面幅に合わせて調整する必要があります。

8
dronus

簡単に言うと、適切なダウンスケーリングアルゴリズム(最近傍ではない)は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/

4
goRGon