前言
手游上架各大游戏应用商店(渠道)时候,很多渠道对游戏icon有要求, 需要加上渠道提供的角标才能正常上架,最开始的时候需要让美术去完成游戏icon和游戏角标合成工作, 客户端需要将美工合成后的图片复制到对应路径,多个游戏多个渠道都要来一遍,想想这个工作量就酸爽。合成图片这个工作太依赖美术 重复复制合成后的图片到对应路径 浪费大量的人力和时间成本。懒是第一生产力,反复重复的工作能用代码 解决绝不手动复制。
实现效果和说明
- 合成图片首先要有2张图片,放一个512 * 512游戏图标的ICON。注意一定要是PNG格式另需要一个512 * 512带渠道角标的图片(一般渠道都会提供)
- 用代码方式进行2张图片合成,合成后效果如下图app_icon.png
代码逻辑
- 用java.awt.Graphics2D 类 进行2张图片合成,建议游戏icon和渠道角标放在同一个路径下,合成后的icon放到另一个路径下。
- 文件复制用到 FileUtils.copyFile()需要下载对应jar如有需要私信我。
- app_icon这个命名是获取AndroidMainfest.xml中application节点中配置的图标名称 例如android:icon=@drawable/app_icon ,@drawable对应着res下的\”drawable-hdpi\”,“drawable-ldpi”, “drawable-mdpi”,“drawable-xhdpi”,“drawable-xxhdpi”, “drawable-xxxhdpi”,
- android:icon=@mipmap/app_icon,@mipmap对应着 “mipmap-hdpi”,“mipmap-mdpi”, “mipmap-xhdpi”,“mipmap-xxhdpi”,“mipmap-xxxhdpi”, “mipmap-xxxhdpi-v4”,“mipmap-xxhdpi-v4”,“mipmap-xhdpi-v4”,“mipmap-mdpi-v4”, “mipmap-ldpi-v4”,\”mipmap-hdpi-v4\”文件夹,合成后的icon需要复制到res/路径下替换。
- Java版本是打包工具合成icon功能中拆分出来的部分代码,有需要可以在这个基础上做下代码调整。python 版只是简单实现并没有处理多余的逻辑。
代码实现(java版本)
import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;import javax.imageio.ImageIO;import org.apache.commons.io.FileUtils;/***JDK1.8* @author sjr 2020-6-30*/public class ChannelMergeImg {/*** 写入指定路径*/private static void writeImageToLocal(String marketIconPath,BufferedImage mergeImage) throws IOException {if (marketIconPath == \"\" || marketIconPath == null) {return;}if (mergeImage == null) {return;}ImageIO.write(mergeImage, \"png\", new File(marketIconPath));}private static BufferedImage getImageFromLocal(String path) throws IOException {return ImageIO.read(new File(path));}/*** @param gameIconPath 游戏icon路径* @param marketIconPath 渠道角标路径* @param mergeIconPath 合成后的角标路径*/public static void saveMergeImage(String gameIconPath, String marketIconPath,String mergeIconPath) {System.out.println(\"图片开始合成\");try {writeImageToLocal(mergeIconPath,mergeImage(getImageFromLocal(gameIconPath),getImageFromLocal(marketIconPath)));System.out.println(\"图片合成结束\");} catch (IOException e) {System.out.println(\"图片合成异常\");e.printStackTrace();}}/*** 合并图片核心代码*/private static BufferedImage mergeImage(BufferedImage gameIconPath,BufferedImage marketIconPath) {if (gameIconPath != null && marketIconPath != null) {Graphics2D graphics2D = marketIconPath.createGraphics();graphics2D.drawImage(gameIconPath, 0, 0, 512, 512, null);graphics2D.dispose();}return marketIconPath;}public static List<String> getIconOutPutListDir(String outPutDir) {String[] dirList = new String[] {\"drawable-hdpi\",\"drawable-ldpi\", \"drawable-mdpi\", \"drawable-xhdpi\",\"drawable-xxhdpi\", \"drawable-xxxhdpi\", \"mipmap-hdpi\",\"mipmap-mdpi\", \"mipmap-xhdpi\", \"mipmap-xxhdpi\",\"mipmap-xxxhdpi\", \"mipmap-xxxhdpi-v4\", \"mipmap-xxhdpi-v4\",\"mipmap-xhdpi-v4\", \"mipmap-mdpi-v4\", \"mipmap-ldpi-v4\",\"mipmap-hdpi-v4\" };return Arrays.stream(dirList).map(dir -> outPutDir + dir).collect(Collectors.toList());}/*** 替换普通图标为带角标图片* @throws Exception*/public static void replaceGameIcon(String outPutDir ,String marketMargeIconPath) throws Exception {getIconOutPutListDir(outPutDir).stream().forEach(dir -> {if (!new File(outPutDir).exists()) { //如果文件不存在 returnreturn;}try {FileUtils.copyFile(new File(marketMargeIconPath), new File(dir+ File.separator + \"app_icon.png\"));System.out.println(\"开始拷贝文件:\"+dir+File.separator+\"app_icon.png\");} catch (IOException e) {e.printStackTrace();}});System.out.println(\"拷贝图片结束\");}public static void main(String[] args) {String gameIconPath=\"C:\\\\Users\\\\Administrator\\\\Desktop\\\\master\\\\icon\\\\channelIcon\\\\common_icon.png\";String marketIconPath=\"C:\\\\Users\\\\Administrator\\\\Desktop\\\\master\\\\icon\\\\channelIcon\\\\icon_marker.png\";String mergeIconPath=\"C:\\\\Users\\\\Administrator\\\\Desktop\\\\master\\\\icon\\\\app_icon.png\";ChannelMergeImg.saveMergeImage(marketIconPath,gameIconPath, mergeIconPath);String outPutDir=\"C:\\\\Users\\\\Administrator\\\\Desktop\\\\master\\\\output\\\\res\\\\\";try {ChannelMergeImg.replaceGameIcon(outPutDir, mergeIconPath);} catch (Exception e) {e.printStackTrace();}}}
Python版icon合成(python2.7)
pip命令安装 pip install Pillow
Pillow使用方式详见 :http://pillow.readthedocs.io/en/latest/reference/Image.html
# -*- coding: utf-8 -*-from PIL import Image\'\'\'图片合成\'\'\'def mergePicture():commonIcon= Image.open(\"C:/Users/Administrator/Desktop/common_icon.png\")markIcon = Image.open(\"C:/Users/Administrator/Desktop/icon_marker.png\")markLayer = Image.new(\'RGBA\', commonIcon.size, (0, 0, 0, 0))markLayer.paste(markIcon, (0, 0))out = Image.composite(markLayer, commonIcon, markLayer)out.save(\"C:/Users/Administrator/Desktop/app_icon.png\", quality=95, subsampling=0)print (\'Merge picture Successful\')if __name__== \'__main__\':mergePicture()
python2.7版本合成icon 参考借鉴了博客:http://www.uustory.com/?p=1778
结语:
记录下自己的学习和工作经验,分享给有需要的人。如果有那里写的不对或者不理解,欢迎大家的指正。