• 请不要在回答技术问题时复制粘贴 AI 生成的内容
h3xz
V2EX  ›  程序员

c++对大量图片进行序列化和反序列化

  •  
  •   h3xz · Apr 10, 2024 · 3852 views
    This topic created in 938 days ago, the information mentioned may be changed or developed.
    工作中开发的软件有这样一个需求:
    程序用了某种算法对大量图片(约有 9 千多张,每张约 4M )进行了处理。我该怎么将这所有的图片以数组的形式序列化为一个文件夹,当从硬盘将这些图片读回内存时可以随机访问图片,以便用户第二次打开。
    34 replies  •  2024-04-11 15:48:26 +08:00
    feirisu
    feirisu
    Apr 10, 2024
    1
    没看懂
    wangtian2020
    wangtian2020
    Apr 10, 2024
    2
    不就是跟个系统自带的相册、或者说是图片查看器差不多吗。搞个缩略图差不多得了
    xtreme1
    xtreme1
    Apr 10, 2024
    3
    意思是图片在内存里什么样就在文件里什么样?
    存 PPM 呗
    I3tZ9NgHU44xmaA4
    I3tZ9NgHU44xmaA4
    Apr 10, 2024❤️1
    4
    9k 张图片也不多,我近千万张图片在电脑。
    将所有文件的名字存在一个文本文件里就行了,随机到那个图片的名字再读哪个图片出来,我还是用弱鸡 C#弄的。
    h3xz
    h3xz
    OP
    Apr 10, 2024
    5
    感谢大家的回复。我没有表达清楚问题的意思,我是希望将所有的图片能够序列化到一个文件中(不是文件夹),我保存的不单单只有图片,还有与图片相关的一系列的数据,编号等,因此我想请教有没有这样一种第三方库:能够以将图片,数据,编号,日期作为一个对象进行序列化,我起初使用的是 protobuf ,但是该库不能序列化太大的文件 。如果采用的是读取图片的名称,用户一旦修改了图片名,那么读取图片就会出错了。非常感谢大家的建议。
    xieym
    xieym
    Apr 10, 2024
    6
    sqlite?
    h3xz
    h3xz
    OP
    Apr 10, 2024
    7
    @xtreme1 我想的是每次都保存对象,这个对象包含了图片,编号,和一系列相关数据。
    hitmanx
    hitmanx
    Apr 10, 2024❤️1
    8
    看不出来这个用例里面,图片和普通的二进制文件对于序列化有什么区别?你把图片想象成一个普通的二进制文件不就行了。
    那么现在就是序列化一个 array 或者 map ,里面每个元素包含一些 metadata(number, string etc)和一个不定长的二进制文件。
    F7TsdQL45E0jmoiG
    F7TsdQL45E0jmoiG
    Apr 10, 2024
    9
    这不就是对象存储干的事儿嘛
    StrangerA
    StrangerA
    Apr 10, 2024
    10
    9k * 4M ,36 个 G 存入一个文件,还想瞬间读写?

    建议存缩略图进 sqlite
    jones2000
    jones2000
    Apr 10, 2024
    11
    内存数据库
    mxalbert1996
    mxalbert1996
    Apr 10, 2024 via Android❤️1
    12
    换个思路,直接把文件打包成一个不带压缩的 zip 文件。zip 文件是支持随机读取的。
    3dwelcome
    3dwelcome
    Apr 10, 2024
    13
    zip 文件可以,但是大小有一定限制,有 zip64 的变种,可以支持 4G 以上的大文件。
    picone
    picone
    Apr 10, 2024
    14
    记录 offset ,fseek 即可
    leonshaw
    leonshaw
    Apr 10, 2024
    15
    在文件上建文件系统,mount
    taygetus
    taygetus
    Apr 10, 2024
    16
    #include <boost/serialization/map.hpp>
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
    linauror
    linauror
    Apr 10, 2024
    17
    如果要存的数据不多,直接把这些数据给图片命名呢,比如 xxxx_yyyy_20240101235959.jpg
    shyrock
    shyrock
    Apr 10, 2024❤️3
    18
    建议直接说原始需求,而不是你分析之后想要的算法。。。
    shakeyo
    shakeyo
    Apr 10, 2024
    19
    简单点就 zip
    麻烦点就自己设计一个文件格式,类似|magicNumber|version|indexOffset|fileOffset|
    生成过程就是计算头,填充并依次将头、文件索引表、文件数据 1 ,文件数据 2 。。。。。写入到文件中
    edward1987
    edward1987
    Apr 10, 2024
    20
    确定需求是 [随机访问图片] 而不是 [随时访问图片] ? 怎么看着像是在做一个图文游戏,然后想用序列化的方式加密啊
    xytysingle
    xytysingle
    Apr 10, 2024
    21
    用 base64 编码图片为字符串,比如一行一个编号,日期,图片的 base64 字符串
    bertonzh
    bertonzh
    Apr 10, 2024
    22
    .img 文件
    knva
    knva
    Apr 10, 2024
    23
    还是实现个文件系统简单。
    kokutou
    kokutou
    Apr 10, 2024 via Android
    24
    啥都无所谓的话。。。直接丢数据库?
    feirisu
    feirisu
    Apr 10, 2024❤️1
    25
    大概懂了,就是游戏资源的打包方式呗,其设计目的就是不让用户修改,又能快速定位资源,格式也简单。

    但是单文件过大建议考虑分包。

    通常格式是:
    固定自定义格式头,包含多少个文件[int]等
    资源名长度[int]、资源名[char*]、资源尺寸[int]、资源内容[byte*]

    读取时可以直接打开文件,用文件句柄偏移的方式可以快速构建索引以及针对对应的偏移取出数据。
    GeruzoniAnsasu
    GeruzoniAnsasu
    Apr 10, 2024
    26
    数据库中存索引和 meta info ,图片文件一律改名成 ID ,完毕。

    IO 不够就把文件丢进分布式文件系统里从网络读
    mioktiar56
    mioktiar56
    Apr 10, 2024
    27
    我怀疑你是微信上找我的那个人

    内存映射即可解决
    feirisu
    feirisu
    Apr 10, 2024
    28
    就依照我#25 写的,可以直接让 chatgpt 给你封装一套打包加拆包的类。
    wxf666
    wxf666
    Apr 10, 2024❤️1
    29
    @h3xz 那就存 SQLite 数据库呗。。

    优点:

    - 单文件
    - 可随机读写
    - 依赖库只有几百 KB
    - 有原生 C/C++ 接口
    - 可存一系列数据(编号、日期、数据、图片文件本身、……),单个数据最大 2GB


    写了 10GB 共 2500 条数据(每条包含 4MB 图片及数据),
    再测试下,随机读取图片速度(测试前,已用 RamMap 清空系统文件缓存):

    - 机械盘:27 条数据/秒( 150 MB/s 顺序读取,0.65 MB/s 随机 4K 读取)
    - 内存盘:323 条数据/秒( 6754 MB/s 顺序读取,310 MB/s 随机 4K 读取,感觉明显没吃满 IO )
    rpWQTyfsAjMCKgPA
    rpWQTyfsAjMCKgPA
    Apr 11, 2024 via iPhone❤️1
    30
    @h3xz 谷歌的 protobuf 。你这个需求和深度学习里准备训练数据十分类似:都是要把图片和一些 meta 信息(标注)序列化到硬盘上方便 retrieval 。
    h3xz
    h3xz
    OP
    Apr 11, 2024
    31
    @feirisu 今天测试了一下,我存了 1000 张 4M/张 的图片到 SQLite 中,为什么显示 db 文件占了 11 个 G 呀
    h3xz
    h3xz
    OP
    Apr 11, 2024
    32
    @wxf666 今天测试了一下,我存了 1000 张 4M/张 的图片到 SQLite 中,为什么显示 db 文件占了 11 个 G 呀
    ma46
    ma46
    Apr 11, 2024
    33
    @h3xz 你是不是直接存了图片的矩阵数据, 因为你看到的文件大小其实是图像压缩编码后的大小
    wxf666
    wxf666
    Apr 11, 2024❤️1
    34
    @h3xz 不知道你是怎么存的。我写个示例,你按情况改了后,执行看看?


    1. 准备 SQLite 环境

    原因:
    ① 不想在这儿写 C/C++,太冗长。
    ② 后文的脚本,需要用到 dll 没有的,仅命令行版本才有的 readfile 函数。

    步骤:
    ① 打开 https://sqlite.org/download.html
    ② 找到 sqlite-tools-win-x64-3450200.zip (当前版本)并下载(若 Linux/MacOS 找对应平台的)
    ③ 解压,得到 sqlite3.exe


    2. 准备(存数据的) SQL 文件

    参考以下内容,按你自己情况更改后,用 UTF-8 编码,保存为 test.sql 。

    ```sql
    -- 把默认页大小 4KB 改为 64KB 。因为你大部分数据都很大,一次读取便加载更多数据,能提速
    PRAGMA page_size = 65536;

    CREATE TABLE image (
    id INTEGER PRIMARY KEY,
    -- 假设你通过名字来定位图片及其他数据。UNIQUE 既创建了索引,也保证名字唯一
    name TEXT NOT NULL UNIQUE,
    -- 注意,默认生成的时间,是 UTC 时间,比中国慢 8 个小时
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    extra_data JSON,
    data BLOB NOT NULL
    );

    BEGIN;
    -- 省略 id ,SQLite 则会自动填写为最大 ID + 1 。
    -- 单引号内的 \ 不用转义。若要表示 ',双写即可。如 'Kai''Sa.jpg'。
    -- 文件路径不要包含中文,因为 SQLite 会把 UTF8 字符串,原样调用系统 API ,然而 Windows 会以为是 GBK 编码。。
    -- 如果文件路径一定包含中文,请保证其它字符串(如 name 列)没有中文,然后 SQL 文件转为 GBK 编码。
    INSERT INTO image (name, data) VALUES ('aaa.jpg', readfile('C:\aaa.jpg'));
    INSERT INTO image (name, data) VALUES ('bbb.jpg', readfile('C:\bbb.jpg'));
    INSERT INTO image (name, extra_data, data) VALUES ('ccc.jpg', '{"width": 123, "height": 456}', readfile('C:\ccc.jpg'));
    COMMIT;

    -- 可选:碎片整理数据库文件,并去除冗余空间,达到瘦身紧实的效果。
    -- VACUUM;

    SELECT printf('写入了 %d 个文件,共 %d 字节。', COUNT(*), SUM(LENGTH(data))) FROM image;
    ```


    3. 执行

    ```shell
    sqlite3.exe images.db < test.sql
    ```
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   5499 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 102ms · UTC 02:03 · PVG 10:03 · LAX 18:03 · JFK 21:03
    ♥ Do have faith in what you're doing.