画像をきれいに縮小する方法

5,330 views
Skip to first unread message

たろサ

unread,
Jan 5, 2011, 9:22:10 AM1/5/11
to android-g...@googlegroups.com
 たろサです。

 画像をきれいに縮小する方法を教えてください。

 子供が描いたメロンの絵(250×250)を52×52に縮小したいのですが、下記のプロ
グラムを用いると、添付画像のdevice.pngにあるように(左上の絵)、汚い画像に
しかなりません。

 melon2.png程度の原型をとどめている絵にしたいのですが、どのようにすれば
いいのでしょうか。自力でLanczosなどのアルゴリズムを実装するしか方法はな
いのでしょうか。

 よろしくお願いします。

String toFile = "/sdcard/luarida/melon.png";
Bitmap bmp = BitmapFactory.decodeFile( toFile );
Bitmap workBmp = Bitmap.createBitmap( 300, 300, Bitmap.Config.ARGB_8888);
Canvas workcanvas = new Canvas( workBmp );
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
int w = bmp.getWidth();
int h = bmp.getHeight();
workcanvas.drawBitmap(bmp, new Rect(0, 0, w, h), new Rect(0, 0, 52, 52),
paint);
workcanvas.drawBitmap(bmp, new Rect(0, 0, w, h), new Rect(0, 60, 250,
310), paint);


--
山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----
E-Mail: taro...@gmail.com


device.png
melon2.png

kenz

unread,
Jan 5, 2011, 10:56:10 AM1/5/11
to 日本Androidの会
可愛い画像ですね
この画像をなんとしても綺麗に表示したいです。
Matrixを使ってみてはどうでしょう。
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
String toFile = "/sdcard/luarida/melon.png";
Bitmap src = BitmapFactory.decodeFile( toFile );
int width = src.getWidth();
int height = src.getHeight();
Matrix matrix = new Matrix();
float reSize = 0.5f;
matrix.postScale(reSize, reSize);
Bitmap bmp = Bitmap.createBitmap(src,
0,0,width,height,matrix,true);//最後をTrueにするのがミソ
ImageView imgView = new ImageView(this);
imgView.setImageBitmap(bmp);
ll.addView(imgView);
setContentView(ll);
> E-Mail: taros...@gmail.com
>
> device.png
> 12K表示ダウンロード
>
> melon2.png
> 2K表示ダウンロード

たろサ

unread,
Jan 5, 2011, 11:13:44 AM1/5/11
to android-g...@googlegroups.com
 たろサです。
 kenzさん、お返事ありがとうございます。

 メールを書いてから、いろいろと試していました。下記のソースのように、
matrix.postScale()を使う方法や、BitmapDrawableでsetAntiAliasを使う方法です。
 いずれの場合も、同じような画像しか得られませんでした。結果画像を添付し
ます。プログラムにおかしなところがあるのでしょうか。
 
String refFile = "/sdcard/luarida/melon2.png";
String toFile = "/sdcard/luarida/melon.png";
Bitmap refbmp = BitmapFactory.decodeFile( refFile );


Bitmap bmp = BitmapFactory.decodeFile( toFile );
Bitmap workBmp = Bitmap.createBitmap( 300, 300, Bitmap.Config.ARGB_8888);
Canvas workcanvas = new Canvas( workBmp );

Matrix matrix = new Matrix();
float rx = 52f/250f;
float ry = 52f/250f;
matrix.postScale( rx, ry );
Bitmap scaledBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
bmp.getHeight(), matrix,true);

BitmapDrawable bmd = new BitmapDrawable(bmp);

bmd.setAntiAlias(true);
bmd.setBounds(0,0,52,52);
//BitmapDrawableのアンチエイリアス有り
bmd.draw(workcanvas);

bmd.setAntiAlias(false);
bmd.setBounds(52,0,104,52);
//BitmapDrawableのアンチエイリアス無し
bmd.draw(workcanvas);

int a = scaledBitmap.getWidth();
int b = scaledBitmap.getHeight();


int w = bmp.getWidth();
int h = bmp.getHeight();

