iOS 隐形水印之 LSB 实现

发表于 3年以前  | 总阅读数:2104 次

在音视频的领域里,其涵盖的知识点繁多,学习方向也很多。而本篇就是一篇比较入门的文章它简单地介绍如何在 iOS 上读取图片 RGB 数据,并通过修改最后一位 bit 来记录数字水印的信息下面就介绍《隐形水印之 iOS 实现》 欢迎阅读

技术背景

本文实现的两个技术点

水 印

水印是经常出现在图片 & 视频等多媒体文件上是一种很常见的元素,它一般以单一的图片或者文字的形式显示在一个角落。

它主要用于声明版权 & 防盗,以及查看来源等。

而我们千帆直播在主播直播后,我们的后端会为生成的 点播 & 回放 打上「千帆直播」水印,如下图的右上角:

这种水印是可见的,添加水印的方式可以是直接将水印图片的原数据memcpy 到载体图片原数据上(这里只是简单描述啦,对齐这些各位自己了解下)。还有可以使用第三方库,如 ffmpeg等。

L S B

英文 least significant bit,中文译最低有效位。

用个例子来描述下,我们知道一个数字,如11,把它转换为二进制的话就是 0000 1011,取最右边的 1 即为最低位。

而本文是针对图片的,图片的原数据构成是 RBG,那我们的操作就是:

(255, 255, 255) -取255-> 1111 1111 -> 把最后一位(1 => 0) -> 1111 1110 -放回-> (254, 255, 255)

这也是本文实现的核心。

而上面的操作会让原本的白色在 R值 上变小,然后再转换回颜色上,人眼是很难看出修改之后与之前的差别。

因此我们这样的修改对原本的影响是很小的。这就是我们通过获取 LSB,修改它来实现本次技术点。

数字水印

结合我们上面说的两个技术点,就是我们的实现了。

这里介绍数字水印,一种不易被发现的水印,也可以叫它,隐形水印。顾名思义,它不会像一般的水印一样显示在图片 & 视频帧上,而是通过其他技术原理将信息附带在载体上,最后通过反计算来获取信息内容。

数字水印的实现其实不止 LSB,还有其他改进的 LSB,或者其他算法,本文使用 标准LSB 来实现。但算法的大致都是建立在对原数据的修改不会在视觉上被察觉,将信息加入到原数据里面,有点像藏头诗。

通过以上大概了解原理 & 技术背景之后,本篇将着重使用 标准的LSB 来为 iOS 的截图上添加隐形水印 & 获取隐形水印内容。

应用场景

在Demo App上通过系统的截图后,将已经加入隐形水印的 App 截图展示,通过直接分享到QQ或者保存到相册,再由相册分享到QQ,然后客服获取到图片之后将图片保存或者直接复制,转发给处理人员。

然后通过相应的工具或者App将图片的隐形水印信息读取出来。

至于信息内容,可以是当时用户操作App的点击行为,或者部分接口的响应结果,从而来协助定位、追踪问题,等等。

QFImageMaskMan

这里的是整个Demo & Demo的操作展示,我在iPhone截图上将一首诗加入进去,然后分享出去或者保存本地。

QFImageMaskDemo[1]见文末

实 现

static let markBin: [QFLSBMarkBin] = [.key, .lengthBit, .length, .info]

读者看完Demo之后尝试添加 version 记录 加 密 头

字段:key 说明:标识 内容:“QianFan”(本库使用)

字段:lengthBit 说明:记录使⽤的 length(扩展来变更 length 所占的字节) 内容:1 byte

字段:length 说明:全部信息的总长度,如果减去固定的信息头长度就是加密的信息⻓度 内容:2 bytes

加 密 体

加密头:key.cout + 1 + 2 加密内容: length - (key.cout + 1 + 2)

encode & decode

都是通过CGContext获取位图数据,encode3使用了CVPixelBuffer,方便后续应用到视频帧,然后对 data[n] 二进制化的尾数进行比较 & 操作。

class func baseEncode(data: UnsafeMutablePointer<UInt8>, infoData: Data, width w: Int, height h: Int) {
    let kQHKeyData = kQFkey.data(using: .utf8)!
    let kQHKeyDataCount = kQHKeyData.count
    let kLenghtCount = kLengthBit

    let markCount = kQHKeyDataCount + kLengthBitCount + kLenghtCount + infoData.count

    var bStop = false
    var markIndex = -1
    var markIndexText: Int = 0
    var markBin: QFLSBMarkBin?
    var markLengthBitCount = 0

