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

cn三少nginx cn三少nginx     2022-08-15     611

关键词:

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图片裁剪的工具类,

 

 

 

[java] view plain copy
 
 技术分享技术分享
  1. /** 
  2.  *  
  3.  */  
  4. package com.bmob.worker.image;  
  5.   
  6. import java.awt.image.BufferedImage;  
  7. import java.io.FileInputStream;  
  8. import java.io.FileNotFoundException;  
  9. import java.io.IOException;  
  10. import java.io.InputStream;  
  11. import java.util.concurrent.ExecutionException;  
  12.   
  13.   
  14.   
  15. /** 
  16.  
  17.  */  
  18. public class Image {  
  19.   
  20.     /* 
  21.      1、指定宽,高自适应,等比例缩放; 
  22.      2、指定高, 宽自适应,等比例缩放; 
  23.      3、指定最长边,短边自适应,等比例缩放; 
  24.      4、指定最短边,长边自适应,等比例缩放; 
  25.      5、指定最大宽高, 等比例缩放; 
  26.      6、固定宽高, 居中裁剪) 
  27.      */  
  28.     public static int DefineWidth=1;   
  29.     public static int DefineHeight=2;   
  30.     public static int DefineLong=3;   
  31.     public static int DefineShort=4;   
  32.     public static int MaxWidthHeight=5;   
  33.     public static int DefineWidthHeight=6;   
  34.       
  35.     /** 
  36.      * 图片缩放的方法 
  37.      *  
  38.      * @param mode 
  39.      1、指定宽,高自适应,等比例缩放; 
  40.      2、指定高, 宽自适应,等比例缩放; 
  41.      3、指定最长边,短边自适应,等比例缩放; 
  42.      4、指定最短边,长边自适应,等比例缩放; 
  43.      5、指定最大宽高, 等比例缩放; 
  44.      6、固定宽高, 居中裁剪) 
  45.      * @param src 源文件路径 
  46.      * @param desc 目标文件路径 
  47.      * @param width 指定宽 
  48.      * @param height 指定高 
  49.      * @param maxFrame 指定最长边 
  50.      * @param minFrame 指定最短边 
  51.      * @return 
  52.      * @throws Exception 
  53.      */  
  54.     public  String resize(int mode, String src,String desc, int width, int height, int maxFrame, int minFrame) throws Exception {  
  55.           
  56.         String str="";  
  57.           
  58.         BHPApplication.init();  
  59.           
  60.         // create command  
  61.         ConvertCmd cmd = this.getCmd();  
  62.         IMOperation op =null;  
  63.         if( mode==Image.DefineWidth ){  
  64.             op=this.resizeDefineWidth( src,desc, width, height);  
  65.         }else if( mode==Image.DefineHeight ){  
  66.             op=this.resizeDefineHeight( src,desc, width, height);  
  67.         }else if( mode==Image.DefineLong ){  
  68.             op=this.resizeDefineLong( src,desc, maxFrame);  
  69.         }else if( mode==Image.DefineShort ){  
  70.             op=this.resizeDefineShort( src,desc, minFrame);  
  71.         }else if( mode==Image.MaxWidthHeight ){  
  72.             op=this.resizeMaxWidthHeight( src,desc, width, height);  
  73.         }else if( mode==Image.DefineWidthHeight ){  
  74.             op=this.resizeDefineWidthHeight( src,desc, width, height);  
  75.         }  
  76.           
  77.         cmd.run(op);  
  78.           
  79.         return str;  
  80.     }  
  81.       
  82.     //指定宽,高自适应,等比例缩放;  
  83.     public  IMOperation resizeDefineWidth(String src,String desc, int width, int height){  
  84.         IMOperation op = new IMOperation();  
  85.         op.addImage(src);  
  86.         op.resize(width,null);  
  87.         op.addImage(desc);        
  88.         return op;  
  89.     }  
  90.       
  91.     //指定高, 宽自适应,等比例缩放;  
  92.     public  IMOperation resizeDefineHeight(String src,String desc, int width, int height){  
  93.         IMOperation op = new IMOperation();  
  94.         op.addImage(src);  
  95.         op.resize(null,height);  
  96.         op.addImage(desc);        
  97.         return op;  
  98.     }  
  99.       
  100.     //指定最长边,短边自适应,等比例缩放;  
  101.     public  IMOperation resizeDefineLong(String src,String desc, int maxFrame) throws Exception{  
  102.           
  103.         InputStream is = new FileInputStream(src);//通过文件名称读取  
  104.         BufferedImage buff = ImageIO.read(is);  
  105.         int srcWidth=buff.getWidth();//得到图片的宽度  
  106.         int srcHeight=buff.getHeight();  //得到图片的高度  
  107.         is.close(); //关闭Stream  
  108.           
  109.         IMOperation op = new IMOperation();  
  110.         op.addImage(src);  
  111.         if( srcWidth>srcHeight ){  
  112.             op.resize(maxFrame,null);  
  113.         }else{  
  114.             op.resize(null,maxFrame);  
  115.         }  
  116.           
  117.         op.addImage(desc);        
  118.         return op;  
  119.     }  
  120.       
  121.     //指定最短边,长边自适应,等比例缩放;  
  122.     public  IMOperation resizeDefineShort(String src,String desc, int minFrame) throws Exception {  
  123.           
  124.         InputStream is = new FileInputStream(src);//通过文件名称读取  
  125.         BufferedImage buff = ImageIO.read(is);  
  126.         int srcWidth=buff.getWidth();//得到图片的宽度  
  127.         int srcHeight=buff.getHeight();  //得到图片的高度  
  128.         is.close(); //关闭Stream        
  129.           
  130.         IMOperation op = new IMOperation();  
  131.         op.addImage(src);  
  132.         if( srcWidth<srcHeight ){  
  133.             op.resize(minFrame,null);  
  134.         }else{  
  135.             op.resize(null,minFrame);  
  136.         }  
  137.         op.addImage(desc);        
  138.         return op;  
  139.     }  
  140.       
  141.     //指定最大宽高, 等比例缩放;  
  142.     public  IMOperation resizeMaxWidthHeight(String src,String desc, int width, int height){  
  143.         IMOperation op = new IMOperation();  
  144.         op.addImage(src);  
  145.         op.resize(width,height,‘!‘);  
  146.         op.addImage(desc);        
  147.         return op;  
  148.     }  
  149.       
  150.     //固定宽高, 居中裁剪  
  151.     public  IMOperation resizeDefineWidthHeight(String src,String desc, int width, int height){  
  152.         IMOperation op = new IMOperation();  
  153.         op.addImage(src);  
  154.         op.gravity("center").extent(width, height);    
  155.         op.addImage(desc);        
  156.         return op;  
  157.     }     
  158.       
  159.     public  ConvertCmd getCmd(){  
  160.         ConvertCmd cmd = new ConvertCmd(true); //set true, use GraphicsMagick  
  161.         String path = "/usr/local/GraphicsMagick/bin"; //GraphicsMagick安装路径  
  162.         cmd.setSearchPath(path);          
  163.         return cmd;  
  164.     }  
  165.       
  166.       
  167.   
  168. }  



