美文网首页Android
android图像绘制——画布保存为图片

android图像绘制——画布保存为图片

作者: 孙科技 | 来源:发表于2018-10-12 14:04 被阅读248次
Bitmap bmp = Bitmap.createBitmap(480, 800, Config.ARGB_8888); 
Canvas canvas = new Canvas(bmp); 
canvas.drawBitmap(this.bmp, matrix, paint); 
canvas.save(Canvas.ALL_SAVE_FLAG); 
canvas.restore(); 
 
File file = new File("/sdcard/akai/"); 
if(!file.exists()) 
file.mkdirs(); 
try { 
FileOutputStream fos = new FileOutputStream(file.getPath() + "/2.png"); 
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos); 
fos.close(); 
System.out.println("saveBmp is here"); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
Bitmap bmp = Bitmap.createBitmap(480, 800, Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
canvas.drawBitmap(this.bmp, matrix, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
   
File file = new File("/sdcard/akai/");
if(!file.exists())
 file.mkdirs();
 try {
  FileOutputStream fos = new FileOutputStream(file.getPath() + "/2.png");
  bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
  fos.close();
  System.out.println("saveBmp is here");
 } catch (Exception e) {
e.printStackTrace();
}

解释:

1、首先创建一个Bitmap图片,并指定大小;

2、在该图片上创建一个新的画布Canvas,然后在画布上绘制,并保存即可;

3、需要保存的目录File,注意如果写的目录如“/sdcard/akai/”如果不存在的话,要先创建(file.mkdirs()),否则FileOutputStream会报错No found;

4、需要添加权限:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

android中的画布(Canvas)

什么是画布呢 其实通过字面意思的理解就是用来绘画的地方,那么android里的画布是神马样子的呢?

在自定义画布中常用到下面3个类

Canvas

   Canvas提供了绘图方法,可以向底层的位图绘制基本图形。
   Canvas类封装了用作绘图表面的位图;它还提供了draw*方法来实现设计。
   Canvas():创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布。
   Canvas(Bitmapbitmap): 以bitmap对象创建一个画布,则将内容都绘制在bitmap上,因 此bitmap不得为null。
   drawARGB/ drawRGB / drawColor 使用单一的颜色填充画布。
   drawBitmap在画布上绘制一个位图。可以通过指定目标大小或者使用一个矩阵来改变目标位图的外观。
   drawBitmapMesh使用一个mesh(网)来绘制一个位图,它可以通过移动网中的点来操作  目标的外观。
   drawPaint使用指定的Paint填充整个Canvas
   drawPath绘制指定的Path。Path对象经常用来保存一个对象中基本图形的集合。
   drawPicture在指定的矩形中绘制一个Picture对象。
   drawPosText绘制指定了每一个字符的偏移量的文本字符串。
   drawRoundRect绘制一个圆角矩形。
   drawTextOnPath在一个指定的path上绘制文本。
   drawColor:设置Canvas的背景颜色。
   setBitmap:  设置具体画布。
   clipRect:设置显示区域,即设置裁剪区。
   isOpaque:检测是否支持透明。
   rotate:  旋转画布
   setViewport:  设置画布中显示窗口。
   skew:  设置偏移量。
   sava()保存画布当前的状态
   restore()操作之后取出之前保存过的状态

   还有很多这里就不列举了,详情请查看Android SDK

这些绘图方法中的每一个都需要指定一个Paint对象来渲染它

Paint

Paint也称为"刷子",Paint可以指定如何将基本图形绘制到位图上。

Paint类相当于一个笔刷和调色板。它可以选择如何使用上面描述的draw方法来渲染绘 制在画布上的基本图形。通过修改Paint对象,可以在绘图的时候控制颜色、样式、字体和特殊效果。最简单地,setColor可以让你选择一个Paint的颜色,而Paint对象的样式(使用setStyle控制)则可以决定是绘制绘图对象的轮廓(STROKE),还是只填充每一部 分(FILL),或者是两者都做(STROKE_AND_FILL)除了这些简单的控制之外,Paint类还支持透明度,另外,它也可以通过使用各种各样的阴影、过滤器和效果进行修改,从而提供由更丰富的、复杂的画笔和颜料组成的调色板。

从继承View类(或其子类)开始,并定义onDraw()回调方法。系统会调用该方法来完 成View对象自己的绘制请求。这也是通过Canvas对象来执行所有的图形绘制调用的地方,这个Canvas对象是由onDraw()回调方法传入的。

Android框架只在必要的时候才会调用onDraw()方法,每次请求应用程序准备完成图形 绘制任务时,必须通过调用invalidate()方法让该View对象失效。这表明可以在该View 对象上进行图形绘制处理了,然后Android系统会调用该View对象的onDraw()方(尽 管不保证该回调方法会立即被调用)。

在定制的View组件的onDraw()方法内部,使用给定的Canvas对象来完成所有的图形绘制处理(如Canvas.draw…()方法或把该Canvas对象作为参数传递给其他类的draw() 方法)。一旦onDraw()方法被执行完成,Android框架就会使用这个Canvas对象来绘制一个有系统处理的Bitmap对象。

下面是Paint一些常用方法:

  setAntiAlias:设置画笔的锯齿效果。
  setColor: 设置画笔颜色
  setARGB:  设置画笔的a,r,p,g值。
  setAlpha:  设置Alpha值
  setTextSize: 设置字体尺寸。
  setStyle:  设置画笔风格,空心或者实心。
  setStrokeWidth: 设置空心的边框宽度。
  getColor:  得到画笔的颜色
  getAlpha:  得到画笔的Alpha值。
  还有很多这里就不列举了,详情请查看Android SDK

Bitmap

Bitmap绘图的表面也称位图(这里详细说哈位图的功能)。

从资源中获取位图:

通过Resource的函数:InputStream openRawResource(int id)获取得到资源文件的数据流后,可以通过2种方式获得bitmap

使用BitmapDrawable :

使用BitmapDrawable(InputStream is)构造一个BitmapDrawable;

使用BitmapDrawable类的getBitmap()获取得到位图;

使用BitmapFactory使用BitmapFactory类decodeStream(InputStream is)解码位 图资源,获取位图BitmapFactory的所有函数都是static,这个辅助类可以通过资 源ID、路径、文件、数据流等方式来获取位图。

获取位图的信息

一般获取位图信息包括:位图大小、透明度、颜色格式等等,这些信息呢可以通过 三-一方法获取得到Bitmap就迎刃而解了,Android SDK中对Bitmap有详细说明,大家可以去详细了解哈。

显示位图

显示位图需要使用核心类Canvas,可以直接通过Canvas类的drawBirmap()显示位图,或者借助于BitmapDrawable来将Bitmap绘制到Canvas,下面的实例中会详细列举到

位图的缩放

位图的缩放,在Android SDK中提供了2种方法:

1:将一个位图按照需求重画一遍,画后的位图就是我们需要的了,与位图的显示几乎 一样:
drawBitmap(Bitmap bitmap, Rect src, Rectdst, Paint paint)

2:在原有位图的基础上,缩放原位图,创建一个新的位图:
createBitmap(Bitmap source, int x, int y,int width, int height, Matrix m, boolean filter)

位图旋转

位图的旋转,离不开Matrix。Android SDK提供了Matrix类,可以通过各种接口来设置 矩阵

android 处理图片工具

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

/**
 * 处理图片的工具类.
 */
public class imageTool {
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int TOP = 3;
public static final int BOTTOM = 4;

/** */
/**
 * 图片去色,返回灰度图片
 * 
 * @param bmpOriginal
 *传入的图片
 * @return 去色后的图片
 */
public static Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height,
Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}

/** */
/**
 * 去色同时加圆角
 * 
 * @param bmpOriginal
 *原图
 * @param pixels
 *圆角弧度
 * @return 修改后的图片
 */
public static Bitmap toGrayscale(Bitmap bmpOriginal, int pixels) {
return toRoundCorner(toGrayscale(bmpOriginal), pixels);
}

/** */
/**
 * 把图片变成圆角
 * 
 * @param bitmap
 *需要修改的图片
 * @param pixels
 *圆角的弧度
 * @return 圆角图片
 */
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}

/** */
/**
 * 使圆角功能支持BitampDrawable
 * 
 * @param bitmapDrawable
 * @param pixels
 * @return
 */
public static BitmapDrawable toRoundCorner(BitmapDrawable bitmapDrawable,
int pixels) {
Bitmap bitmap = bitmapDrawable.getBitmap();
bitmapDrawable = new BitmapDrawable(toRoundCorner(bitmap, pixels));
return bitmapDrawable;
}

/**
 * 读取路径中的图片,然后将其转化为缩放后的bitmap
 * 
 * @param path
 */
public static void saveBefore(String path) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// 获取这个图片的宽和高
Bitmap bitmap = BitmapFactory.decodeFile(path, options); // 此时返回bm为空
options.inJustDecodeBounds = false;
// 计算缩放比
int be = (int) (options.outHeight / (float) 200);
if (be <= 0)
be = 1;
options.inSampleSize = 2; // 图片长宽各缩小二分之一
// 重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦
bitmap = BitmapFactory.decodeFile(path, options);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
System.out.println(w + " " + h);
// savePNG_After(bitmap,path);
saveJPGE_After(bitmap, path);
}

