从零开始的立绘拆包教程

蓝毒小天使天下第一!
蓝毒小天使天下第一!

本文拆包教程不限于明日方舟,在后面也会给出其他手游的拆包教程,例如少女前线,碧蓝航线等
最近一次更新于2019年8月7日

目录

拆包简介和使用工具:

首先拆包最简单的无非就是拆取游戏资源,例如游戏立绘,音频,视频等,再深层次一点有拆取游戏配置文件,apk反编译得到部分源码等
在本文,我们只介绍拆取游戏资源和对游戏资源的后期处理,但是这里的方法不能保证所有的手游立绘都能提取,不同游戏对立绘等游戏文件的处理不同,这里只提供几种思路 XD

可能需要用到的工具有 Unity Studio,装有 opencv 的python或C++,PhotoShop
其中 Unity Studio 是必要工具,可以用来提取市面上大部分手游的游戏资源
装有 opencv 的python或C++,PhotoShop 等可以对提取的游戏资源(立绘)进行处理,如果是要批量处理的话首推 C++python 虽然方便但是太慢,PhotoShop 也可以进行批量处理,但是麻烦且慢

PS:如果有其他有同样功能的工具也可以,不限于上面的几个软件,点击蓝色可以进网盘下载,理论上用 python的 PIL库 更好,不过我直接用 opencv 了,导致最后生成的可执行文件比较大

提取资源的方法:

首先,如果要拆取立绘等文件,就需要对应用程序进行处理,最简单的有两种方式:

  1. 对下载的 apk 安装包 进行解压
    方法如下,在电脑上下载对应游戏的apk安装包,把后缀 .apk 改为压缩包文件格式,如 .rar 等,利用解压软件对其进行解压得到解压文件夹
  2. 对已经安装在手机的游戏,寻找系统目录,找到其文件夹
    以少女前线为例,通常在手机上安装的软件,会把资源文件等放在 Android 文件夹的 data 文件夹下,这个时候找到其对应的游戏文件夹即可,下图是 少女前线 的文件夹,明日方舟比较特殊,它将资源文件隐藏在了其他文件目录下,所以最好使用第一种方法
    在这里插入图片描述
    通常进入文件夹后按照顺序进入以下文件夹 files 文件夹—— AB 文件夹 ——Android 文件夹,会看到里面的游戏资源文件,如果你是按照第一个解压方法做的,也可以看到上面的文件路径,按照该顺序点进去就行,然后根据游戏的不同,不同的文件可能会被放在一起,也可能会被分类在不同文件夹中,这个时候只需要按照自己需要的进行复制提取到电脑上就好了,注意不要剪切,特别是用第二种方法的,千万别剪切

当然,到这里还没有结束,我们看到的资源文件并不是原来格式,而是以 ab后缀的文件 展示的,这个时候就需要 Unity Studio 来提取目标文件(当然不是所有手游都会用Unity,所以这个方法并不适用于所有手游,如果以后我遇到其他类型的再更新吧XD)
在这里插入图片描述
这里我们以明日方舟为例,如果你正确的找到了路径,那么你可以看到一个名为 charpack 的文件夹,其中储存了明日方舟的干员立绘文件
在这里插入图片描述
这个时候打开 Unity Studio ,用如下选项 Extract folder 批量解压提取ab文件,之后使用 load folder 加载处理后的文件
在这里插入图片描述
然后在 Asset List 中就可以看到提取的内容
在这里插入图片描述
在这里插入图片描述

资源的后续处理:

提取出来的图片大部分情况下是有瑕疵的,因为他们需要进一步处理才能得到原图
而对于其中提取的内容,我们通常需要关心很多文件
常规情况下(使用通道分离压缩图片的):我们需要找到一个是Type为Texture2D的原图,一个是Type为Texture2D或Sprite的透明度背景图,而且通常情况下,原图有一个文件名,对应透明度背景图文件名会在原图文件名后面加上alpha字样,我们通过处理这两个图才能得到最终的png图像文件,所以现在就将所有对应的图片文件从 Unity Studio 导出
还有一些情况,有些手游会对图片进行加密或者是做一些额外处理:这种情况我们就需要按照情况来分析哪些文件有用,哪些文件没用,例如碧蓝航线需要使用一张图片 + 一张obj 3D模型文件来还原原图

在这里插入图片描述

A. 通道分离图像的合成:

首先我们在前面提到过,如果我们能找到一个是Type为Texture2D的原图,一个是Type为Texture2D或Sprite的透明度背景图,那么就说明这个立绘需要进行通道分离图像的合成来得到原图

