Android 图片旋转,缩放,切割,叠加处理

时间:2023-02-04 16:22:54

Android中对图片处理应用比较常见,所以整理了一些对图片的基本操作处理功能方法:

/**
* 图片反转
* @param img
* @return
*/
public Bitmap toturn(Bitmap img){
Matrix matrix = new Matrix();
matrix.postRotate(90); /*翻转90度*/
int width = bitmap.getWidth();
int height =bitmap.getHeight();
img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);
return img;
}
/**
* 图片缩放
* @param bigimage
* @param newWidth
* @param newHeight
* @return
*/
public Bitmap tochange(Bitmap bigimage,int newWidth,int newHeight){
// 获取这个图片的宽和高
int width = bigimage.getWidth();
int height = bigimage.getHeight();
// 创建操作图片用的matrix对象
Matrix matrix = new Matrix();
// 计算缩放率,新尺寸除原始尺寸
float scaleWidth = ((float) newWidth)/width;
float scaleHeight = ((float) newHeight)/height;
// 缩放图片动作
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(bigimage, 0, 0, width, height,matrix, true);
return bitmap;
}

/**
* 程序切割图片
* @param bitmap
* @param x
* @param y
* @param w
* @param h
* @return
*/
public Bitmap BitmapClipBitmap(Bitmap bitmap,int x, int y, int w, int h) {
return Bitmap.createBitmap(bitmap, x, y, w, h);
}
/**     * 图片叠加     * @param b     * @return     */    public Bitmap diejia(Bitmap b){        if(!b.isMutable()){//设置图片为背景为透明b = b.copy(Bitmap.Config.RGB_565, true);//}Canvas canvas = new Canvas(b);Bitmap lock=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);//叠加新图b2//注意此时绘制坐标是相对于图片bcanvas.drawBitmap(lock, 0, 0, null);canvas.save(Canvas.ALL_SAVE_FLAG);canvas.restore();lock.recycle();lock=null;    return b;    }

图片居中叠加:

Bitmap centerToFit(Bitmap bitmap, int width, int height, Context context) {
final int bitmapWidth = bitmap.getWidth();
final int bitmapHeight = bitmap.getHeight();

if (bitmapWidth < width || bitmapHeight < height) {
int color = context.getResources().getColor(R.color.window_background);

Bitmap centered = Bitmap.createBitmap(bitmapWidth < width ? width : bitmapWidth,
bitmapHeight < height ? height : bitmapHeight, Bitmap.Config.RGB_565);
centered.setDensity(bitmap.getDensity());
Canvas canvas = new Canvas(centered);
canvas.drawColor(color);
canvas.drawBitmap(bitmap, (width - bitmapWidth) / 2.0f, (height - bitmapHeight) / 2.0f,
null);

bitmap = centered;
}

return bitmap;
}

对图像进行相关参数转换,重新形成新的图片数据参数展示形式(Drawble)

 /**
* Create a drawable from file path name.
*/
public Drawable createFromPath(String pathName) {
if (pathName == null) {
return null;
}

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;

opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, opts);

opts.inSampleSize = computeSampleSize(opts, -1, 1280 * 720);
opts.inJustDecodeBounds = false;

Bitmap bm = BitmapFactory.decodeFile(pathName, opts);

if (bm != null) {
return drawableFromBitmap(null, bm, null, null, pathName);
}

return null;
}

private Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
Rect pad, String srcName) {

if (np != null) {
return new NinePatchDrawable(res, bm, np, pad, srcName);
}

return new BitmapDrawable(res, bm);
}

public int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);

int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}

return roundedSize;
}

private int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;

int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength));

if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}

if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}


/** 
* create the bitmap from a byte array
*生成水印图片
* @param src the bitmap object you want proecss
* @param watermark the water mark above the src
* @return return a bitmap object ,if paramter's length is 0,return null
*/
private Bitmap createBitmap( Bitmap src, Bitmap watermark )
{
String tag = "createBitmap";
Log.d( tag, "create a new bitmap" );
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;
}

水印图片2:

public static Bitmap createWaterMakerBitmap(Bitmap bitmap, Bitmap watermaker){
return createWaterMakerBitmap(bitmap, watermaker, null);
}