//matrix.postScaleを使って縮小
workcanvas.drawBitmap(scaledBitmap, new Rect(0, 0, a, b), new Rect(104,
0, 156, 52), null);
//ただの縮小
workcanvas.drawBitmap(bmp, new Rect(0, 0, w, h), new Rect(156, 0, 208,
52), null);
//参照
workcanvas.drawBitmap(refbmp, new Rect(0, 0, 52, 52), new Rect(208, 0,
208+52, 52 ), null);

//原寸大
workcanvas.drawBitmap(bmp, new Rect(0, 0, w, h), new Rect(0, 60, w,
60+h), null);

E-Mail: taro...@gmail.com

device.png

Hiroshi Matsunaga

unread,
Jan 5, 2011, 11:48:42 AM1/5/11
to android-g...@googlegroups.com
たろサさん

松永と申します。

スレの流れと完全に違う方法ですが、
最近私も画像の縮小やトリミングを試していたので、
参考になればと思い。返信させていただきます。

私はWebViewで画像を読み込んで、
縮小等はHTMLやCSSで記述してみました。

にメモを取ってあるのとサンプルソースのリンクがあるので、
参考にしていただければと思います。
<img src=\""+image_uri+"\" width=\"210\" height=\"210\"/>
としている部分のwidthとheightを変更していただければ、それなりに縮小できると思います。

以上です。

2011年1月6日1:13 たろサ <taro...@gmail.com>:

--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。




--
Hiroshi Matsunaga
email: hiroshi.82...@gmail.com

たろサ

unread,
Jan 5, 2011, 12:38:17 PM1/5/11
to android-g...@googlegroups.com
 たろサです。

 松永さん、こんにちは。

> 私はWebViewで画像を読み込んで、
> 縮小等はHTMLやCSSで記述してみました。

 こういうやり方もあるのですね。参考になります。ネット接続が必須になりま
すね。私の場合、wifi経由しか使っていないので、半常時接続状態なので、難し
いところです。

 さっきのメール後、自力で、Lanczos処理を実装してみました。
 処理が遅い割りには、結果がいまいちで、参ったなぁ・・・。という感じで
す。添付画像の右から2つ目です。

 もう少し、悩んで見て、だめならあきらめます。

private Bitmap Lanczos(Bitmap bmp, float sc) {
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[width * height];
bmp.getPixels(pixels, 0, width, 0, 0, width, height);

int w = (int)((float)width*sc);
int h = (int)((float)height*sc);
int[] retpixels = new int[w * h];
int n = 3; // N値
int nx = n-1;

for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
double x0 = (float)x/sc;
double y0 = (float)y/sc;

int xBase = (int)x0;
int yBase = (int)y0;

int color = 0;

// ランツォシュの処理範囲
if (xBase >= nx && xBase < width - n && yBase >= nx && yBase < height
- n) {
double[] color_element = new double[3];
color_element[0] = 0.0;
color_element[1] = 0.0;
color_element[2] = 0.0;
double w_total = 0.0;

// 周辺(a*2)^2画素を取得して処理
for (int i = -nx; i <= n; i++) {
for (int j = -nx; j <= n; j++) {
int xCurrent = xBase + i;
int yCurrent = yBase + j;

// 距離決定
double distX = Math.abs(xCurrent - x0);
double distY = Math.abs(yCurrent - y0);

// 重み付け
double weight = 0.0;

if (distX == 0.0) {
weight = 1.0;
} else if (distX < n) {
double dPIx = Math.PI*distX;
weight = (Math.sin(dPIx)*Math.sin(dPIx/n))/(dPIx*(dPIx/n));
} else {
continue;
}
if (distY == 0.0) {
;
} else if (distY < n) {
double dPIy = Math.PI*distY;
weight *= (Math.sin(dPIy)*Math.sin(dPIy/n))/(dPIy*(dPIy/n));
} else {
continue;
}

// 画素取得
int color_process = pixels[xCurrent+yCurrent*width];
for (int k = 0; k < 3; k++) {
color_element[k] += ((color_process >> k*8) & 0xff)*weight;
}

w_total += weight;
}
}
for (int i = 0; i < 3; i++) {
if (w_total != 0) color_element[i] /= w_total;
color_element[i] = (color_element[i] > 255) ? 255:
(color_element[i] < 0) ? 0: color_element[i];
color += (int)color_element[i] << i*8;
}
}
retpixels[x+y*w] = 0xff000000 + color;
}
}