那么这个时候我们应该如何处理呢,首先 png 图像有4个通道,前三个是 RGB 颜色通道,第四个是透明度通道,实际上为了减少图片的大小,大部分游戏厂商都会先对图片进行 ETC 等压缩算法的处理,再将透明通道单独剥离出去,以达到最大程度的压缩,其中你会发现我们经手的立绘和在游戏中展示的一样,但仔细看会发现不够清晰,正是因为在打包成apk文件之前,游戏公司就已经先对图片进行了压缩处理,丧失了一部分信息,所以说并不是画师的原图,如果想提高清晰度,有两种方法,一种是找原画师或官方公布等途径得到原图,一种是利用图片优化软件对其进行清晰度优化

进入正题,如何处理我们得到文件?

1. 利用 PS 进行处理:

这里我们直接引用一下这位贴吧老哥的方法: 透明立绘简单合成方法,小白一键操作

方法很简单,但缺点是对大量处理文件十分无力,而且需要手工对文件顺序进行排序,也没法判断两个图片尺寸比,适合小量立绘的手工处理

效果图:
在这里插入图片描述
输出效果:
在这里插入图片描述

2. 利用python或C++进行处理:

这个方法适合大量处理,而且不用对图片进行分类,甚至你在 Untiy Studio上导出图片时,可以毫无顾忌的将图片一股脑导出来,让程序自己去找原图和透明度背景图
在这里我用到的工具是 opencv 库

以明日方舟为例: 可以发现它 Alpha 图像中 R 通道 的值代表原图片透明度,那么我只需要将这个图片矩阵的 R 通道 信息赋值给原图像的 透明度通道 即可,然后注意一下有些Alpha图像是原图像大小的 1/2 倍,需要放大 2
其中放大方法调用的是 双立方插值算法 ,这个算法效果比较好
另外就是 PhotoShop 的默认放大算法也是这个算法

python代码: (本来想用C++的,但无奈python太方便了Orz,导致处理速度会慢很多)

# -*- coding: utf-8 -*-
import shutil
import time
import cv2
import os

def read_png(s):
	img = cv2.imread(s, cv2.IMREAD_UNCHANGED)
	return img