app后端系列文章总目录

 

如果您觉得这系列的文章对你有所帮助,欢迎打赏。
支付宝账号:[email protected] 收款人:曾健生

 

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

alpha冲刺12/12

...成情况遇到问题贡献值胡武成完成app端api编写已完成JAVA后端跨域访问没有处理(目前已解决),导致前端localhost请求失败而误以为自己操作失误浪费了不少时间,背锅孙浩楷1.与后端交接,2.完成图片在线编辑插件引入未完成考试... 查看详情

app后端设计--总目录

...,android客户端,iphone客户端,现就职于app云后端平台bmob(想了解bmob点击这里)。其中的乐与苦,得与失,仰首问天有谁知?我觉得是时候来个总 查看详情

前端和后端怎么链接呀?

后端提供接口,前端使用jq的ajax、原生js的XMLHttpRequest、request或者axios模块等调用各自API,请求后端服务器地址,带上请求参数即可实现交互参考技术A前端即网站前台部分,运行在PC端,移动端等浏览器上展现给用户浏览的网页... 查看详情

怪咖------前后端分离与不分离的区别------

   前后端分离,首先所有的程序以数据为基础的,没有数据的程序没有实际意义,程序的本质就是对程序的增删改查,其实前后端分离就是把数据操作和显示分离出来。前端专注做数据显示,通过文字,图片或者图标等方... 查看详情

