戊辰人博客

青,取之于蓝而青于蓝;冰,水为之而寒于水。

Python之利用PIL批量给图片添加文字

日期:2017年4月11日 作者: 分类:编程 阅读:190

因为略懂Photoshop,所以接到一个任务:将公司所有的产品图片整理出来,并在图片中写明产品的品牌和型号,然后分类放在iPad中方便给客户展示。

WTF,几千张图片,用PS一个个打开添加文字,这会把人弄疯的,作为一个懒人,做这种大量机械性的重复工作显然不是我的追求,于是就想到用程序自动实现。

一、使用Python和PIL图片处理库

思路:所有图片的文件名都是以品牌+型号的方式命名,所以先用python读取当前目录下所有文件,得到文件名后我们就可以得到当前图片的品牌型号字符串,然后根据图片像素大小自动判断合适的字体大小,再利用PIL库给原图片加上文字水印(品牌型号),然后将处理后的图片保存在当前目录下的new子文件夹。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import os
import sys

import PIL
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# 设置文字水印
def set_water_text(imagefile, text):

    img = Image.open(imagefile)
    (img_x, img_y) = img.size
    
    # 文字字体像素高度为图片高度的 1/20
    ttfont = ImageFont.truetype('/usr/share/fonts/noto/NotoSansCJK-Regular.ttc', int(img_y/20))

    draw = ImageDraw.Draw(img)
    draw.text((int(img_x/20), img_y - int((img_y*1.3)/20)), text, (0,0,0), font=ttfont)

    newdir = "new"
    if not os.path.exists(newdir):
        os.mkdir(newdir)

    img.save(newdir + '/' + text + '.jpg', 'jpeg')

if __name__ == '__main__':
    files = os.listdir(os.getcwd())
    for filename in files:
        if 'jpg' == filename.split('.')[-1].lower() or 'png' == filename.split('.')[-1].lower():
            set_water_text(filename, filename.split('.')[0])
            print(filename)

阅读全文…

在Linux中让echo命令显示带颜色的字

日期:2016年3月2日 作者: 分类:编程 阅读:347