def save_png(s, img):
	cv2.imwrite(s, img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
def exchange(img, x): #放大图像
	w, h = img.shape[0:2]
	tempimg = cv2.resize(img,(w*x,h*x), interpolation=cv2.INTER_CUBIC)
	return tempimg
def Do(a, b):
    a[:,:,3] = b[:,:,0] #合成的基本思路
    return a
    
print("提取图片/合成立绘?1/2")
a = input()
if a == '1': #提取立绘
    file_list = os.listdir("./Input")
    print("共%d个图片:" %len(file_list))
    print('begin')
    for i in file_list:
      	img = cv2.imread("./Input/" + i, cv2.IMREAD_UNCHANGED)
        	if img is not None and img.shape[0] > 512:
         	if '#' in i:
          	i2 = i.replace(i[i.find('#'):], '#1[alpha].png')
            	i3 = i.replace(i[i.find('#'):], '#1.png')
         	else:
         		i2 = i.replace(".png", '[alpha].png')
         		i3 = i
         	if i2 in file_list:
         		hutil.copy("./Input/" + i, "./Texture2D_A/" + i3)
         		os.remove("./Input/" + i)
         		shutil.copy("./Input/" + i2, "./Texture2D_B/" + i2)
         		os.remove("./Input/" + i2)
    	print('over')
    	os.system('pause')
if a == '2': #合成立绘
	file_list = os.listdir("./Texture2D_A")
	print("待合成%d个图片:" %len(file_list))
    	for i in file_list:
    		print('正在处理%s' %i)
    		time_start = time.time()
    		i2 = i.replace(".png", '[Alpha].png')
    		a = read_png('./Texture2D_A/' + i)
    		b = read_png('./Texture2D_B/' + i2)
    		if a.shape[0]/b.shape[0] != 1:
    			b = exchange(b, int(a.shape[0]/b.shape[0]))
    			save_png('./Picture/' + i, Do(a, b))
    			shutil.copy("./Texture2D_A/" + i, "./Used/" + i)
    			os.remove("./Texture2D_A/" + i)
    			time_end = time.time()
    			print("耗时 %f s" %(time_end-time_start))
    	print('over')
    	os.system('pause')

具体操作就是:
1:你只需要把提取出来的立绘图像(可以包括小人动态的分割图像)放进 Input 文件夹中
2:运行exe文件,先输入 1 提取所有合理的立绘图像
3:再次运行exe文件,输入 2 合成立绘,最后图像在 Picture 文件夹中
在这里插入图片描述
其中 Texture2D_ATexture2D_BUsed 都是程序运行的中间文件夹,可以不用去管,另外就是这个程序支持中断操作,也就是说你在合成图片或提取图片时因为某些原因终止了程序,那么程序会保留你之前的记录,你想要把剩余的图片处理完,只需要再次运行即可


明日方舟立绘集合,目前更新至2019年7月20号: 明日方舟立绘集合,提取码:5iyj
明日方舟立绘合成器,目前更新至2019年7月20号: 明日方舟立绘合成器,提取码:dsfd

同理,少女前线也是使用了通道分离来处理立绘图像,所以代码都差不多,就不贴了

少女前线立绘集合,目前更新至2019年7月27号: 少女前线立绘集合,提取码:xmts
少女前线立绘合成器,目前更新至2019年8月3号: 少女前线立绘合成器,提取码:50f9

B. 碎块图像合成:

比较典型的就是就是碧蓝航线,这款游戏没有用通道分离来压缩图像,而是因不明原因,将图像换成了碎块和记录碎块在原图信息的 obj 文件组成

22 举例:

碎块图(尸块图):

在这里插入图片描述
obj文件:
在这里插入图片描述
打开obj文件分析就会发现其中的 v 记录的是每个碎块在原图像的顶点坐标,4 个为一组:
在这里插入图片描述
其中的 vt 记录的是每个碎块在碎块图像的顶点坐标(分别乘上碎块图像长和宽之后就是顶点坐标,这个小数代表在碎块图像中的比例位置),也是 4 个为一组:
在这里插入图片描述
那么通过读取 obj 文件的信息来拼接碎尸图,就可以系统的将原图拼接好

python代码:

# -*- coding: utf-8 -*-
import numpy as np
import shutil
import time
import cv2
import os

def read_file(s):
	List1 = []
	Filer = open(s,'r')
	List2 = Filer.readlines()
	Filer.close()
	for i0 in range(0, len(List2)):
		List2[i0] = List2[i0].replace("\n", "")
		List1.append(List2[i0].split())
	return List1
	
def read_png(s):
	img = cv2.imread(s, cv2.IMREAD_UNCHANGED)
	return img
def save_png(s, img):
	cv2.imwrite(s, img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
def rotate(img):
	new_img = cv2.flip(img, -1)
	return new_img
	
def manage(s1, s2):
	s1 = "./Mesh/" + s1
	max_height = max_weight = vtjShu = firstx = endx = firsty = endy = 0
	print('正在处理%s' %s2)
	time_start = time.time()
	List = read_file(s1)
	img = read_png("./Texture2D/" + s2)
	height = img.shape[0]
	eight = img.shape[1]
	img = rotate(img)
	img = cv2.flip(img, 1
	for i in range(1, len(List)):
		if List[i][0] != 'v':
			vtjShu = i
			break
		if abs(int(List[i][1])) > max_weight:
			max_weight = abs(int(List[i][1]))
		if abs(int(List[i][2])) > max_height:
			max_height = abs(int(List[i][2])
	Base_img = np.zeros([max_height+1, max_weight+1, 4], np.uint8)
	jShu = vtjShu
	while vtjShu < len(List):
		if List[vtjShu][0] != 'vt':
			break
		firsty = int(float(List[vtjShu][1]) * float(weight) + 0.5)
		firstx = int(float(List[vtjShu][2]) * float(height) + 0.5)
		endy = int(float(List[vtjShu+2][1]) * float(weight) + 0.5)
		endx = int(float(List[vtjShu+2][2]) * float(height) + 0.5)
		y1 = abs(int(List[vtjShu-jShu+1][1]))
		x1 = abs(int(List[vtjShu-jShu+1][2]))
		for i in range(firstx, endx):
			for j in range(firsty, endy):
				Base_img[x1+i-firstx][y1+j-firsty] = img[i][j]
		vtjShu += 4
	Base_img = rotate(Base_img)
	save_png("./Picture/"+s2, Base_img)
	time_end = time.time()
	print("处理完毕,耗时 %f s" %(time_end-time_start))

Mesh_list = os.listdir("./Mesh")
Texture2D_list = os.listdir("./Texture2D")
print("检测到%d组" %len(Texture2D_list))
for i in range(0, len(Texture2D_list)):
	s = Texture2D_list[i].replace(".png", "-mesh.obj")
	if s not in Mesh_list:
		print("Can't find the %s in Mesh" %s)	
	else:
		manage(s, Texture2D_list[i])
		shutil.copy("./Texture2D/" + Texture2D_list[i], "./Used/" + Texture2D_list[i])
		os.remove("./Texture2D/" + Texture2D_list[i])
print("Over")
os.system("pause")


碧蓝航线立绘集合,目前更新至2019年7月31号: 碧蓝航线立绘集合,提取码:65wf
碧蓝航线立绘合成器,目前更新至2019年8月5号: 碧蓝航线立绘合成器,提取码:slcg

具体操作就是:
1:你只需要把提取出来的立绘图像放在 Texture2D 中,而 obj 文件放进 Mesh 文件夹中,不必考虑顺序问题,程序会自己找
2:运行exe文件即可,最后结果在 Picture 文件夹中
在这里插入图片描述
其中 Used 是程序运行的中间文件夹,可以不用去管,另外就是这个程序跟上一个明日方舟立绘合成的程序一样也支持中断操作,所以中途暂停再运行是会按照原来的进度继续,而不是从头开始

C. 其他类型待更

其他手游的资源提取方法和后期处理方法可能会有所不同,而有些手游则相同,所以需要变通,如果有时间的话这个博客应该会一直更新

后记:

本人拆包立绘仅出于学习目的,不用做商业用途 (舔老婆 prpr)

### 回答1: "圣女战旗"是一款冒险战斗类游戏,在游戏中,玩家可以扮演各种游戏角色进行战斗和探险。游戏中的角色立绘是提供游戏玩家了解和认识角色外貌特征的重要组成部分。 这款游戏提供的游戏角色全身免扣PNG立绘,意味着角色的立绘图像没有背景,可以直接使用。这方便了玩家在制作宣传海报、编辑视频、设计游戏界面等方面的创作。玩家可以根据自己的需求,将立绘图像与背景、特效等进行组合,创造出更具个性和创意的形象。 通过游戏角色全身免扣PNG立绘,玩家可以更加直观地了解角色的服饰、装备、姿势等细节,从而更好地展示角色的个性和特点。立绘的精细细节和丰富表情也能够增加玩家对角色的情感共鸣,进一步提升游戏的沉浸感和可玩性。 在游戏角色全身免扣PNG立绘的基础上,玩家还可以通过自己对角色的创作和改编,打造出更加独特和个性化的形象。这种自由度和创造性可以激发玩家的想象力和创作力,使得游戏角色在玩家心目中的形象更加丰富多样。 总之,圣女战旗游戏角色全身免扣PNG立绘为玩家提供了更大的创作空间和表现力,帮助玩家更好地展示和赋予游戏角色个性和深度。这种立绘形式为游戏的美术效果和玩家体验增添了更多的亮点和魅力。 ### 回答2: 《圣女战旗》是一款受欢迎的游戏,角色们的立绘以全身免扣png格式呈现。PNG格式是一种支持透明背景的图片格式,因此在游戏中使用这种立绘可以更好地展示角色的细节和动态。 这些立绘是以圣女战旗游戏中各个角色的形象为基础绘制而成的。每个角色都经过精心设计和绘制,从头到脚的细节都被展现出来。这些立绘的像素化效果非常高,可以轻松适应不同的屏幕分辨率和游戏界面要求。 使用全身免扣png立绘的好处是,玩家可以将角色立绘放置在游戏画面的任何位置,而不必为背景的颜色和元素所限制。这样一来,角色立绘可以更加融入游戏场景,增强了游戏的沉浸感。 另外,全身免扣png立绘在制作海报和宣传材料时也非常实用。开发者可以使用这些立绘来制作精美的海报、广告和宣传画,吸引更多的玩家来体验游戏。 总的来说,圣女战旗游戏角色的全身免扣png立绘非常有助于增强游戏的画面效果和推广效果。这些立绘的高像素化和透明背景使其在游戏中具有更好的表现力和灵活性,为游戏玩家提供更好的游戏体验。 ### 回答3: 《圣女战旗》是一款富有创新的游戏,该游戏的角色立绘是以全身免扣png的形式呈现的。这种形式的立绘呈现方式,有着诸多优点。 首先,全身免扣png立绘可以完整地展现游戏角色的造型和细节。玩家可以清晰地看到角色的服饰、装备以及其他饰品等。这样一来,玩家可以更加直观地了解角色的形象和特点,增强了游戏的可玩性。 其次,全身免扣png立绘可以提供更大的自由度。由于该立绘形式将角色完整地呈现出来,游戏设计师可以更加自由地给予角色动作和表情,增加了角色的丰富性和活力。玩家在游戏中观看到的角色立绘将更加生动逼真。 再次,全身免扣png立绘方便制作和使用。这种形式的立绘可以方便地与游戏场景和其他元素进行组合。游戏开发人员可以根据需要调整立绘的大小和位置,使其完美地融入游戏界面。同时,该立绘可以独立于背景,方便进行替换和编辑,提高了游戏制作的效率和灵活性。 综上所述,圣女战旗游戏角色全身免扣png立绘具有展现细节、提供自由度和方便使用等优点。这种立绘形式为游戏增添了更多的乐趣和互动,使玩家能够更好地融入游戏世界中。
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值