public static Bitmap createWaterMakerBitmap(Bitmap bitmap, Bitmap watermaker, String title){
Context context = GOApplication.getInstance();
return createWaterMakerBitmap(bitmap, watermaker, title,
TypefaceHelper.get(context, context.getString(R.string.config_default_font)));
}

public static Bitmap createWaterMakerBitmap(Bitmap bitmap, Bitmap watermaker, String title, Typeface typeface){
if(!TextUtils.isEmpty(title)) {
return createWaterMakerBitmap(bitmap, watermaker, title, getDefaultPaint(), typeface);
}
return createWaterMakerBitmap(bitmap, watermaker, null, null, null);
}

public static Bitmap createWaterMakerBitmap(Bitmap bitmap, Bitmap watermaker, String title, Paint paint,Typeface typeface){
if(bitmap == null
|| (watermaker == null && TextUtils.isEmpty(title))) return bitmap;//nothing need todohere
int width = bitmap.getWidth();
int height = bitmap.getHeight();
if(width>0 && height>0) {
try {
Bitmap newBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(bitmap, 0, 0, null);//draw src
if(watermaker != null){
canvas.drawBitmap(watermaker, 0, 0, null);
}
if(!TextUtils.isEmpty(title)){
Paint mpaint = paint;
if(mpaint == null){
mpaint = getDefaultPaint();
}
if(typeface != null){
mpaint.setTypeface(typeface);
}
mpaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(title, width/3, height*3/4, mpaint);
}
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return newBitmap;
}catch (Throwable e){}
}
return null;
}

public static Paint getDefaultPaint(){
Paint paint = new Paint();
paint.setColor(Color.parseColor("#ffff6600"));// #141,141,141
paint.setTextSize(100);
paint.setAntiAlias(true);
paint.setStrokeWidth(10);
paint.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.SOLID));
return paint;
}



更多处理

/**圆角处理
* 实际上是在原图片上画了一个圆角遮罩。对于paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
* 方法我刚看到也是一知半解Mode.SRC_IN参数是个画图模式,该类型是指只显 示两层图案的交集部分,且交集部位只显示上层图像。
* 实际就是先画了一个圆角矩形的过滤框,于是形状有了,再将框中的内容填充为图片
* @param bitmap
* @param roundPx
* @return
*/
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap,float roundPx)
{

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);

paint.setAntiAlias(true);
canvas.drawARGB(0,0,0,0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

paint.setXfermode(new android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);

return output;
}
/**
* 灰白处理
就是利用了ColorMatrix 类自带的设置饱和度的方法setSaturation()。
不过其方法内部实现的更深一层是利用颜色矩阵的乘法实现的,对于颜色矩阵的乘法下面还有使用
* @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;
}

/**
* 黑白处理
这张图片不同于灰白处理的那张,不同之处是灰白处理虽然没有了颜色,
但是黑白的程度层次依然存在,而此张图片连层次都没有了,只有两个区别十分明显的黑白 颜色。
实现的算法也很简单,对于每个像素的rgb值求平均数,如果高于100算白色,低于100算黑色。
不过感觉100这个标准值太大了,导致图片白色区 域太多,把它降低点可能效果会更好
* @param mBitmap
* @return
*/
public static Bitmap toblackAndwhite(Bitmap mBitmap)
{
int mBitmapWidth =0;
int mBitmapHeight =0;

mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
Bitmap bmpReturn = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
Bitmap.Config.ARGB_8888);
int iPixel =0;
for(int i =0; i < mBitmapWidth; i++)
{
for(int j =0; j < mBitmapHeight; j++)
{
int curr_color = mBitmap.getPixel(i, j);

int avg = (Color.red(curr_color) + Color.green(curr_color) + Color
.blue(curr_color)) /3;
if(avg >=100)
{
iPixel =255;
}
else
{
iPixel =0;
}
int modif_color = Color.argb(255, iPixel, iPixel, iPixel);

bmpReturn.setPixel(i, j, modif_color);
}
}
return bmpReturn;
}
/**
* 镜像处理
* 原理就是将原图片反转一下,调整一 下它的颜色作出倒影效果,再将两张图片续加在一起,
* 不过如果在反转的同时再利用Matrix加上一些倾斜角度就更好了,不过那样做的话加工后的图片的高度需要同比例计算出来,
* 不能简单的相加了,否则就图片大小就容不下现有的像素内容。
* @param bitmap
* @return
*/
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap)
{
final int reflectionGap =4;
int width = bitmap.getWidth();
int height = bitmap.getHeight();

Matrix matrix =new Matrix();
matrix.preScale(1, -1);

Bitmap reflectionImage = Bitmap.createBitmap(bitmap,0, height /2,
width, height /2, matrix,false);

Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height /2), Config.ARGB_8888);

