自动处理Android中各个渠道角标和ICON

    技术2023-12-30  70

    前言

      手游上架各大游戏应用商店(渠道)时候,很多渠道对游戏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()) { //如果文件不存在 return return; } 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

    结语:

      记录下自己的学习和工作经验,分享给有需要的人。如果有那里写的不对或者不理解,欢迎大家的指正。

    Processed: 0.017, SQL: 9