V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
edis0n0
V2EX  ›  程序员

jpg 能做到无损合并吗?一个网页游戏每个场景背景图都是左右半边各一张 jpg 拼起来的,我想无损拼接但不想保存成 png,有可能实现吗?

  •  1
     
  •   edis0n0 · 2023-03-06 21:55:10 +08:00 · 3351 次点击
    这是一个创建于 657 天前的主题,其中的信息可能已经有所发展或是发生改变。
    31 条回复    2023-03-08 09:54:33 +08:00
    Mithril
        1
    Mithril  
       2023-03-06 22:03:25 +08:00
    什么叫“无损拼接”?

    你能看见图的时候,jpg 已经还原成像素矩阵了,该损的也已经损完了。

    不考虑缩放的话,你直接截个图都可以。
    sakura6264
        2
    sakura6264  
       2023-03-06 22:11:32 +08:00
    大概不能。jpeg 压缩时应该是用了 DCT 的,这东西好像没法做拼接。
    话说你都用 jpeg 这种有损压缩了还考虑什么无损拼接有意思吗..
    edis0n0
        3
    edis0n0  
    OP
       2023-03-06 22:19:14 +08:00
    @sakura6264 #2 用 jpg 是因为只能搞到 jpg ,收藏用不想有画质损失,如果转成 png 有点浪费空间
    zhangberry
        4
    zhangberry  
       2023-03-06 22:19:21 +08:00 via Android
    读到内存中,转为矩阵,然后相加,再输出。
    sakura6264
        5
    sakura6264  
       2023-03-06 22:30:06 +08:00
    @edis0n0 只能搞到 jpeg 就代表已经有损失了,后续的所谓不想有画质损失都基本免谈。
    到头来就是你能不能接受的问题,唯一的方法就是合并之后再保存为 jpeg ,压缩度开低点,之后安慰自己已经无损了。
    jpeg 压缩时候记得是分析整张图的频率信息,丢弃高频项,所以没法直接合并。
    更简单的方法就是存两张图...
    favourstreet
        6
    favourstreet  
       2023-03-06 23:06:31 +08:00 via Android   ❤️ 2
    楼上好像都没理解楼主的需求啊,楼主是想避免二次压制。让合并的图像素级对应原图是可行的,jpg 量化系数和原图一致就成。网上大概有摆弄 jpeg 的现成工具,实在没有的话,用 libjpeg 自己写一个吧
    BeautifulSoap
        7
    BeautifulSoap  
       2023-03-06 23:19:56 +08:00   ❤️ 1
    楼主的意思应该是解码 jpg 之后又重新编码为 jpg 是不是会有画质损失。如果次数很少的话损失应该没多大的。但是需要重复好多次的话就会有较为明显的画质损失了(几十上百次

    贴吧各种包浆的表情包就是这么来的
    mikewang
        8
    mikewang  
       2023-03-06 23:45:03 +08:00   ❤️ 7
    写过 JPEG 编码器,对 JPEG 略知一二。
    理论上两张 JPEG 是存在完全无损拼接的可能性的,但是条件比较苛刻:
    1. 长宽像素是 8 的整数倍( YUV422 采样的情况下应该是要 16 的整数倍)
    2. 两张 JPEG 有着相同的 Huffman 表和量化表
    3. (暂时没想到,可能还有)

    总之很苛刻,如果两张 JPEG 压缩的参数不一样(尤其是量化表,用于控制有损压缩效果),拼接只能有损处理。
    所以 JPEG 无损裁剪的工具很常见(单个文件只有一种参数设定),而无损拼接的几乎没有。
    edis0n0
        9
    edis0n0  
    OP
       2023-03-07 01:01:08 +08:00
    @favourstreet #6 对,就是这个意思
    @mikewang #8 第一个条件就满足不了,看来是不行
    NoOneNoBody
        10
    NoOneNoBody  
       2023-03-07 01:30:12 +08:00
    import cv2, numpy
    cvim1 = cv2.imread(jpg1)
    cvim2 = cv2.imread(jpg2)
    h,w = cvim1.shape[:2]
    cvim2=cv2.resize(cvim2, (w, h), interpolation=inter)
    merge = numpy.hstack([cvim1, cvim2])
    ...
    edis0n0
        11
    edis0n0  
    OP
       2023-03-07 01:31:23 +08:00
    @NoOneNoBody #10 这样导出 jpg 像素就变了
    NoOneNoBody
        12
    NoOneNoBody  
       2023-03-07 01:36:07 +08:00
    @edis0n0 #11
    你自己改啊,我又不知道你的具体场景如何
    而且搞不清你说的“像素就变了”是什么意思,拼接后还要像素尺寸不变么?
    msg7086
        13
    msg7086  
       2023-03-07 04:32:33 +08:00
    @NoOneNoBody 人家要求合并 jpg 使合并后的文件包含合并后的图片。
    你这代码一开始就用 imread 把 jpg 解码成像素矩阵了,完全离题了。
    bbroot
        14
    bbroot  
       2023-03-07 07:48:26 +08:00 via iPhone
    你们有没有过度理解了…楼主不就是要把俩张照片拼在一起么…随随便便 ps 就是 Photoshop 一下就好
    krixaar
        15
    krixaar  
       2023-03-07 08:33:52 +08:00
    @bbroot #14 需求是避免二次压缩,但凡你把 JPG 打开成图片就输了
    orangie
        16
    orangie  
       2023-03-07 09:11:13 +08:00   ❤️ 3
    针对这种为需求,应该用一种伪实现,比如设计一个后缀名.j2p ,其本质是一个 zip 包,要求把两张 jpg 按照 1 ,2 明明压缩成 zip 并更改后缀伪.j2p ,在开发一个看图软件专门自动完成解压 j2p 、在显示 jpg 图片的时候自动把两张放在一起显示。反正都是自欺欺人,不如做全套,指不定还能忽悠点外行人。
    tool2d
        17
    tool2d  
       2023-03-07 09:37:17 +08:00
    可以转换成 jpeg2000 ,文件格式有提供无损压缩和无损拼接。因为不是 8x8 的 DCT ,可以随意限定块的大小,无所谓第一条图片大小的限制。

    jpeg 应该是很古老的格式,现在手机上都被 webp 淘汰了。
    sharpy
        18
    sharpy  
       2023-03-07 09:39:35 +08:00
    把解码后的数据用一些格式无损压缩呗
    duke807
        19
    duke807  
       2023-03-07 09:47:45 +08:00 via Android   ❤️ 1
    @orangie
    这个实现可不是什么伪实现,它很好,不过不应该叫 j2p 且只支持两张图,应该叫 ipk (image package),支持超多图片,且不限图片种类。

    很多行业应用可以用,譬如大桥航拍检测表面裂痕,会产生很多张高清图片,有拼接的需求。

    加载可以做成缩略图展示,放大后再高清展示需要显示的一小部分图片,另外软件提供接口,可以根据传入座标和框选范围,返回拼接后的高清图。
    lonewolfakela
        20
    lonewolfakela  
       2023-03-07 09:52:12 +08:00
    先讨论一下为啥不想存成 png 吧……这图得是有多大,才会觉得 png 占用空间太大了不合适呢……
    lambdaq
        21
    lambdaq  
       2023-03-07 10:19:59 +08:00
    laqow
        22
    laqow  
       2023-03-07 11:01:53 +08:00
    可能可以存 TIF 然后把两个图作为两个 tile ,应该自己撸一下代码可以不需要重新压缩,类似 @duke807 的思路
    ysy950803
        23
    ysy950803  
       2023-03-07 11:06:55 +08:00
    楼主是开发这个网页游戏的需求还是只是玩家想存这个场景图片而已?
    libook
        24
    libook  
       2023-03-07 11:16:53 +08:00
    首先,你所能拿到的 jpg 极大概率是已经被压缩过的,需要考虑此时再追求像素级别的一一对应是否有意义,是否能接受极小的像素差异的再次压缩。

    其次,你可以将两张图片分别转成像素矩阵,然后拼到一起,然后生成一张未压缩的图。关键是看你怎么输出,如果你用常规输出 jpg 的方式,为了节省空间就必须再进行压缩,否则就跟 png 一样了,此时接缝附近的像素极大可能会被重新调整,虽然肉眼可能看不出来差别。
    swordmaster
        25
    swordmaster  
       2023-03-07 12:02:56 +08:00
    不想保存成 png 就把 jpg 保存成 webp ,体积更小质量更高
    digimoon
        26
    digimoon  
       2023-03-07 12:42:59 +08:00
    我也想知道解决方法,类似的还有两个同编码的视频但是编码参数不一样,怎么拼接起来还能正常播放
    NoOneNoBody
        27
    NoOneNoBody  
       2023-03-07 12:50:05 +08:00
    @msg7086 #13
    中文博大精深,OP 说的“合并”究竟指的是打包、拼接、还是仅仅并排显示?
    jpg 是压缩格式,要得到图片内容什么软件都要解码,难道讨论的是另外的格式
    只有 bmp 这类直接像素记录到字节的格式,才能按字节合并
    Huelse
        28
    Huelse  
       2023-03-07 13:10:37 +08:00
    是否可以不对图片做任何处理,只是在最终的显示上拼接呢?就像前端多个 img 标签一样,放大缩小还是定位都很容易。
    msg7086
        29
    msg7086  
       2023-03-08 06:41:52 +08:00
    @NoOneNoBody 「要得到图片内容什么软件都要解码」
    就是要在不解码的情况下把图片并排显示。
    NoOneNoBody
        30
    NoOneNoBody  
       2023-03-08 08:20:35 +08:00
    @msg7086 #29
    绕了一个大圈
    并排显示还不简单,html img 支持指定尺寸,设成最底 layer ,固定位置,就相当于背景了,老早就能做到,不过我太久没接触,现在语法怎么写就不清楚了,你可以搜搜“双图背景”或“多背景图”
    其他 GUI 软件的话也是可以缩放到等尺寸并排的,原理都一样是设成最底层 layer 并固定
    msg7086
        31
    msg7086  
       2023-03-08 09:54:33 +08:00
    @NoOneNoBody 原文是说保存到一个 jpg 里。并排显示是为了给你解释「合并」的意思,又不是说 OP 只需要并排显示就完事了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2669 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 15:08 · PVG 23:08 · LAX 07:08 · JFK 10:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.