Bitmap newbmp = Bitmap.createBitmap( w, h, Bitmap.Config.ARGB_8888);
newbmp.setPixels(retpixels, 0, w, 0, 0, w, h);
return newbmp;
}


(2011/01/06 1:48), Hiroshi Matsunaga wrote:
> たろサさん
>
> 松永と申します。
>
> スレの流れと完全に違う方法ですが、
> 最近私も画像の縮小やトリミングを試していたので、
> 参考になればと思い。返信させていただきます。
>
> 私はWebViewで画像を読み込んで、
> 縮小等はHTMLやCSSで記述してみました。
>
> http://matsuhilog.blogspot.com/2011/01/webview.html

> <http://matsuhilog.blogspot.com/2011/01/webview.html>にメモを取ってある

> のとサンプルソースのリンクがあるので、
> 参考にしていただければと思います。
>
> <img src=\""+image_uri+"\" width=\"210\" height=\"210\"/>
>
> としている部分のwidthとheightを変更していただければ、それなりに縮小できると思います。
>
>
> 以上です。
>

> 2011年1月6日1:13 たろサ <taro...@gmail.com <mailto:taro...@gmail.com>>:

> >> E-Mail: taros...@gmail.com <mailto:taros...@gmail.com>


> >>
> >> device.png
> >> 12K表示ダウンロード
> >>
> >> melon2.png
> >> 2K表示ダウンロード
> >
>
> --
> 山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----

> E-Mail: taro...@gmail.com <mailto:taro...@gmail.com>


>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に
> 送られています。
> このグループに投稿するには、android-g...@googlegroups.com

> <mailto:android-g...@googlegroups.com> にメールを送信してくだ
> さい。
> このグループから退会するには、android-group-
> japan+un...@googlegroups.com
> <mailto:android-group-japan%2Bunsu...@googlegroups.com> にメール
> を送信してください。
> 詳細については、http://groups.google.com/group/android-group-


> japan?hl=ja からこのグループにアクセスしてください。
>
>
>
>
> --
> Hiroshi Matsunaga
> email: hiroshi.82...@gmail.com

> <mailto:hiroshi.82...@gmail.com>


>
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送ら
> れています。
> このグループに投稿するには、android-g...@googlegroups.com にメー
> ルを送信してください。
> このグループから退会するには、android-group-

> japan+un...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja
> からこのグループにアクセスしてください。

--

device.png

Hiroshi Matsunaga

unread,
Jan 5, 2011, 1:48:01 PM1/5/11
to android-g...@googlegroups.com

松永です。

失礼しました。
私が持っている実機はsimいれているので気がつかなかったです。
SDcardに保存してある画像も縮小できたので、お役に立てるかと思ったのですが、WebViewを利用する場合は、ネットワーク接続が必須だったのですね。。。
こちらこそ勉強になりました。

2011/01/06 2:38 "たろサ" <taro...@gmail.com>:

たろサ

unread,
Jan 5, 2011, 2:10:48 PM1/5/11
to android-g...@googlegroups.com
 たろサです。

 あれから、Bi-CubicとかBi-Linearとか、いろいろと実装して試していたので
すが、結局、考え方を変えました。

 下記のようなアルゴリズムで、matrix.postScale()を使って縮小するプログラ
ムにしてみました。

 これだと、高速で参照画像とほぼ同様の画像を得ることができました。

Matrix matrix = new Matrix();

float n = 4.0f;
float sc = (float)Math.exp(Math.log(52.0/250.0)/n);
matrix.postScale( sc, sc );


Bitmap scaledBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
bmp.getHeight(), matrix,true);

for( int i=0; i<(int)n-1; i++ ){
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,true);
}

 すいません、お騒がせしました。

 返信していただいた皆様、ありがとうございました。

> if (xBase>= nx&& xBase< width - n&& yBase>= nx&& yBase< height

> color_element[k] += ((color_process>> k*8)& 0xff)*weight;

device.png
Reply all
Reply to author
Forward
0 new messages