Canvas canvas =new Canvas(bitmapWithReflection);
canvas.drawBitmap(bitmap,0,0,null);
Paint deafalutPaint =new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);

canvas.drawBitmap(reflectionImage,0, height + reflectionGap,null);

Paint paint =new Paint();
LinearGradient shader =new LinearGradient(0, bitmap.getHeight(),0,
bitmapWithReflection.getHeight() + reflectionGap,0x70ffffff,
0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);

return bitmapWithReflection;
}
/**
* 加旧处理
* @param bitmap
* @return
*/
public static Bitmap toOldBitmap(Bitmap bitmap)
{
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.RGB_565);

Canvas canvas =new Canvas(output);

Paint paint =new Paint();
ColorMatrix cm =new ColorMatrix();
float[] array = {1,0,0,0,50,
0,1,0,0,50,
0,0,1,0,0,
0,0,0,1,0};
cm.set(array);
paint.setColorFilter(new ColorMatrixColorFilter(cm));

canvas.drawBitmap(bitmap,0,0, paint);
return output;
}
/**
*   浮雕处理
* 观察浮雕就不难发现,其实浮雕的特点就是在颜色有跳变的地方就刻条痕迹。127,127,127为深灰色,
* 近似于石头的颜色,此处取该颜色为底色。算法是将上一个点的rgba值减去当前点的rgba值然后加上127得到当前点的颜色。
* @param mBitmap
* @return
*/
public static Bitmap to_embossment(Bitmap mBitmap)
{


int mBitmapWidth =0;
int mBitmapHeight =0;

mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
Bitmap bmpReturn = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
Bitmap.Config.RGB_565);
int preColor =0;
int prepreColor =0;
preColor = mBitmap.getPixel(0,0);

for(int i =0; i < mBitmapWidth; i++)
{
for(int j =0; j < mBitmapHeight; j++)
{
int curr_color = mBitmap.getPixel(i, j);
int r = Color.red(curr_color) - Color.red(prepreColor) +127;
int g = Color.green(curr_color) - Color.red(prepreColor) +127;
int b = Color.green(curr_color) - Color.blue(prepreColor) +127;
int a = Color.alpha(curr_color);
int modif_color = Color.argb(a, r, g, b);
bmpReturn.setPixel(i, j, modif_color);
prepreColor = preColor;
preColor = curr_color;
}
}

Canvas c =new Canvas(bmpReturn);
Paint paint =new Paint();
ColorMatrix cm =new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f =new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpReturn,0,0, paint);

return bmpReturn;
}
/**
*   油画处理
* 其实油画因为是用画笔画的,彩笔画的时候没有那么精确会将本该这点的颜色滑到另一个点处。
* 算法实现就是取一个一定范围内的随机数,每个点的颜色是该点减去随机数坐标后所得坐标的颜色。
* @param bmpSource
* @return
*/
public static Bitmap to_oilPainting(Bitmap bmpSource)
{
Bitmap bmpReturn = Bitmap.createBitmap(bmpSource.getWidth(),
bmpSource.getHeight(), Bitmap.Config.RGB_565);
int color =0;
int Radio =0;
int width = bmpSource.getWidth();
int height = bmpSource.getHeight();

Random rnd =new Random();
int iModel =10;
int i = width - iModel;
while(i >1)
{
int j = height - iModel;
while(j >1)
{
int iPos = rnd.nextInt(100000) % iModel;
color = bmpSource.getPixel(i + iPos, j + iPos);
bmpReturn.setPixel(i, j, color);
j = j -1;
}
i = i -1;
}
return bmpReturn;
}

