app后端设计(12)--图片的处理.docx

app上线后,不断接受用户的反馈,于是,反馈非常差的情况下,都会有app的改版。

一旦app的改版,都会有比较大的UI改动,一改动UI,那么图片的尺寸也就必须要改变。

在app后端设计(1)—api(http://blog.csdn.net/newjueqi/article/details/14053733)这篇文章中,我提到过app后台图片处理的一个基本原则,数据库中只保存原图的路径。对于同一张图片来说,针对不同机型,不同app版本所需要的不同尺寸,使用动态生成的策略,大体思路如下:

(1)      在图片的url末尾加上参数,声明需要生成的图片的新的尺寸,例如:户端需要图片(http://www.baidu.com/img/bdlogo.gif)的80*80的尺寸,则在图片的路径加上宽和高的参数(类似于CDN的机制) http://www.baidu.com/img/bdlogo.gif?w=80&h=80

(2)      服务器接收到图片的请求,先在缓存中查找这个尺寸的图片是否已经生成,如果已经在缓存中有记录,则不用重新生成。

(3)      如果该尺寸的图片还没生成,则生成新的图片尺寸,并把新生成的图片路径放在缓存中。

在app整个系统架构中,图片应该有两层缓存:

(1)      app本地的图片缓存,当app中没有该图片时,才去服务取

(2)      服务器的图片缓存,记录图片不同尺寸的保存路径

我的建议是,如果不差钱,直接使用七牛的云存储的服务吧,云存储不但可以加速图片的下载上传,也能实现图片的大量操作。要知道,速度才是用户体验最直接的部分。

如果真的要自己实现图片的裁切,那么要考虑到图片操作是非常消耗CPU,内存,和大量的磁盘IO,所以在选择图片处理工具要慎重!!!

推荐使用GraphicsMagick,一个久经考验的图片处理软件,支持多个平台,而且支持多种语言的客服端。GraphicsMagick是ImageMagick的一个分支,相对于ImageMagick而言,TA处理速度更快,消耗资源更少,并且大的图片处理网站,如 Flickr and Etsy  已经在使用TA了。

使用GraphicsMagick时,最折腾的是怎么配GraphicsMagick环境,查阅了大量的文章,都注明在linux下不能使用cmd.setSearchPath(path); ,但经过我实验,是可以的,而且配了这个的话,可以让linux和win下都运行同一段代码,只要把path放在配置文件中就好了。

下面我写的GraphicsMagick+Im4java图片裁剪的工具类,

/**
 *
 */
package com.bmob.worker.image;

import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;

/**

 */
public class Image {

	/*
	 1、指定宽,高自适应,等比例缩放;
	 2、指定高, 宽自适应,等比例缩放;
	 3、指定最长边,短边自适应,等比例缩放;
	 4、指定最短边,长边自适应,等比例缩放;
	 5、指定最大宽高, 等比例缩放;
	 6、固定宽高, 居中裁剪)
	 */
	public static int DefineWidth=1;
	public static int DefineHeight=2;
	public static int DefineLong=3;
	public static int DefineShort=4;
	public static int MaxWidthHeight=5;
	public static int DefineWidthHeight=6; 

	/**
	 * 图片缩放的方法
	 *
	 * @param mode
	 1、指定宽,高自适应,等比例缩放;
	 2、指定高, 宽自适应,等比例缩放;
	 3、指定最长边,短边自适应,等比例缩放;
	 4、指定最短边,长边自适应,等比例缩放;
	 5、指定最大宽高, 等比例缩放;
	 6、固定宽高, 居中裁剪)
	 * @param src 源文件路径
	 * @param desc 目标文件路径
	 * @param width 指定宽
	 * @param height 指定高
	 * @param maxFrame 指定最长边
	 * @param minFrame 指定最短边
	 * @return
	 * @throws Exception
	 */
	public  String resize(int mode, String src,String desc, int width, int height, int maxFrame, int minFrame) throws Exception {

		String str="";

		BHPApplication.init();

		// create command
		ConvertCmd cmd = this.getCmd();
		IMOperation op =null;
		if( mode==Image.DefineWidth ){
			op=this.resizeDefineWidth( src,desc, width, height);
		}else if( mode==Image.DefineHeight ){
			op=this.resizeDefineHeight( src,desc, width, height);
		}else if( mode==Image.DefineLong ){
			op=this.resizeDefineLong( src,desc, maxFrame);
		}else if( mode==Image.DefineShort ){
			op=this.resizeDefineShort( src,desc, minFrame);
		}else if( mode==Image.MaxWidthHeight ){
			op=this.resizeMaxWidthHeight( src,desc, width, height);
		}else if( mode==Image.DefineWidthHeight ){
			op=this.resizeDefineWidthHeight( src,desc, width, height);
		}

		cmd.run(op);

		return str;
	}

	//指定宽,高自适应,等比例缩放;
	public  IMOperation resizeDefineWidth(String src,String desc, int width, int height){
		IMOperation op = new IMOperation();
		op.addImage(src);
		op.resize(width,null);
		op.addImage(desc);
		return op;
	}

	//指定高, 宽自适应,等比例缩放;
	public  IMOperation resizeDefineHeight(String src,String desc, int width, int height){
		IMOperation op = new IMOperation();
		op.addImage(src);
		op.resize(null,height);
		op.addImage(desc);
		return op;
	}

	//指定最长边,短边自适应,等比例缩放;
	public  IMOperation resizeDefineLong(String src,String desc, int maxFrame) throws Exception{

		InputStream is = new FileInputStream(src);//通过文件名称读取
		BufferedImage buff = ImageIO.read(is);
		int srcWidth=buff.getWidth();//得到图片的宽度
		int srcHeight=buff.getHeight();  //得到图片的高度
		is.close(); //关闭Stream

		IMOperation op = new IMOperation();
		op.addImage(src);
		if( srcWidth>srcHeight ){
			op.resize(maxFrame,null);
		}else{
			op.resize(null,maxFrame);
		}

		op.addImage(desc);
		return op;
	}

	//指定最短边,长边自适应,等比例缩放;
	public  IMOperation resizeDefineShort(String src,String desc, int minFrame) throws Exception {

		InputStream is = new FileInputStream(src);//通过文件名称读取
		BufferedImage buff = ImageIO.read(is);
		int srcWidth=buff.getWidth();//得到图片的宽度
		int srcHeight=buff.getHeight();  //得到图片的高度
		is.close(); //关闭Stream		

		IMOperation op = new IMOperation();
		op.addImage(src);
		if( srcWidth<srcHeight ){
			op.resize(minFrame,null);
		}else{
			op.resize(null,minFrame);
		}
		op.addImage(desc);
		return op;
	}

	//指定最大宽高, 等比例缩放;
	public  IMOperation resizeMaxWidthHeight(String src,String desc, int width, int height){
		IMOperation op = new IMOperation();
		op.addImage(src);
		op.resize(width,height,'!');
		op.addImage(desc);
		return op;
	}

	//固定宽高, 居中裁剪
	public  IMOperation resizeDefineWidthHeight(String src,String desc, int width, int height){
		IMOperation op = new IMOperation();
		op.addImage(src);
		op.gravity("center").extent(width, height);
		op.addImage(desc);
		return op;
	}	

	public  ConvertCmd getCmd(){
		ConvertCmd cmd = new ConvertCmd(true); //set true, use GraphicsMagick
		String path = "/usr/local/GraphicsMagick/bin"; //GraphicsMagick安装路径
		cmd.setSearchPath(path);
		return cmd;
	}

}

新建了“app后端技术” 交流qq群:254659220

[文章作者]曾健生

[作者邮箱][email protected]

[作者QQ]190678908

[新浪微博] @newjueqi

[博客]http://blog.csdn.net/newjueqi

时间: 2024-08-07 04:31:29

app后端设计(12)--图片的处理.docx的相关文章

app后端设计(12)--图片的处理

app上线后,不断接受用户的反馈,于是,反馈非常差的情况下,都会有app的改版. 一旦app的改版,都会有比较大的UI改动,一改动UI,那么图片的尺寸也就必须要改变. 在app后端设计(1)—api(http://blog.csdn.net/newjueqi/article/details/14053733)这篇文章中,我提到过app后台图片处理的一个基本原则,数据库中只保存原图的路径.对于同一张图片来说,针对不同机型,不同app版本所需要的不同尺寸,使用动态生成的策略,大体思路如下: (1) 

app后端设计--总目录 (转)

特此说明,我转载的!!! app后端设计(1)--api app后端设计(2)--xmpp的使用 app后端设计(3)--短信,邮件,推送服务 app后端设计(4)-- 通讯的安全性 app后端设计(5)-- 表情的处理 app后端设计(6)-- LBS app后端设计(7)-- 项目管理 app后端设计(8)-- 数据库分表 app后端设计(9)-- 动态通知 app后端设计(10)--数据增量更新 app后端设计(11)-- 系统架构 app后端设计(12)--图片的处理 app后端设计(1

app后端设计(php)

来源:http://blog.csdn.net/column/details/mobilebackend.html?page=1 做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经历过手机网页端,android客户端,iphone客户端,现在从事日pv过5千万的云后端开发.其中的乐与苦,得与失,仰首问天有谁知?我觉得是时候来个总结,把相关的技术和心得记录下来. app后端设计(1)--api app后端设计(2)--xmpp的使用 app后端设计(3)--短信,邮件,推送服务

app后端设计(0)--总目录(转)

原文:http://blog.csdn.net/newjueqi/article/details/19003775 做了接近两年app相关的系统架构,api设计,先后在两个创业公司中工作,经历过手机网页端,android客户端,iphone客户端,其中的乐与苦,得与失,仰首问天有谁知?我觉得是时候来个总结,把相关的技术和心得记录下来. 注:这系列文章谈到的经验是根据自身在小型创业团队中总结的,大牛们请飘过^-^ app后端设计(1)--api app后端设计(2)--xmpp的使用 app后端设

app后端设计(0)--总目录

原文:http://blog.csdn.net/newjueqi/article/details/19003775 做了接近两年app相关的系统架构,api设计,先后在两个创业公司中工作,经历过手机网页端,android客户端,iphone客户端,其中的乐与苦,得与失,仰首问天有谁知?我觉得是时候来个总结,把相关的技术和心得记录下来. 注:这系列文章谈到的经验是根据自身在小型创业团队中总结的,大牛们请飘过^-^ app后端设计(1)--api app后端设计(2)--xmpp的使用 app后端设

app后端设计(13)--IM4JAVA+GraphicsMagick实现中文水印

在app的后台中,有时候为了标示版权,需要给图片加上水印. 在liunx中,IM4JAVA+GraphicsMagick是个高效处理图片的方案,图片的裁剪是使用了这个技术方案,为了减少不必要的开发成本和运维成本,对应水印,我们是打算继续采用这个方案. 但在开发的过程中,发现这个方案对中文水印支持得不好. 根据网上的搜索结果,就算采用了im4java的GMOperation,并将水印的字符串转成GBK的编码,添加中文水印时,对于奇数个数的中文,没问题:但对于偶数个数的中文,就出现乱码了. 试了多次

23.app后端如何架设文件系统

现在app展现内容的形式多种多样的,有文字,图片,声音,视频等等,其中文件占了一个很大的比重.随着app不断运营,文件会越来越多,占用的磁盘空间也不断增大,架设一套高效的文件系统,对于整个app架构有着巨大的影响. 1.    如果可能,使用成熟的文件云存储服务 对于创业公司来说,我一直推崇的架构原则是"尽量使用成熟的第三方服务和软件,自己只负责业务逻辑". 架设文件系统,需要牵涉到文件的分布式存储,图片水印,图片缩放,还有CDN等方面,每方面都能耗费掉巨大的开发成本和运维成本. 对于

14.app后端如何设计api

app和后端的交互,一般都是通过后端提供的api实现.api的设计,估计很多刚进入app后端的小伙伴会一无头绪,不知道怎么入门.下面根据自己3年的app后端经验,总结出下几个api设计原则,给小伙伴参考. 1. 什么是api? 这个问题在以前发表的文章"7.app和app后端的通讯"中其实已经回答了,这里再重复一次. 相信大家都用过银行的柜员机(ATM)的查询余额,转帐,取款等操作. 当在柜员机取款的时候,我们输入要取款的金额,隔一会钱就出来了,如果因为有什么问题不能取款(例如超过取款

app后端api设计【转】

博客:https://blog.csdn.net/newjueqi/article/details/44037011 app和后端的交互,一般都是通过后端提供的api实现.api的设计,估计很多刚进入app后端的小伙伴会一无头绪,不知道怎么入门.下面根据自己3年的app后端经验,总结出下几个api设计原则,给小伙伴参考. 1. 什么是api? 这个问题在以前发表的文章"7.app和app后端的通讯"中其实已经回答了,这里再重复一次. 相信大家都用过银行的柜员机(ATM)的查询余额,转帐