Bitmap的缩放基本操作

Matrix提供了一些方法来控制图片变换:
setTranslate(float dx,float dy):控制Matrix进行位移。
setSkew(float kx,float ky):控制Matrix进行倾斜,kx、ky为X、Y方向上的比例。
setSkew(float kx,float ky,float px,float py):控制Matrix以px、py为轴心进行倾斜,kx、ky为X、Y方向上的倾斜比例。
setRotate(float degrees):控制Matrix进行depress角度的旋转,轴心为(0,0)。
setRotate(float degrees,float px,float py):控制Matrix进行depress角度的旋转,轴心为(px,py)。
setScale(float sx,float sy):设置Matrix进行缩放,sx、sy为X、Y方向上的缩放比例。
setScale(float sx,float sy,float px,float py):设置Matrix以(px,py)为轴心进行缩放,sx、sy为X、Y方向上的缩放比例。
注意:以上的set方法,均有对应的post和pre方法,Matrix调用一系列set,pre,post方法时,可视为将这些方法插入到一个队列.当然,按照队列中从头至尾的顺序调用执行.其中pre表示在队头插入一个方法,post表示在队尾插入一个方法.而set表示把当前队列清空,并且总是位于队列的最中间位置.当执行了一次set后:pre方法总是插入到set前部的队列的最前面,post方法总是插入到set后部的队列的最后面

Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);// 缩小为原来的一半
matrix.postRotate(45.0f);// 旋转45度 == matrix.setSinCos(0.5f, 0.5f);
Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
iv2.setImageBitmap(bm);

在Android开发中,经常会遇到图片的操作问题,由于Android屏幕尺寸繁多,最经常的是图片的缩放问题。下面为一段Android操作的基本代码

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.net.Uri;
import android.util.Log;
public class Bitmaptest
{
 private static final String TAG = "BitmapUtil";
 /**
  * 通过资源id转化成Bitmap
  *
  * @param context
  * @param resId
  * @return
  */
 public static Bitmap ReadBitmapById(Context context, int resId)
 {
  BitmapFactory.Options opt = new BitmapFactory.Options();
  opt.inPreferredConfig = Bitmap.Config.RGB_565;
  opt.inPurgeable = true;
  opt.inInputShareable = true;
  InputStream is = context.getResources().openRawResource(resId);
  return BitmapFactory.decodeStream(is, null, opt);
 }
 /**
  * 缩放Bitmap满屏
  *
  * @param bitmap
  * @param screenWidth
  * @param screenHight
  * @return
  */
 public static Bitmap getBitmap(Bitmap bitmap, int screenWidth,
   int screenHight)
 {
  int w = bitmap.getWidth();
  int h = bitmap.getHeight();
  Matrix matrix = new Matrix();
  float scale = (float) screenWidth / w;
  float scale2 = (float) screenHight / h;
  // scale = scale < scale2 ? scale : scale2;
  matrix.postScale(scale, scale);
  Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
  if (bitmap != null && !bitmap.equals(bmp) && !bitmap.isRecycled())
  {
   bitmap.recycle();
   bitmap = null;
  }
  return bmp;// Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
 }
 