/**
 * 保存图片为PNG
 * 
 * @param bitmap
 * @param name
 */
public static void savePNG_After(Bitmap bitmap, String name) {
File file = new File(name);
try {
FileOutputStream out = new FileOutputStream(file);
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)) {
out.flush();
out.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
 * 保存图片为JPEG
 * 
 * @param bitmap
 * @param path
 */
public static void saveJPGE_After(Bitmap bitmap, String path) {
File file = new File(path);
try {
FileOutputStream out = new FileOutputStream(file);
if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
out.flush();
out.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
 * 水印
 * 
 * @param bitmap
 * @return
 */
public static Bitmap createBitmapForWatermark(Bitmap src, Bitmap watermark) {
if (src == null) {
return null;
}
int w = src.getWidth();
int h = src.getHeight();
int ww = watermark.getWidth();
int wh = watermark.getHeight();
// create the new blank bitmap
Bitmap newb = Bitmap.createBitmap(w, h, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
Canvas cv = new Canvas(newb);
// draw src into
cv.drawBitmap(src, 0, 0, null);// 在 0,0坐标开始画入src
// draw watermark into
cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印
// save all clip
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
// store
cv.restore();// 存储
return newb;
}

/**
 * 图片合成
 * 
 * @return
 */
public static Bitmap potoMix(int direction, Bitmap... bitmaps) {
if (bitmaps.length <= 0) {
return null;
}
if (bitmaps.length == 1) {
return bitmaps[0];
}
Bitmap newBitmap = bitmaps[0];
// newBitmap = createBitmapForFotoMix(bitmaps[0],bitmaps[1],direction);
for (int i = 1; i < bitmaps.length; i++) {
newBitmap = createBitmapForFotoMix(newBitmap, bitmaps[i], direction);
}
return newBitmap;
}

private static Bitmap createBitmapForFotoMix(Bitmap first, Bitmap second,
int direction) {
if (first == null) {
return null;
}
if (second == null) {
return first;
}
int fw = first.getWidth();
int fh = first.getHeight();
int sw = second.getWidth();
int sh = second.getHeight();
Bitmap newBitmap = null;
if (direction == LEFT) {
newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh,
Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(first, sw, 0, null);
canvas.drawBitmap(second, 0, 0, null);
} else if (direction == RIGHT) {
newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh,
Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(first, 0, 0, null);
canvas.drawBitmap(second, fw, 0, null);
} else if (direction == TOP) {
newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh,
Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(first, 0, sh, null);
canvas.drawBitmap(second, 0, 0, null);
} else if (direction == BOTTOM) {
newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh,
Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(first, 0, 0, null);
canvas.drawBitmap(second, 0, fh, null);
}
return newBitmap;
}

/**
 * 将Bitmap转换成指定大小
 * 
 * @param bitmap
 * @param width
 * @param height
 * @return
 */
public static Bitmap createBitmapBySize(Bitmap bitmap, int width, int height) {
return Bitmap.createScaledBitmap(bitmap, width, height, true);
}

/**
 * Drawable 转 Bitmap
 * 
 * @param drawable
 * @return
 */
public static Bitmap drawableToBitmapByBD(Drawable drawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
return bitmapDrawable.getBitmap();
}

/**
 * Bitmap 转 Drawable
 * 
 * @param bitmap
 * @return
 */
public static Drawable bitmapToDrawableByBD(Bitmap bitmap) {
Drawable drawable = new BitmapDrawable(bitmap);
return drawable;
}

/**
 * byte[] 转 bitmap
 * 
 * @param b
 * @return
 */
public static Bitmap bytesToBimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}

/**
 * bitmap 转 byte[]
 * 
 * @param bm
 * @return
 */
public static byte[] bitmapToBytes(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
}

截取视频帧并转化为Bitmap

/**
 * Demo描述:
 * 利用MediaMetadataRetriever按照时间截取视频
 * 并转换为Bitmap存放于SDCard
 * 
 * 特别注意:
 * getFrameAtTime()方法第一个参数的单位是微秒 (us)
 * 
 */
public void getBitmapsFromVideo() {
        String dataPath = Environment.getExternalStorageDirectory()+ "/testVideo.mp4";
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(dataPath);
        // 取得视频的长度(单位为毫秒)
        String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        // 取得视频的长度(单位为秒)
        int seconds = Integer.valueOf(time) / 1000;
        // 得到每一秒时刻的bitmap比如第一秒,第二秒
        for (int i = 1; i <= seconds; i++) {
            Bitmap bitmap = retriever.getFrameAtTime(i*1000*1000,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
            String path = Environment.getExternalStorageDirectory()+ File.separator + i + ".jpg";
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(path);
                bitmap.compress(CompressFormat.JPEG, 80, fos);
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

相关文章

  • android图像绘制——画布保存为图片

    解释: 1、首先创建一个Bitmap图片,并指定大小; 2、在该图片上创建一个新的画布Canvas,然后在画布上绘...

  • 安卓截图笔记

    Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后...

  • Android截屏方案

    Android截屏 Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后...

  • QML Book 第七章 画布(Canvas)元素 2

    7.4 图片绘制 QML 画布支持来自多个来源的图像绘制。要在画布中使用图像,需要首先加载图像。我们将使用 Com...

  • Android开发截屏截图方法汇总(Activity、View、

    Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途...

  • Android截屏总结

    Android截屏的原理:获取具体需要截屏的区域的Bitmap,然后绘制在画布上,保存为图片后进行分享或者其它用途...

  • canvas drawImage方法

    dravImage方法是用来在画布上绘制图像,视频和画布的还可以用来绘制图像的部分内容,以及增加或者减少图片的尺寸...

  • 性能优化-图像的绘制CGContextRef

    图像的绘制通常是指用那些以 CG 开头的方法把图像绘制到画布中,然后从画布创建图片并显示这样一个过程。这个最常见的...

  • canvas绘制图片及帧动画

    1.绘制图片 1 基本绘制图片的方式 2 在画布上绘制图像,并规定图像的宽度和高度 如果指定宽高,最好成比例,不然...

  • Android 图像绘制之 Drawable

    Android 图像绘制系列文章Android图像绘制之BitmapAndroid 图像绘制之 DrawableA...

网友评论

    本文标题:android图像绘制——画布保存为图片

    本文链接:https://www.haomeiwen.com/subject/vrtgaftx.html