Python图片处理脚本,个人用于Unity图片处理

先介绍功能点

原图

原图.png

1.自动裁切掉透明像素(可对边缘透明度过滤)
处理后.png
2.自动裁切后充满填充到目标像素
image.png
image.png
3.不裁切自动缩放后填充到目标像素
image.png
4.将图片自动处理到etc2压缩支持的格式,即长和宽都是4的倍数
image.png
5.将图片自动处理到pvrtc压缩支持的格式,即长和宽都是2的n次幂(这里长宽都取最近,不强行处理成正方形)
处理前

处理后
6.将图片自动处理到pvrtc压缩支持的格式,即长和宽都是2的n次幂(这里强行处理为正方形)
处理前

处理后
import os
from PIL import Image

##########################################################
##未封装成类,需要请自行修改
##########################################################

def get_auto_crop_box(img,filter_alpha):
    '''
    删除一张图的空白元素,img为原图像,filterAlpha为四边Alpha的过滤强度0-255,返回 [裁切范围Box]
    '''
    if img.mode!='RGBA':
        raise AttributeError('非RBGA图像,没有Alpha通道~')
    if filter_alpha<0 or filter_alpha>=255:
        raise AttributeError('filter_alpha范围是[0,255)')
    w,h = img.size
    top_2_bottom_row = 0    #从上往下扫描得到行
    bottom_2_top_row = h    #从下网上扫描得到行
    left_2_right_col = 0    #从左往右扫描得到列
    right_2_left_col = w    #从右往左扫描得到列
    isDone = False
    for i in range(h):
        if isDone:
            break
        for j in range(w):
            if(img.getpixel((j,i))[3]>filter_alpha):
                isDone = True
                top_2_bottom_row = i
                break
    isDone = False
    for i in range(h-1,-1,-1):
        if isDone:
            break
        for j in range(w-1,-1,-1):
            if(img.getpixel((j,i))[3]>filter_alpha):
                isDone = True
                bottom_2_top_row = i
                break
    isDone = False
    for i in range(w):
        if isDone:
            break
        for j in range(h):
            if(img.getpixel((i,j))[3]>filter_alpha):
                isDone = True
                left_2_right_col = i
                break
    isDone = False
    for i in range(w-1,-1,-1):
        if isDone:
            break
        for j in range(h-1,-1,-1):
            if(img.getpixel((i,j))[3]>filter_alpha):
                isDone = True
                right_2_left_col = i
                break
    
    if top_2_bottom_row>bottom_2_top_row or left_2_right_col > right_2_left_col:
        raise AttributeError('检测到图像是纯透明图像~')

    return (left_2_right_col,top_2_bottom_row,right_2_left_col,bottom_2_top_row)

def get_auto_crop_box_image(img,filter_alpha):
    '''
    删除一张图的空白元素,img为原图像,filterAlpha为四边Alpha的过滤强度0-255.并返回 [新的Image]
    '''
    return img.crop(get_auto_crop_box(img,filter_alpha))

def get_auto_resize_box(img_w_h,resize_w_h):
    '''
    将图片本身根据长宽比匹配到需要缩放的尺寸,该尺寸是自身匹配目标尺寸进行无损缩放后的尺寸,返回该 [尺寸]
    PS:注意,这里的缩放指的是原图如果要匹配到指定目标尺寸,自身最终会无损缩放到的尺寸,并不会对边缘进行填充变成指定的resize_w_h大小,若要此变化,可再进一步get_img_copy_2_transparent_image操作
    '''
    if resize_w_h[0]<=0 or resize_w_h[1]<=0:
        raise AttributeError('无法将图像缩放到小于等于0')

    ratio_w = img_w_h[0]/resize_w_h[0]    #目标图像和需要缩放的尺寸的宽度比
    ratio_h = img_w_h[1]/resize_w_h[1]    #目标图像和需要缩放的尺寸的高度比
    img_new_w_h = img_w_h
    if ratio_w>ratio_h:
        #宽度比大于高度比,则以宽度为准去匹配需要缩放的宽度
        img_new_w_h = (resize_w_h[0],(int)(img_w_h[1]/ratio_w))
    else:
        #高度比大于宽度比,则以高度为准去匹配需要缩放的高度
        img_new_w_h = ((int)(img_w_h[0]/ratio_h),resize_w_h[1])
    return img_new_w_h   

def get_auto_resize_box_image_no_fill(img,resize_w_h):
    '''
    将图片本身根据长宽比匹配到需要缩放的尺寸,该尺寸是自身匹配目标尺寸进行无损缩放后的尺寸,并返回 [新的Image]
    PS:注意,这里的缩放指的是原图如果要匹配到指定目标尺寸,自身最终会无损缩放到的尺寸,并不会对边缘进行填充变成指定的resize_w_h大小,若要此变化,可再进一步get_img_copy_2_transparent_image操作
    '''
    return img.resize(get_auto_resize_box(img.size,resize_w_h))

def get_auto_resize_box_image_fill(img,resize_w_h):
    '''
    将图片本身根据长宽比匹配到需要缩放的尺寸,然后填充到resize_w_h尺寸中取,并返回 [新的Image]
    '''
    return get_img_copy_2_transparent_image(img.resize(get_auto_resize_box(img.size,resize_w_h)),resize_w_h)