 /**
  * 按最大边按一定大小缩放图片
  * */
 public static Bitmap scaleImage(byte[] buffer, float size)
 {
  // 获取原图宽度
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  options.inPurgeable = true;
  options.inInputShareable = true;
  Bitmap bm = BitmapFactory.decodeByteArray(buffer, 0, buffer.length,
    options);
  // 计算缩放比例
  float reSize = options.outWidth / size;
  if (options.outWidth < options.outHeight)
  {
   reSize = options.outHeight / size;
  }
  // 如果是小图则放大
  if (reSize <= 1)
  {
   int newWidth = 0;
   int newHeight = 0;
   if (options.outWidth > options.outHeight)
   {
    newWidth = (int) size;
    newHeight = options.outHeight * (int) size / options.outWidth;
   } else
   {
    newHeight = (int) size;
    newWidth = options.outWidth * (int) size / options.outHeight;
   }
   bm = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
   bm = scaleImage(bm, newWidth, newHeight);
   if (bm == null)
   {
    Log.e(TAG, "convertToThumb, decode fail:" + null);
    return null;
   }
   return bm;
  }
  // 缩放
  options.inJustDecodeBounds = false;
  options.inSampleSize = (int) reSize;
  bm = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options);
  if (bm == null)
  {
   Log.e(TAG, "convertToThumb, decode fail:" + null);
   return null;
  }
  return bm;
 }
 /**
  * 检查图片是否超过一定值,是则缩小
  *
  * @param view
  * @param strFileName
  */
 public static Bitmap convertToThumb(byte[] buffer, float size)
 {
  // 获取原图宽度
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  options.inPurgeable = true;
  options.inInputShareable = true;
  Bitmap bm = BitmapFactory.decodeByteArray(buffer, 0, buffer.length,
    options);
  // 计算缩放比例
  float reSize = options.outWidth / size;
  if (options.outWidth > options.outHeight)
  {
   reSize = options.outHeight / size;
  }
  if (reSize <= 0)
  {
   reSize = 1;
  }
  Log.d(TAG, "convertToThumb, reSize:" + reSize);
  // 缩放
  options.inJustDecodeBounds = false;
  options.inSampleSize = (int) reSize;
  if (bm != null && !bm.isRecycled())
  {
   bm.recycle();
   bm = null;
   Log.e(TAG, "convertToThumb, recyle");
  }
  bm = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, options);
  if (bm == null)
  {
   Log.e(TAG, "convertToThumb, decode fail:" + null);
   return null;
  }
  return bm;
 }
 /**
  * Bitmap --> byte[]
  *
  * @param bmp
  * @return
  */
 private static byte[] readBitmap(Bitmap bmp)
 {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  bmp.compress(Bitmap.CompressFormat.JPEG, 60, baos);
  try
  {
   baos.flush();
   baos.close();
  } catch (IOException e)
  {
   e.printStackTrace();
  }
  return baos.toByteArray();
 }
 /**
  * Bitmap --> byte[]
  *
  * @param bmp
  * @return
  */
 public static byte[] readBitmapFromBuffer(byte[] buffer, float size)
 {
  return readBitmap(convertToThumb(buffer, size));
 }
 /**
  * 以屏幕宽度为基准,显示图片
  *
  * @param iv
  * @param path
  * @param screenW
  * @return
  */
 public static Bitmap decodeStream(Context context, Intent data, float size)
 {
  Bitmap image = null;
  try
  {
   Uri dataUri = data.getData();
   // 获取原图宽度
   BitmapFactory.Options options = new BitmapFactory.Options();
   options.inJustDecodeBounds = true;
   options.inPurgeable = true;
   options.inInputShareable = true;
   BitmapFactory.decodeStream(context.getContentResolver()
     .openInputStream(dataUri), null, options);
   // 计算缩放比例
   float reSize = (int) (options.outWidth / size);
   if (reSize <= 0)
   {
    reSize = 1;
   }
   Log.d(TAG, "old-w:" + options.outWidth + ", llyt-w:" + size
     + ", resize:" + reSize);
   // 缩放
   options.inJustDecodeBounds = false;
   options.inSampleSize = (int) reSize;
   image = BitmapFactory.decodeStream(context.getContentResolver()
     .openInputStream(dataUri), null, options);
  } catch (Exception e)
  {
   e.printStackTrace();
  }
  return image;
 }
 
 /**
  * 按新的宽高缩放图片
  *
  * @param bm
  * @param newWidth
  * @param newHeight
  * @return
  */
 public static Bitmap scaleImage(Bitmap bm, int newWidth, int newHeight)
 {
  if (bm == null)
  {
   return null;
  }
  int width = bm.getWidth();
  int height = bm.getHeight();
  float scaleWidth = ((float) newWidth) / width;
  float scaleHeight = ((float) newHeight) / height;
  Matrix matrix = new Matrix();
  matrix.postScale(scaleWidth, scaleHeight);
  Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
    true);
  if (bm != null & !bm.isRecycled())
  {
   bm.recycle();
   bm = null;
  }
  return newbm;
 }
 /**
  * fuction: 设置固定的宽度,高度随之变化,使图片不会变形
  *
  * @param target
  * 需要转化bitmap参数
  * @param newWidth
  * 设置新的宽度
  * @return
  */
 public static Bitmap fitBitmap(Bitmap target, int newWidth)
 {
  int width = target.getWidth();
  int height = target.getHeight();
  Matrix matrix = new Matrix();
  float scaleWidth = ((float) newWidth) / width;
  // float scaleHeight = ((float)newHeight) / height;
  int newHeight = (int) (scaleWidth * height);
  matrix.postScale(scaleWidth, scaleWidth);
  // Bitmap result = Bitmap.createBitmap(target,0,0,width,height,
  // matrix,true);
  Bitmap bmp = Bitmap.createBitmap(target, 0, 0, width, height, matrix,
    true);
  if (target != null && !target.equals(bmp) && !target.isRecycled())
  {
   target.recycle();
   target = null;
  }
  return bmp;// Bitmap.createBitmap(target, 0, 0, width, height, matrix,
     // true);
 }
 
 /**
  * 根据指定的宽度平铺图像
  *
  * @param width
  * @param src
  * @return
  */
 public static Bitmap createRepeater(int width, Bitmap src)
 {
  int count = (width + src.getWidth() - 1) / src.getWidth();
  Bitmap bitmap = Bitmap.createBitmap(width, src.getHeight(),
    Config.ARGB_8888);
  Canvas canvas = new Canvas(bitmap);
  for (int idx = 0; idx < count; ++idx)
  {
   canvas.drawBitmap(src, idx * src.getWidth(), 0, null);
  }
  return bitmap;
 }
 
 /**
  * 图片的质量压缩方法
  *
  * @param image
  * @return
  */
 public static Bitmap compressImage(Bitmap image)
 {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
  int options = 100;
  while (baos.toByteArray().length / 1024 > 100)
  { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
   baos.reset();// 重置baos即清空baos
   image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
   options -= 10;// 每次都减少10
  }
  ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
  Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
  if (baos != null)
  {
   try
   {
    baos.close();
   } catch (IOException e)
   {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  if (isBm != null)
  {
   try
   {
    isBm.close();
   } catch (IOException e)
   {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  if (image != null && !image.isRecycled())
  {
   image.recycle();
   image = null;
  }
  return bitmap;
 }
 
 /**
  * 图片按比例大小压缩方法(根据Bitmap图片压缩)
  *
  * @param image
  * @return
  */
 public static Bitmap getImage(Bitmap image)
 {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
  if (baos.toByteArray().length / 1024 > 1024)
  {// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
   baos.reset();// 重置baos即清空baos
   image.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中
  }
  ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
  BitmapFactory.Options newOpts = new BitmapFactory.Options();
  // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
  newOpts.inJustDecodeBounds = true;
  Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
  newOpts.inJustDecodeBounds = false;
  int w = newOpts.outWidth;
  int h = newOpts.outHeight;
  // 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
  float hh = 800f;// 这里设置高度为800f
  float ww = 480f;// 这里设置宽度为480f
  // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
  int be = 1;// be=1表示不缩放
  if (w > h && w > ww)
  {// 如果宽度大的话根据宽度固定大小缩放
   be = (int) (newOpts.outWidth / ww);
  } else if (w < h && h > hh)
  {// 如果高度高的话根据宽度固定大小缩放
   be = (int) (newOpts.outHeight / hh);
  }
  if (be <= 0)
   be = 1;
  newOpts.inSampleSize = be;// 设置缩放比例
  // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
  isBm = new ByteArrayInputStream(baos.toByteArray());
  bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
  if (isBm != null)
  {
   try
   {
    isBm.close();
   } catch (IOException e)
   {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  if (image != null && !image.isRecycled())
  {
   image.recycle();
   image = null;
  }
  return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
 }
 /**
  * 通过资源id转化成Bitmap 全屏显示
  *
  * @param context
  * @param drawableId
  * @param screenWidth
  * @param screenHight
  * @return
  */
 public static Bitmap ReadBitmapById(Context context, int drawableId,
   int screenWidth, int screenHight)
 {
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inPreferredConfig = Config.ARGB_8888;
  options.inInputShareable = true;
  options.inPurgeable = true;
  InputStream stream = context.getResources().openRawResource(drawableId);
  Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
  return getBitmap(bitmap, screenWidth, screenHight);
 }
 
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容