V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
andybest
V2EX  ›  问与答

将一个黑白二值的图像存入数据库,有什么好建议?

  •  
  •   andybest · 2014-05-22 20:03:05 +08:00 · 3751 次点击
    这是一个创建于 3844 天前的主题,其中的信息可能已经有所发展或是发生改变。
    图片样例:
    只有黑白两色,图片(PNG格式)大小在200字节左右
    我将图片转换为0与1的文本,看是否能降低尺寸,结果该 文本.length 有1k+...
    除了直接将该图片以二进制形式存入数据库,还有没有什么更好的办法?
    第 1 条附言  ·  2014-05-22 21:21:09 +08:00
    PS:上面显示的那个图片因上传到微博转成JPG反而变大了
    原始图片:https://dl.dropboxusercontent.com/u/3858034/forum.png
    24 条回复    2014-05-23 17:49:11 +08:00
    czheo
        1
    czheo  
       2014-05-22 20:15:12 +08:00   ❤️ 1
    转16进制? 比如在bash里面输入
    printf '%x\n' "$((2#10101010100011101111101))"
    66CCFF
        2
    66CCFF  
       2014-05-22 20:16:52 +08:00 via Android   ❤️ 1
    二进制当然比文本小一些…
    还想优化的话,试试对binary压缩一下?把连续超过8位的1或者0计数起来。
    andybest
        3
    andybest  
    OP
       2014-05-22 20:17:03 +08:00
    @czheo 谢谢,转为0与1的文本长度为891:

    000000000000000111111111000000000
    000000000111000000000000000000000
    000111000000000111000111111000111
    000000111111000111111000111000000
    111111000111111000111000000111000
    111000111111000000000000000111000
    111111000000000000000111000111111
    000000000000111000000000111000000
    000000111000000000111000000000000
    111000000000111111111111000000111
    111000000111000111000000100000000
    000111000111000000100000000000111
    000111000111100000000111000111000
    000111100000000111000111000000111
    100000000111000111000000000000000
    111000000000111000000000000111000
    000000111000000000000111000000000
    111000000000001000000111000111000
    000000001000000111000111000000000
    001000000111000111000111000001000
    111000111111111111000001000111000
    111111111111000001000111000000000
    111111000001111000111000000111111
    000001111000111000000111111000001
    111000111000000111111111111000000
    000111000111111111111000000000111
    000111111111111000000000111000111

    这串东西即使转为 16 进制长度也不会低于图片本身的200字节吧?
    andybest
        4
    andybest  
    OP
       2014-05-22 20:19:31 +08:00
    @66CCFF 谢谢,也就是说,我直接把图片存数据库里就得了?没什么简单的方案可以节约更多空间了?
    vibbow
        5
    vibbow  
       2014-05-22 20:20:24 +08:00
    先gz一下再存呢
    andybest
        6
    andybest  
    OP
       2014-05-22 20:26:51 +08:00
    @vibbow 谢谢,这个图片 265 字节,gz 后 176 字节,
    除了更耗 CPU 的压缩方式外,还有能比176更低的方案吗?
    wingoo
        7
    wingoo  
       2014-05-22 20:26:52 +08:00   ❤️ 1
    01压缩应该比较好压吧
    写个算法,0/1大于1个的后面用数字标示,数字个数含有01用其他字符代替
    试试
    forexi
        8
    forexi  
       2014-05-22 20:27:55 +08:00
    图片的数量很大吗?
    如果不是很大的话,不用转换,直接把png图片的内容存入数据库,也才200字节左右。或者使用压缩的png(好像可以压缩),简单做。
    andybest
        9
    andybest  
    OP
       2014-05-22 20:32:22 +08:00
    @wingoo 谢谢,这个压缩方案对大量连续的黑白有效,但这种均匀散布的黑白图压缩后文本长度仍然远大于 200 字节
    forexi
        10
    forexi  
       2014-05-22 20:33:06 +08:00
    再说明下,不用读图片的像素,直接把png文件的内容存入数据库。回头从数据库读出来,再解析png。想数据量小的话,尝试压缩png格式。
    andybest
        11
    andybest  
    OP
       2014-05-22 20:34:40 +08:00
    @forexi 谢谢,现在我就是这样做的,PNG图片本身也已经压缩到最优了,但我想有没更好的储存方案来针对这种图片
    forexi
        12
    forexi  
       2014-05-22 20:37:44 +08:00
    @andybest 如果类似二维码的话。考虑用一位二进制代表一个色块?
    PhilCai
        13
    PhilCai  
       2014-05-22 20:39:57 +08:00
    纯外行提个不负责任的意见:那个二进制既然有一串01并且很多是连续的,干脆用类似压缩矩阵来存呢。。。
    andybest
        14
    andybest  
    OP
       2014-05-22 20:44:35 +08:00
    @forexi 不是二维码,类似迷宫图,有2px粗的条,也有1px的

    @PhilCai 关键是连续性不够,导致单纯去压缩0101010文本效果很不理想,比如文本:000111用33代表就可以了(只是个简单假设不是真正压缩算法),但010101这用这个算法去压缩就甚至会比之前的文本还大了
    czheo
        15
    czheo  
       2014-05-22 21:03:46 +08:00   ❤️ 1
    Sunyanzi
        16
    Sunyanzi  
       2014-05-22 21:15:48 +08:00   ❤️ 1
    图片样例看起来略奇怪 ... 大量的 3x3 像素的黑白格子 ... 感觉应该有规律可循 ...

    如果是类似二维码的图片可以直接用摘要算法搞定 ...

    如果是单纯的黑白图 ... 存成只有黑白两色的 gif 应该会小于存成 png ... 不确定 ...

    论算法的话 ...最容易想到的也是最通用的办法就是二值化然后八位一分组存成 ASCII ...

    以你的例子来看 ... 891 转化后的长度是 112 ... 小于原始图片的两百字节 ...

    如果二值化之后的结果有大量的连续值 ... 那么可以用如下的算法 ...

    最终结果的奇数位代表连续 0 的个数 ... 偶数位代表连续 1 的个数 ...

    如果有连续的 0 或者 1 超过 255 个 ... 后一位接 0x0 ... 然后继续分隔 ...

    这两种方式不一定哪种会更优 ... 要看具体的数据特征 ... 以 3F 贴出数据的前八行为例 ...

    二值化存储的结果是 33 个字节 ... 连续算法的结果是 43 字节 ...

    按照结果做出的 33x8 的图片不管存成什么格式都要上百字节 ...

    我的测试结果就是如此 ... 供参考 ...
    paulw54jrn
        17
    paulw54jrn  
       2014-05-22 21:16:52 +08:00   ❤️ 1
    楼主可以试下 bwt + 上面说的run-length-encoding.
    bwt可以把所有的相同字符归类在一起,然后再做run length encode就会有高效很多.

    http://en.wikipedia.org/wiki/Run-length_encoding
    http://en.wikipedia.org/wiki/Burrows%E2%80%93Wheeler_transform
    79bxh9b
        18
    79bxh9b  
       2014-05-22 21:18:16 +08:00   ❤️ 1
    如果自定义图片格式的话
    你这张图33x27,33*27/8,每个字节存8个像素,要112字节,再加上恢复成图像需要宽高信息,如果尺寸在256以下的数值1个字节就能表示,114字节是极限了。
    然后以二进制存数据库

    想省力的话换gif格式,gif支持黑白模式,150字节
    66CCFF
        19
    66CCFF  
       2014-05-22 21:28:52 +08:00   ❤️ 1
    @andybest 最省事而且靠谱的办法,把二进制gz一下丢数据库就好了。
    Tianpu
        20
    Tianpu  
       2014-05-22 22:20:02 +08:00
    @czheo 给出数据亲测可以做到129哇

    用尽ASCII表可能有隐患 不过可以再设计更好的方法 比如如果片段值是小于64的就再搞一次 感觉平均做到100之下应该可以的

    function encode($str){
    $r = '';
    $temp = str_split($str,7);
    $count = count($temp);
    for($i=0;$i<$count;$i++){
    if($i==$count-1){
    $r.= ' '.$temp[$i];
    }
    else{
    $r.= chr(base_convert($temp[$i],2,10));
    }
    }
    echo strlen($r);
    }
    yingluck
        21
    yingluck  
       2014-05-22 23:32:04 +08:00
    基本上PNG就是最优的数据压缩算法了。
    如果楼主还想提升并且图片尺寸是固定大小的话,可以将矩形黑白色块简化为一个个的像素,比如说将图片切分成3*2的黑白小块,白色的用1替换黑色的用0替换,然后再转为PNG存入数据库。
    xierch
        22
    xierch  
       2014-05-23 03:20:45 +08:00
    Fireworks 支持的几种格式挨个试了一下..
    wbmp 139 字节
    akfish
        23
    akfish  
       2014-05-23 04:52:17 +08:00
    图片本身怎么来的?
    如果生成算法是决定性的,为什么要存图?
    还不如只存生成参数,每次动态生成。
    msg7086
        24
    msg7086  
       2014-05-23 17:49:11 +08:00
    这个数量级下RLE不怎么划算啦,不如直接转成bitmap,114字节,或者直接用WBMP,149字节,或者就存200字节的png也不是很大问题吧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1834 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 16:30 · PVG 00:30 · LAX 08:30 · JFK 11:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.