echo -e “\033[字背景颜色;文字颜色m字符串\033[0m”

例如:

echo -e “\033[41;37m TonyZhang \033[0m”

其中41的位置代表底色, 37的位置是代表字的颜色

注:

1、字背景颜色和文字颜色之间是英文的“”””

2、文字颜色后面有个m

3、字符串前后可以没有空格,如果有的话,输出也是同样有空格

下面看几个例子:

echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
 
echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"
echo -e "\033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[0m"
echo -e "\033[44;37m 蓝底白字 \033[0m"
echo -e "\033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[0m"
echo -e "\033[47;30m 白底黑字 \033[0m"

控制选项说明 :

\33[0m 关闭所有属性
\33[1m 设置高亮度
\33[4m 下划线
\33[5m 闪烁
\33[7m 反显
\33[8m 消隐
\33[30m -- \33[37m 设置前景色
\33[40m -- \33[47m 设置背景色
\33[nA 光标上移n行
\33[nB 光标下移n行
\33[nC 光标右移n行
\33[nD 光标左移n行
\33[y;xH设置光标位置
\33[2J 清屏
\33[K 清除从光标到行尾的内容
\33[s 保存光标位置
\33[u 恢复光标位置
\33[?25l 隐藏光标
\33[?25h 显示光标

阅读全文…

Python之PIL图片处理

日期:2015年12月28日 作者: 分类:编程 阅读:951

由于工作原因需要将大量jpg图片文件缩放成宽度为1000像素的图片上传,最初是用图片处理工具进行一张张处理,但效率十分低下,于是就自己动手用Python实现一个批量处理工具。

PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。

在Debian/Ubuntu Linux下直接通过apt安装:

sudo apt-get install python-imaging

为了方便不同宽度的需求,程序要支持指定宽度,缩放后的图片保存在当前目录下的子目录中。程序代码如下

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Filename: resize-img.py
# require: python-pil python-imaging

import os
import sys
import Image

# 重新设置图片大小
def resize_img(width, filename):
    newdir = "size_" + str(width)
    if not os.path.exists(newdir):
        os.mkdir(newdir)
    img = Image.open(filename)
    (x, y) = img.size

    x_s = width
    y_s = y * x_s / x

    out = img.resize((x_s, y_s), Image.ANTIALIAS)
    out.save(newdir + '/' + filename, 'jpeg');


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print 'usage: ' + sys.argv[0] + " width(px)"
        print 'e.g. : ' + sys.argv[0] + " 1000"
        sys.exit(1)

    files = os.listdir(os.getcwd())
    for filename in files:
        if 'jpg' == filename.split('.')[-1].lower():
            resize_img(int(sys.argv[1]), filename)
            print 'resize ' + filename + ' succes'

阅读全文…

WordPress上传图片或附件自动重命名的实现方法

日期:2015年11月20日 作者: 分类:编程 阅读:1,068

在使用wordpress发布文章时,经常用到的一个功能就是添加媒体,比如在文章中添加图片或其他格式的附件。那么,问题来了,wordpress在英语环境中使用,文件名一般都是英文,但是对于中文用户来说,经常会碰到文件名是中文的情况。尽管直接上传一个中文名的文件到网站上是没有问题的,但是我们更希望这个文件能在我们上传的时候自动变成英文或数字。

本文将会介绍两个格式的文件命名方法:根据上传的时间命名,如20140101112233.xxx(表示2014年1月1日11时22分33秒上传的,xxx表示文件类型后缀);另一种是将文件名通过md5转码后得到的一个32位字符串,如21232f297a57a5a743894a0e4a801fc3.xxx(原始文件名为admin.xxx)。在自定义的wordpress主题或官方自带的主题中都可以使用这个方法来实现上传文件重命名。

原理

wordpress之所以强大就是因为它给开发者提供了一系列API,使其变得非常灵活。wordpress有一个Filter Functions(过滤器函数):add_filter,使用这个函数来操作wp_handle_upload_prefilter就能实现重命名的功能。

wp_handle_upload_prefilter可以参看wordpress官方文档的说明:

根据上传时间重命名文件

通常情况下,我们每次上传文件的时间都是不同的,即使是批量上传的情况下,也几乎不会出现同一时刻上传了多张图片文件的情况。所以这个方法几乎不会出现重名的文件。

这里需要用到php中的date()函数,完整的代码如下:

add_filter('wp_handle_upload_prefilter', 'custom_upload_filter' );
function custom_upload_filter( $file ){
	$info = pathinfo($file['name']);
	$ext = $info['extension'];
	$filedate = date('YmdHis').rand(10,99);//为了避免时间重复,再加一段2位的随机数
	$file['name'] = $filedate.'.'.$ext;
    return $file;
}

阅读全文…

Python解决生活问题之闹钟程序的实现

日期:2015年9月18日 作者: 分类:编程 阅读:755

昨天下班回家忘了带手机充电器,手机熄火没闹钟了,可现实是迟到30分钟以内要罚100RMB,超过30分钟算旷工要扣除3天工资,想想这代价,好吧,还是自己动手写一个闹钟程序吧!

系统环境: Linux Mint Debian Edition 2

软件需求:1. mpg123 (用来播放闹钟铃声)   2. python2.7.x(开发语言环境,本系统已经自带)

1.安装字符模式下的播放器mpg123

sudo apt-get install mpg123

2.编写闹钟程序代码

#!/usr/bin/env python
# -*- coding: utf8 -*-
import time
import os
import sys
from subprocess import call

# When get up ?
h = 7
m = 40

loop = True
while(loop):
    # now
    dt = list(time.localtime())
    hour = dt[3]
    minute = dt[4]

    # get up ?
    if h == hour and m == minute:
        return_code = call("/usr/bin/mpg123 我只在乎你.mp3", shell=True)
        loop = False

    # display current time
    timestr = "%04d-%02d-%02d %02d:%02d:%02d\r" \
            % (dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
    sys.stdout.write(timestr)
    sys.stdout.flush()
    time.sleep(1)
    # end

阅读全文…

C++学习复习笔记05 – 构造函数重载时的写法

日期:2015年8月5日 作者: 分类:编程 阅读:514

在C++类中进行构造函数重载时,有几种不同的简洁的写法。

下面先演示可读性最好的也是初学时常用的写法一:

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    string name;
    int age;

public:
    Person()
    {
        cout << "Person()" << endl;
    }
    // 构造函数一经重写,系统默认的无参数的将不复存在,若要使用得写出来
    Person(string name, int age)
    {
        this->name = name;
        this->age = age;
        cout << "Person(string name, int age)" << endl;
    }
};

int main()
{
    Person wuxie;
    Person xiaoge("张起灵", 22);

    return 0;
}

阅读全文…

C++学习复习笔记04 – 函数重载

日期:2015年8月5日 作者: 分类:编程 阅读:475

重载函数是函数的一种特殊情况,为方便使用,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个运算符完成不同的运算功能。这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。

知识要点:

1) 独立函数重载

2) 类中非构造函数重载

3) 类中构造函数重载

4) 析构函数不能重载,因为系统自动调用,无法传递参数.

 

代码示例:

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    string name;
    int age;

public:
    /* 类中构造函数重载 */
    Person()
    {
        cout << "默认调用原始构造函数" << endl;                         
    }     
    // 构造函数一经重写,系统默认的无参数的将不复存在,若要使用得写出来     
    Person(string name, int age)     
    {         
        this->name = name;
        this->age = age;
        cout << this->name << "调用重载的构造函数" << endl;
    }

    /* 类中非构造函数重载 */
    void display()
    {
        cout << "-----> " << this->name << " : " << this->age << endl;
    }
    void display(string msg)
    {
        cout << msg << endl;
    }
};

/* 独立函数重载 */
void run()
{
    cout << "快跑!!!" << endl;
}
void run(Person p)
{
    cout << p.name << "快跑!!!" << endl;
}

int main()
{
    Person wuxie;
    wuxie.name = "吴邪";
    wuxie.age = 20;
    cout << "-----------" << endl;

    Person xiaoge("小哥", 22);
    cout << "-----------" << endl;
    cout << endl;

    run();
    cout << "-----------" << endl;
    run(wuxie);
    cout << "-----------" << endl;
    cout << endl;

    xiaoge.display();
    xiaoge.display("小哥叫闷油瓶");

    return 0;
}

阅读全文…

C++学习复习笔记03 – 析构函数

日期:2015年7月17日 作者: 分类:编程 阅读:448

析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。

析构函数的知识点:

1. 函数名为取反符~加上类名,例如~stud( );

2. 无参数无返回值;

3. 在对象脱离作用域时,如程序退出、函数调用完成退出时,析构函数会自动调用;

4. 只能有一个析构函数;

 

由于自动调用,我们就可以在析构函数中做清理类工作,如释放堆中申请的内存。

 

代码实例:

#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    Person()
    {
        cout << "创建类:构造函数Person()自动执行了" << endl;
    }
    ~Person()
    {
        cout << "结束类:析构函数~Person()自动执行了" << endl;
    }
};

int main()
{
    Person p1;
    cout << "------------------------------" << endl;
    return 0;
    //此处 p1 将脱离作用域,析构函数将发生作用
}

阅读全文…

C++学习复习笔记02 – 构造函数

日期:2015年7月6日 作者: 分类:编程 阅读:467

构造函数无返回值,函数名和类名相同,构造函数仅仅只是实现自动调用,并无特别。

语法与使用:

#include <iostream>
#include <string>
using namespace std;

class Person
{
private:
    string name;
public:
    //构造函数声明方法:类名(实参表){}
    Person(string name)
    {
        //注意:this->name是类中私有变量,name是函数传递进来参数
        this->name = name;
    }

    void who_am_i()
    {
        cout << this->name << endl;
    }
};

int main()
{
    //使用:类名 对象名(实参表);
    Person p1("吴邪");

    p1.who_am_i();
    return 0;
}

阅读全文…

C++学习复习笔记01 – 类的创建与使用

日期:2015年7月6日 作者: 分类:编程 阅读:378

说明:本系列只展示C++中一些关键语法最直观的用法,对于细节不做复述,因为有很多经典的书籍上有详细的解释;另外,学习一门技术,不能只看视频或者学习别人的重点笔记,书本还是不可少的,它不仅可以从整体上对技术的学习路线进行一个概括,同时还能作为一本参考手册进行使用,所以,如果打算学习一门技术,买一本书是必要的,几十块的投资也是值得的。

 

类的声明:

class 类名
{
访问类型:
    成员变量或成员方法;构造函数;析构函数;
}; // 结束的分号";"千万不要忘记,初学时很容易忘掉的。

类的使用:类名 实例名;

举例:

#include <iostream>
// 不要问下面是什么意思,初学时记住要这样写就行,会用后再去翻书查资料。
using namespace std;

// 声明一个名为Code的类
class Code
{
// 访问类型为public,即公有类型,可以不写,默认为private类型
public:
    // 声明类Code的成员方法
    void geass()
    {
        cout << "有没有一首歌会让你想起我!!!" << endl;
    }
};

int main()
{
    Code p; // 实例化Code类,实例为p
    p.geass();
    return 0;
}

阅读全文…