/**
*   模糊处理
* 算法实现其实是取每三点的平均值做为当前点颜色,这样看上去就变得模糊了。
* 这个算法是三点的平均值,如果能够将范围扩大,并且不是单纯的平均值,
* 而是加权 平均肯定效果会更好。不过处理速度实在是太慢了,而Muzei这种软件在处理的时候
* ,不仅仅速度特别快,而且还有逐渐变模糊的变化过程,显然人家不是用这 种算法实现的。
* 他们的实现方法正在猜测中,实现后也来更新。
* @param bmpSource
* @param Blur
* @return
*/
public static Bitmap blurBitmap(Bitmap bmpSource,int Blur)
{
int mode =5;
Bitmap bmpReturn = Bitmap.createBitmap(bmpSource.getWidth(),
bmpSource.getHeight(), Bitmap.Config.ARGB_8888);
int pixels[] =new int[bmpSource.getWidth() * bmpSource.getHeight()];
int pixelsRawSource[] =new int[bmpSource.getWidth()
* bmpSource.getHeight() *3];
int pixelsRawNew[] =new int[bmpSource.getWidth()
* bmpSource.getHeight() *3];

bmpSource.getPixels(pixels,0, bmpSource.getWidth(),0,0,
bmpSource.getWidth(), bmpSource.getHeight());

for(int k =1; k <= Blur; k++)
{

for(int i =0; i < pixels.length; i++)
{
pixelsRawSource[i *3+0] = Color.red(pixels[i]);
pixelsRawSource[i *3+1] = Color.green(pixels[i]);
pixelsRawSource[i *3+2] = Color.blue(pixels[i]);
}

int CurrentPixel = bmpSource.getWidth() *3+3;

for(int i =0; i < bmpSource.getHeight() -3; i++)
{
for(int j =0; j < bmpSource.getWidth() *3; j++)
{
CurrentPixel +=1;
int sumColor =0;
sumColor = pixelsRawSource[CurrentPixel
- bmpSource.getWidth() *3];
sumColor = sumColor + pixelsRawSource[CurrentPixel -3];
sumColor = sumColor + pixelsRawSource[CurrentPixel +3];
sumColor = sumColor
+ pixelsRawSource[CurrentPixel
+ bmpSource.getWidth() *3];
pixelsRawNew[CurrentPixel] = Math.round(sumColor /4);
}
}

for(int i =0; i < pixels.length; i++)
{
pixels[i] = Color.rgb(pixelsRawNew[i *3+0],
pixelsRawNew[i *3+1], pixelsRawNew[i *3+2]);
}
}

bmpReturn.setPixels(pixels,0, bmpSource.getWidth(),0,0,
bmpSource.getWidth(), bmpSource.getHeight());
return bmpReturn;
}
/**
* 图片合并
* @param bitmap1
* @param bitmap2
* @param path
* @return
* @throws FileNotFoundException
*/
public static Bitmap toJoinbitmap(Bitmap bitmap1,Bitmap bitmap2,String path) throws FileNotFoundException{

Bitmap bitmap3 = Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(), bitmap1.getConfig());
Canvas canvas =new Canvas(bitmap3);
canvas.drawBitmap(bitmap1,new Matrix(),null);
canvas.drawBitmap(bitmap2,120,350,null); //120、350为bitmap2写入点的x、y坐标
//将合并后的bitmap3保存为png图片到本地
FileOutputStream out =new FileOutputStream(path+"/image3.png");
bitmap3.compress(Bitmap.CompressFormat.PNG,90, out);
return bitmap3;
}

/**文字保存为png图片
* @param path 文件保存路径
* @param data 保存数据
* @throws FileNotFoundException
* */
public static void textToImage(String path,ArrayList<String> data) throws FileNotFoundException{

int height = data.size()*20; //图片高
Bitmap bitmap = Bitmap.createBitmap(270,height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE); //背景颜色

Paint p = new Paint();
p.setColor(Color.BLACK); //画笔颜色
p.setTextSize(15); //画笔粗细
for(int i=0;i<data.size();i++){
canvas.drawText(data.get(i),20,(i+1)*20,p);
}
FileOutputStreamout=new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.PNG,90, out);
}