    // 1、读取原数据
    for y in 0..<h {
        if bStop {
            break;
        }
        for x in 0..<w {
            let index = (y * w + x)

            let markIndexTemp = index / 8
            if markIndexTemp >= markCount {
                bStop = true
                break
            }

            // 2、水印信息的计算
            if markIndex != markIndexTemp {
                markIndex = markIndexTemp

                if markIndex < kQHKeyDataCount {
                    markBin = .key
                    markIndexText = Int(kQHKeyData[markIndex])
                }
                else if markIndex < kQHKeyDataCount + kLengthBitCount {
                    markBin = .lengthBit
                    markIndexText = kLengthBit
                }
                else if markIndex < kQHKeyDataCount + kLengthBitCount + kLenghtCount {
                    markLengthBitCount += 1
                    markBin = .length
                    if markLengthBitCount == 1 {
                        markIndexText = markCount%256
                    }
                    else if markLengthBitCount == 2 {
                        markIndexText = Int(markCount>>8)
                    }
                    else {
                        bStop = true
                        break
                    }
                }
                else if markIndex < markCount {
                    markBin = .info
                    markIndexText = Int(infoData[markIndex - (kQHKeyDataCount + kLengthBitCount + kLenghtCount)])
                }
            }

            if markBin == nil {
                bStop = true
                break
            }

            // 3、读取原数据 & 获取最低有效位
            let offset = 4 * index
            let red = data[offset+1]
            let redBinary = red % 2

            let markIndexTextBinaryIndex = index % 8
            let markIndexTextBinary = Int((markIndexText / (1<<Int(markIndexTextBinaryIndex))) % 2)

            // 4、最低有效位记录
            if redBinary != markIndexTextBinary {
                if markIndexTextBinary == 0 {
                    if red == 255 {
                        data[offset+1] = 254
                    }
                    else {
                        data[offset+1] = red + 1
                    }
                }
                else {
                    if red == 0 {
                        data[offset+1] = 1
                    }
                    else {
                        data[offset+1] = red - 1
                    }
                }
            }
        }
    }
}

// 逻辑上与 baseEncode 相同,读取原数据后记录到对应的水印数据信息上。
class func baseDecode(data: UnsafeMutablePointer<UInt8>, width w: Int, height h: Int) -> (result: Bool, info: String) {

    // ......

    return (false, "解密");
}

具体可以看:QFLSBMan.swift[2]见文末(代码没有注释,也比较乱,抱歉了哈)。

补 充

1、这里需要注意在截图类的逻辑那部分,有如下的函数 & 执行(加密后的图片再执行)

将加密后将图片先缓存本地,再获从缓存本地的图片获取出来进行分享和保存相册,这样加密的数才不会由于保存相册或者直接分享而导致数据会丢失。目前测试分享QQ和钉钉数据解码正常,而微信会丢失的。

compare以上图片都是不使用 toPNG 操作后,图片的加密像素部分,都发生变化,所以已无法解密出原来的信息。 而缓存本地的作用就是为了解决该情况(再考察其他办法解决方案)。

private func toPng() -> Bool

if !toPng() {
    print("showScreenshot toPng 失败")
    return
}

2、还有每张截图都加入QFScreenshot 的普通水印,可简单区分系统截图还是加密截图。

let text = "QFScreenshot" as NSString
let p = CGPoint(x: 20, y: 160)
text.draw(at: p, withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor(white: 0.5, alpha: 1)])

总 结

LSB 的抗干扰比较差,原因在于假如使用的第三方分享,其在传送过程对图片进行二次处理或者优化,很可能会导致信息的丢失。

当然目前的Demo实践上,只要用户使用截图后展示的截图图片通过保存到相册,再QQ分享 或者 直接QQ分享 都能保证信息的完整性。

应该会有人问为什么不直接上传到自家的服务器,并且直接将信息一并传过去,无须这样加密,确实也有道理。

但其实加隐形水印这种方式也很直接,让用户直接将截图分享与QQ的客服或者支撑人员,然后进行沟通。

并且本文只是隐形水印在iOS的实现,其用途的扩展就由各位脑补。

其他用途

1、将信息重复布满整张图片(可以使用重复文案,如 QianFan),加入在类似 抽奖 或者 大转盘 等具有敏感信息的结果截图上,以防止有可能的 PS 做假。

2、用在视频帧中,在视频里面传输指令或者信息(帧丢失的话偶就不管了哈),等等。 改进的隐形水印

1、该实现的原理是通过计算像素指定通道(例如 R通道)的 所有 bit 的 0 / 1 ,通过奇偶数 来替换标准的LSB的最低位 进行比较,这样做更具有隐蔽性。- 一种改进的LSB信息隐藏算法研究与实现[3]见文末

2、加密的信息可以是二维码,可以另一张小图片(具体看图片是灰度图还是彩色图)。


文中备注

[1]QFImageMaskMan:

https://gitee.com/chenqihui/QFImageMaskDemo

[2]QFLSBMan.swift:Chuangkit.com/sj-pi2-si13-or0-pt0-us382-pn1.html

[3]一种改进的LSB信息隐藏算法研究与实现:http://www.doc88.com/p-0814918905734.html

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 相关文章
快速配置 Sign In with Apple 4年以前  |  7174次阅读
使用 GPUImage 实现一个简单相机 4年以前  |  5502次阅读
APP适配iOS11 5年以前  |  5480次阅读
 目录