当前位置: 首页>編程日記>正文

JAVA实现生成GIF动态图加文字(完整版无License带锯齿优化处理)

JAVA实现生成GIF动态图加文字(完整版无License带锯齿优化处理)

之前一直觉得实现在图片上添加文字很厉害,后来机缘巧合之下,我也需要自己去实现这个步骤,所以在下面梳理一下踩过的坑和实现的原理,希望能帮到大家。

从网上搜索JAVA相关生成GIF加文字或者加水印会发现已经有很多已经实现的了,不过大都是使用gif4j进行的合成,这种做法在个人使用肯定是没有什么问题,但是要自己公司用或者用于商用的话,就会有很多的License问题,秉着能省则省的原则,所以打算另辟蹊径。

首先要感谢Kevin Weiner提供的实现基础。这是工具类的链接,实现原理就是基于这个来实现的。

链接:https://github.com/rtyley/animated-gif-lib-for-java 尊重原版。

先贴实现代码:

public static void main(String[] args) throws Exception {long timestart = System.currentTimeMillis();InputStream inputStream1 = new FileInputStream("C:\\Users\\TMP\\3_5.gif");new ImageUtil2().getGifSticker("测试问题","SIMSUN.ttf",inputStream1);long timeend = System.currentTimeMillis();System.out.println("用时"+(timeend-timestart));}public void getGifSticker(String markContent,String fontName, InputStream inputStream) throws FontFormatException, IOException  {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try {GifDecoder decoder = new GifDecoder();//读入gif数据流decoder.read(inputStream);//获取GIF的宽高Dimension dimension = decoder.getFrameSize();int height = (int)dimension.getHeight();//获取字体问津数据流,用于规范生成文字的字体格式InputStream intput = ImageUtil2.class.getResourceAsStream(fontName);//生成字体Font font1 = Font.createFont(Font.TRUETYPE_FONT, intput);//要是想使用deriveFont设置字体大小必须重新指定Font,而且不支持整数型,只能使用浮点类型Font font = font1.deriveFont(25.0f);//读取帧数int frameCount = decoder.getFrameCount();AnimatedGifEncoder encoder = new AnimatedGifEncoder();String url = "C:\\Users\\TMP\\o\\" + + System.currentTimeMillis()+".gif";encoder.start(url);encoder.setRepeat(0);Graphics2D g = null;/*** 对GIF进行拆分* 每一帧进行文字处理* 组装*/for (int i = 0; i < frameCount; i++) {//初始化图像g =  (Graphics2D) decoder.getFrame(i).getGraphics();/*** RenderingHint是对图片像素,锯齿等等做的优化,可保证生成的图片放大锯齿点阵也不会很明显*/g.setRenderingHint(SunHints.KEY_ANTIALIASING, SunHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(SunHints.KEY_TEXT_ANTIALIASING, SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
//			    g.setRenderingHint(SunHints.KEY_STROKE_CONTROL, SunHints.VALUE_STROKE_PURE);
//			    g.setRenderingHint(SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST, 100);
//			    g.setRenderingHint(SunHints.KEY_FRACTIONALMETRICS, SunHints.VALUE_FRACTIONALMETRICS_OFF);
//			    g.setRenderingHint(SunHints.KEY_RENDERING, SunHints.VALUE_RENDER_DEFAULT);g.setColor(Color.black); g.setFont(font);g.setFont(font);//设置打印文字和坐标g.drawString(markContent, 12, 81);g.dispose();//组装每一帧encoder.addFrame(decoder.getFrame(i));//设置每帧的切换时间if (i != frameCount - 1) {encoder.setDelay(decoder.getDelay(i));}}encoder.finish();byte b[] = outputStream.toByteArray();}finally {try {if (null != outputStream)outputStream.close();} catch (IOException e) {}}}

传入参数 :markContent : 生成文字 fontName 字体文字  inputStream 图片数据流

原理分析:

根据传入的字体文字去当先CLASSPATH下面找到对应字体文件(建议使用ttf文件,对otf的支持还不是很理想,要想要没有License的ttf字体文件欢迎私聊)。

然后根据传入的image数据流进行操作,代码的分析我都在注释中有声明。

后来发现每次生成的所有GIF虽然都很正常,但是发现放大来看文字会有点阵锯齿问题,研究良久,对这个问题也颇有了解,后来根据JDK源码进行了优化,使用边缘抖动模糊进行的一个处理,这样的话如果放大的话边缘处也会很平滑,但是有一点缺点就是会有略微的模糊,不过对比来看,问题不大!

锯齿优化思路如下:

由于是使用的Graphics2D进行的图像的制作和渲染,所以这个支持RenderingHints的一个处理,关于RenderingHints声明如下:

 * The {@code RenderingHints} class defines and manages collections of  keys and associated values which allow an application to provide input  into the choice of algorithms used by other classes which perform rendering and image manipulation services.* The {@link java.awt.Graphics2D} class, and classes that implement  {@link java.awt.image.BufferedImageOp} and  {@link java.awt.image.RasterOp} all provide methods to get and  possibly to set individual or groups of {@code RenderingHints}  keys and their associated values.* When those implementations perform any rendering or image manipulation  operations they should examine the values of any {@code RenderingHints}  that were requested by the caller and tailor the algorithms used accordingly and to the best of their ability.* <p>* Note that since these keys and values are <i>hints</i>, there is  no requirement that a given implementation supports all possible  choices indicated below or that it can respond to requests to modify its choice of algorithm.* The values of the various hint keys may also interact such that  while all variants of a given key are supported in one situation,* the implementation may be more restricted when the values associated with other keys are modified.* For example, some implementations may be able to provide several types of dithering when the antialiasing hint is turned off, but  have little control over dithering when antialiasing is on.* The full set of supported keys and hints may also vary by destination since runtimes may use different underlying modules to render to  the screen, or to {@link java.awt.image.BufferedImage} objects,  or while printing.* <p>* Implementations are free to ignore the hints completely, but should  try to use an implementation algorithm that is as close as possible to the request.* If an implementation supports a given algorithm when any value is used  for an associated hint key, then minimally it must do so when the  value for that key is the exact value that specifies the algorithm.* <p>* The keys used to control the hints are all special values that  subclass the associated {@link RenderingHints.Key} class.* Many common hints are expressed below as static constants in this class, but the list is not meant to be exhaustive.* Other hints may be created by other packages by defining new objects  which subclass the {@code Key} class and defining the associated values.

粗略翻译如下:

* {@code RenderingHints}类定义和管理键和相关值的集合,允许应用程序为执行渲染和图像处理服务的其他类所使用的算法选择提供输入。
 * {@link java.awt.Graphics2D}类和实现{@link java.awt.image.BufferedImageOp}和{@link java.awt.image.RasterOp}的类都提供了获取和可能设置个体的方法或{@code RenderingHints}键组及其相关值。
 *当这些实现执行任何渲染或图像处理操作时,他们应检查调用者请求的任何{@code RenderingHints}的值,并根据他们的能力量身定制所使用的算法。
 * <p>
 *请注意,由于这些键和值是<i>提示</ i>,因此不要求给定的实现支持下面指出的所有可能的选择,或者它可以响应修改其算法选择的请求。
 *各种提示键的值也可以相互作用,以便在一种情况下支持给定键的所有变体,
 *当修改与其他键相关联的值时,实现可能会受到更多限制。
 *例如,某些实现可能能够在关闭抗锯齿提示时提供几种类型的抖动,但在打开抗锯齿时几乎无法控制抖动。
 *完整的受支持的键和提示集也可能因目的地而异,因为运行时可能使用不同的底层模块呈现到屏幕,或{@link java.awt.image.BufferedImage}对象,或者在打印时。
 * <p>
 *实现可以完全忽略提示,但应该尝试使用尽可能接近请求的实现算法。
 *如果某个实现支持给定的算法,当任何值用于关联的提示键时,那么当该键的值是指定算法的确切值时,它必须最低限度地执行此操作。
 * <p>
 *用于控制提示的键都是特殊值,它们是关联的{@link RenderingHints.Key}类的子类。
 *许多常见提示在下面表示为此类中的静态常量,但该列表并不是详尽无遗的。
 *其他提示可以通过定义新的对象来创建,这些对象继承了{@code Key}类并定义了相关的值。

所以我在本地使用的优化有这些:

g.setRenderingHint(SunHints.KEY_ANTIALIASING, SunHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(SunHints.KEY_TEXT_ANTIALIASING, SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
//			    g.setRenderingHint(SunHints.KEY_STROKE_CONTROL, SunHints.VALUE_STROKE_PURE);
//			    g.setRenderingHint(SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST, 100);
//			    g.setRenderingHint(SunHints.KEY_FRACTIONALMETRICS, SunHints.VALUE_FRACTIONALMETRICS_OFF);
//			    g.setRenderingHint(SunHints.KEY_RENDERING, SunHints.VALUE_RENDER_DEFAULT);

第一行是说明对整个图画的一个矩阵优化,当然如果你和我一样是在图片上添加文字的话,第一行就和第二行没有什么区别。
简而言之,前两行都是对图片点阵锯齿的一个模糊话处理,但是JDK中也说了,会有不可控的抖动会出现,所以在原图放大来看会略微模糊一点。

支持并发,每次读入的图片数据库都有close不用手动去关闭。

以上。

 

良心手打,有疑问或者好的优化建议欢迎找茬。


https://www.fengoutiyan.com/post/15861.html

相关文章:

  • 自己如何制作动态图
  • gif生成在线制作
  • 动态图怎么加文字
  • gif动图文字修改
  • gif动图转换
  • gif转换jpg动态
  • 动态图
  • 怎么生成动态图片
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機