什么是前端和后端

问题一:什么是网页的前端和后端开发当然他们说的也不专业,前端应该是指前台的设计,包括动画制作,图像处理,文字编辑,版面设计等,需要掌握Dreamweaver,Flash,Fireworks,Photoshop,Freehand等工具.后端开发应是指后台程序设计,包括数据库... 查看详情

jquery图片上传前先在本地预览(不经过后端处理)

...段时间遇到一个问题,前端想实现图片上传预览(不经过后端PHP或JAVA处理),用户点击file按钮上传文件,点击确定马上就能看到预览的效果,但在实现的时候无论怎样都取不到file上图片的真实路径,得到的反而是C:fakepatha.jpg,... 查看详情

微信app支付-android+springboot搭建后端(代码片段)

在微信APP支付-Android+springboot搭建后端(一)和微信APP支付-Android+springboot搭建后端(二)这两篇中基本介绍完了微信APP支付的流程,本篇主要补充一点——对于支付通知的处理和查单。Springboot后端一、支... 查看详情

百度前端解答第一章

...还是以网站为主。一个网站的基本完成需要有UI设计师,后端设计师,前端设计师组成,前端设计师主要是使用ul设计师设计好的图片与后端设计师设计好的架构接口,搭建拼接成一个完整的项目网站。2.详情请见:https://blog.csdn.... 查看详情

如何做好app界面设计?

APP界面设计经验总结当我们打开一个APP时,从视觉层面分析,影响用户对APP整体感官体验的元素主要有:图片、文字、色彩、图标、留白等。图片的合理运用、清晰的信息层级、舒适的色彩搭配都将会提高整个APP的美感,从而为... 查看详情

前后端分离及不分离

前后端不分离  在前后端不分离的应用模式中,前端页面看到的效果是由后端控制,由后端渲染页面或重定向,后端需要控制前端的展示,前端与后端的耦合度很,这种应用模式比较适合纯网页应用,但是当后端对接APP时,APP... 查看详情

基于androidstudio+ssh的单词记忆(背单词)app设计(代码片段)

...1.3.相关技术介绍51.3.1.ionic+angular+cordova混合框架51.4.后端SSH框架6系统需求分析82.1.软件功能82.1.1.需求分析82.2.功能性需求9项目介绍103.1.系统的开发环境103.2.系统的技术路线113.3.系统的具体功能113.3.1.登录注册模块113.3.2.单词... 查看详情

前后端分离

开发模式在Web开发模式中,有两种开发模式前后端不分离前后端分离前后端分离优势在前后端不分离模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合... 查看详情

app系统架构设计初探

一,图片体验的优化。    在手机上显示图片,速度是一个非常重要的体验点,试想,如果您打开一个网站,发现里面的图片一直显示失败或者是x,稍微做得好一点的,可能是一个不消失的loading或者是菊花等等,... 查看详情

前后端分离与前后端不分离

前后端不分离  在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制的,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。  这种应用模式比较适合纯网页应用,但是当... 查看详情

iPhone App设计问题,如何正确显示详细视图

】iPhoneApp设计问题,如何正确显示详细视图【英文标题】:iPhoneAppdesignquestion,howtoshowdetailviewcorrectly【发布时间】:2010-12-0213:38:23【问题描述】:我已经为此苦苦挣扎了一段时间。我需要显示有关当前视图(它本身就是一个详细... 查看详情

uni-app图片未加载完处理

参考技术A1.图片未加载完看到的是.new-img占位背景图片,.new_back透明度设置0;2.图片加载失败显示设置的loadImg失败占位图片3.图片加载完直接显示完整图片同时添加类名.loaded透明度设置1; 查看详情

有状态流处理:flink状态后端

...探讨有状态流处理,更确切地说是Flink中可用的不同状态后端。在以下部分,我们将介绍Flink的3个状态后端,看一下它们的局限性以及如何根据具体案例需求选择最合适的状态后端。在有状态的流处理中,当启用了Flink的检查点... 查看详情

前后端分离与不分离

 前后端不分离    在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。     这种应用... 查看详情