def get_img_copy_2_transparent_image(img,resize_w_h):
    '''
    将图像填充到指定resize_w_h透明图像的中间,并返回 [新的Image]
    '''
    new_img = img
    if resize_w_h[0]<new_img.size[0] or resize_w_h[1]<new_img.size[1]:
        new_img = get_auto_resize_box_image_no_fill(img,resize_w_h)             
    newImage = Image.new('RGBA',resize_w_h)
    startPoint = (int((newImage.size[0]-new_img.size[0])/2),int((newImage.size[1]-new_img.size[1])/2))
    newImage.paste(new_img.copy(),startPoint)
    return newImage

def auto_resize_with_set_width(img,width):
    '''
    指定宽度让高度自动缩放,返回缩放后 [新的Image]
    '''
    if width<=0:
        raise AttributeError('width不能小于等于0~')
    r = img.size[0]/width
    new_height = int(img.size[1]/r)
    return img.resize((width,new_height))

def auto_resize_with_set_height(img,height):
    '''
    指定高度让宽度自动缩放,返回缩放后 [新的Image]
    '''
    if height<=0:
        raise AttributeError('height~')
    r = img.size[1]/height
    new_width = int(img.size[0]/r)
    return img.resize((new_width,height))

def get_auto_crop_and_resize_and_fill_image(img,resize_w_h,filter_alpha):
    '''
    自动裁切图片并指定缩放到目标尺寸,不拉伸,自动等比缩放后再填充到目标像素大小
    img为原图像
    resize_w_h为指定缩放尺寸
    filterAlpha为四边Alpha的过滤强度0-255
    返回 [新图像]
    '''
    return get_auto_resize_box_image_fill(get_auto_crop_box_image(img,filter_alpha),resize_w_h)

def deal_img_2_etc2_support(img):
    '''
    #将图片处理成etc2 压缩格式支持的大小,即长和宽必须都是4的倍数
    '''
    res_w = 4
    res_h = 4
    if img.size[0]>=4:
        modnum = img.size[0] % 4
        if modnum < 2:
            res_w = img.size[0] - modnum
        else:
            res_w = img.size[0] + (4 - modnum)

    if img.size[1]>=4:
        modnum = img.size[1] % 4
        if modnum < 2:
            res_h = img.size[1] - modnum
        else:
            res_h = img.size[1] + (4 - modnum)

    return get_auto_resize_box_image_fill(img,(res_w,res_h))
    
def deal_img_2_pvrtc_support(img):
    '''
    #将图片处理成pvrtc压缩格式支持的大小,即长和宽必须都是2的幂次方,这里不处理成为正方形,下面的方法处理成正方形
    '''
    res_w = 1
    res_h = 1
    min_2 = 0
    max_2 = 0  
    surplus = img.size[0]
    while(True):
        surplus = surplus - (2**max_2)
        if max_2 == 0:
            max_2 += 1
        else:
            min_2 += 1
            max_2 += 1

        if surplus <= 0:
            if abs((2**min_2)-img.size[0]) <= abs((2**max_2)-img.size[0]):
                res_w = 2**min_2
            else:
                res_w = 2**max_2
            break

    min_2 = 0
    max_2 = 0  
    surplus = img.size[1]
    while(True):
        surplus = surplus - (2**(max_2))
        if max_2 == 0:
            max_2 += 1
        else:
            min_2 += 1
            max_2 += 1

        if surplus <= 0:
            if abs((2**min_2)-img.size[1]) <= abs((2**max_2)-img.size[1]):
                res_h = (2**min_2)
            else:
                res_h = (2**max_2)
            break

    return get_auto_resize_box_image_fill(img,(res_w,res_h))

def deal_img_2_pvrtc_support_with_square(img):
    '''
    #将图片处理成pvrtc压缩格式支持的大小,即长和宽必须都是2的幂次方,一般避免拉伸处理成正方形,这里处理成正方形
    '''
    bigger_side = max(img.size[0],img.size[1])
    res_side = 1
    min_2 = 0
    max_2 = 0
    
    surplus = bigger_side
    while(True):
        surplus = surplus - 2**max_2
        if max_2 == 0:
            max_2 += 1
        else:
            min_2 += 1
            max_2 += 1

        if surplus <= 0:
            if abs((2**min_2)-bigger_side) <= abs((2**max_2)-bigger_side):
                res_side = 2**min_2
            else:
                res_side = 2**max_2
            break

    return get_auto_resize_box_image_fill(img,(res_side,res_side))

############################################################################
################################  分割线  ###################################
############################################################################

print('start')

lstfiles = os.listdir()
for i in lstfiles:
    if os.path.isfile(i):
        if os.path.splitext(i)[1].lower() in ('.png','.jpg','tga'): ##需要则补充
            img = Image.open(i)
            new_image = deal_img_2_pvrtc_support_with_square(img)
            new_image.save('new_'+i)

print('end')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容

  • 7.1 压缩图片 一、基础知识 1、图片的格式 jpg:最常见的图片格式。色彩还原度比较好,可以支持适当压缩后保持...
    AndroidMaster阅读 2,482评论 0 13
  • Using texturetool to Compress Textures - 使用纹理工具压缩纹理 iOS S...
    一川烟草i蓑衣阅读 1,119评论 0 0
  • 摘要:对android 上图片压缩,其实总结起来基本可以分为两类压缩:尺寸压缩和质量压缩, 尺寸压缩其实也可以理解...
    男爵是只猫丶阅读 8,760评论 2 14
  • 1、属性选择器:id选择器 # 通过id 来选择类名选择器 . 通过类名来选择属性选择器 ...
    Yuann阅读 1,614评论 0 7
  • 在第13章“高效绘图”中,我们研究了和Core Graphics绘图相关的性能问题,以及如何修复。和绘图性能相关紧...
    雪_晟阅读 622评论 0 0