您的浏览器过于古老 & 陈旧。为了更好的访问体验, 请 升级你的浏览器
二周 发布于2019年11月27日 14:38 最近更新于 2019年12月09日 10:33

原创 程序员如何给女朋友整理相册

7708 次浏览 读完需要≈ 14 分钟 ShellJava

内容目录

最近在帮女朋友整理相册,发现女生的照片多的你无法想象,多年来N部手机加在一起都可以达到几百G。先说说这些照片的特点:

  1. 命名凌乱,每个手机都有自己的命名规则,如果把所有手机的照片放在一个文件夹中备份,可能会存在命名冲突
  2. 格式不统一,比如 iOS 设备的.heic格式在 Windows 上不安装解码器无法打开
  3. 照片太大,一般在4-8MB之间,不便于传输和保存

那我们就来一个一个的解决这些问题。前面的文章介绍了如何读取EXIF信息,我们知道照片本身是携带着拍摄时间、拍摄的手机型号等信息的。所以我希望在文件名称中直接包含这些信息,然后根据文件名字就可以进行筛选。通过右键->属性->详细信息是可以看到这些信息的,比如:

照片详细信息.png
照片详细信息.png

文件命名举例.png
文件命名举例.png

照片重命名

package com.smile.test;

import com.drew.imaging.*;
import com.drew.metadata.*;
import com.drew.metadata.exif.*;
import com.drew.metadata.file.*;
import com.drew.metadata.jpeg.*;
import com.drew.metadata.png.*;
import org.junit.*;

import java.io.*;
import java.nio.file.*;
import java.text.*;
import java.util.*;

public class YiFanAlbum {
    /**
     * 第一步:重命名
     * 各种手机拍的照片,命名方式肯定不同
     * 这里我们用 横屏(H)或者竖屏(V)+
     * 拍照时间(如果经过处理的照片或者通过微信发送的照片是获取不到拍摄时间的,此时用修改时间)+
     * 手机型号(如果有)+
     * 编号(如果命名冲突)来命名
     */
    @Test
    public void rename() throws ImageProcessingException, IOException, MetadataException {
        // 相册地址
        final File path = new File("E:/album");
        // 目标相册地址
        final File destPath = new File("E:/dest-album");

        TimeZone timeZone = TimeZone.getDefault();
        SimpleDateFormat fileNameFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
        Map<String, Integer> countMap = new HashMap<String, Integer>();
        for (File imagePath : path.listFiles()) {
            Metadata metadata = ImageMetadataReader.readMetadata(imagePath);
            Optional<Directory> jpegDirectory = Optional.ofNullable(metadata.getFirstDirectoryOfType(JpegDirectory.class));
            Optional<Directory> pngDirectory = Optional.ofNullable(metadata.getFirstDirectoryOfType(PngDirectory.class));
            Optional<ExifSubIFDDirectory> exifSubIFDDirectory = Optional.ofNullable(metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class));
            FileSystemDirectory fileSystemDirectory = metadata.getFirstDirectoryOfType(FileSystemDirectory.class);
            Optional<ExifIFD0Directory> exifIFD0Directory = Optional.ofNullable(metadata.getFirstDirectoryOfType(ExifIFD0Directory.class));
            // 图片宽度
            long w = jpegDirectory.orElseGet(() -> pngDirectory.get()).getLong(JpegDirectory.TAG_IMAGE_WIDTH);
            // 图片高度
            long h = jpegDirectory.orElseGet(() -> pngDirectory.get()).getLong(JpegDirectory.TAG_IMAGE_HEIGHT);
            // 拍摄时间
            Optional<Date> originalDate = exifSubIFDDirectory.map(x -> x.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, timeZone));
            // 修改时间
            Date modifiedDate = fileSystemDirectory.getDate(FileSystemDirectory.TAG_FILE_MODIFIED_DATE, timeZone);
            StringBuilder sb = new StringBuilder();
            sb.append(w > h ? 'W' : 'H').append(fileNameFormat.format(originalDate.orElse(modifiedDate)));
            // 手机型号
            exifIFD0Directory.map(x -> x.getString(ExifIFD0Directory.TAG_MAKE)).ifPresent(x -> sb.append('_').append(x));
            String baseName = sb.toString();
            Integer count = countMap.get(baseName);
            if (count == null) {
                count = 0;
            } else {
                count++;
                sb.append('_').append(count);
            }
            countMap.put(baseName, count);
            String fileName = imagePath.getName();
            // 文件后缀名
            sb.append(fileName.substring(fileName.lastIndexOf(".")));
            File newFile = new File(destPath, sb.toString());
            // copy到新的目录,不改变原来的文件
            Files.copy(imagePath.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }
    }
}

修复后缀

有的用jpg作为后缀,有的用jpeg做后缀,作为程序员的我们,肯定不能接受这种凌乱。这里就用shell命令直接解决吧,多快好省

# cd 到指定的目录然,然后批量把jpeg后缀替换为jpg后缀
$ for i in *.jpeg;do mv "$i" "${i%.jpeg}.jpg" ;done

格式转换

heic转jpg
# 安装heic转换工具
$ sudo apt-get install libheif-examples
# 执行转换
$ for file in *.heic; do heif-convert $file ${file/%.heic/.jpg}; done
# 删除heic文件
$ rm *.heic
png转jpg
# 安装imagemagick
$ sudo apt-get install imagemagick
# 执行转换
$ for file in *.png; do convert $file ${file%%.*}.jpg; done
# 删除png文件
$ rm *.png

压缩图片

jpegoptim是Linux上的压缩利器,提供无损优化(基于优化霍夫曼表)和基于设置最大品质因数的“有损”优化。

# 安装jpegoptim
$ sudo apt-get install jpegoptim
# 执行默认的压缩比(90%),图片效果很好,但是压缩率比较低
$  jpegoptim ./*.jpg
# 指定压缩比(80%)
$ jpegoptim -m80 ./*.jpg

图片打包

兄弟们,千万别只知道打包成zip或者rar,如果你的文件全部是图片或者视频,进行zip压缩或者rar压缩是毫无效果的,完全不能减小文件的大小,只能白白浪费计算机性能,增加压缩和解压的时间。所以对于这类文件,建议直接用tar命令进行打包,速度非常快。

tar -cf dest-album.tar dest-album

图片冲印

冲印照片是有尺寸要求的,这里是一个常用的尺寸列表,我们在送给照相馆冲印之前,最好按照这里的尺寸裁剪好,不然就会出现只打印一半或者留白的情况。同时你提交的照片的像素不能太小,较小像素(用美图秀秀等软件P过的照片像素明显偏低,一般都是不符合要求的)的照片会导致冲印模糊,这里提供一个命令,批量修改照片的像素。

尺寸像素要求.jpeg
尺寸像素要求.jpeg
for i in H*;do convert -resize 1800x1350 $i ${i} ;done
for i in V*;do convert -resize 1350x1800 $i ${i} ;done

好了,就到这里,最后再说一句:程序员都是有女朋友的好吗(^▽^)

  • CodePlayer技术交流群1
  • CodePlayer技术交流群2

1 条评论

Ready · 7个月前

感觉你就是来炫耀女朋友的~

0 0 0

撰写评论