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

2019-09-17  本文已影响0人  hh5460

先介绍功能点

原图

原图.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')
上一篇下一篇

猜你喜欢

热点阅读