png隐写数据进TEXTchunk

本文介绍了PNG图像格式的特点,如高压缩比、透明度支持,并探讨了如何在PNG的TEXT chunk中隐藏数据。通过封装PNG格式信息,实现写入和解析text chunk,以及在图片中写入隐形水印的技术,确保数据的隐蔽传输。
摘要由CSDN通过智能技术生成

–> go to 总目录


想要向 png隐写数据,需求来源于想将图片上传于 csdn并获得 url,实现将印象笔记中的 .enex文件格式中的图片url替换成csdn提供的链接。
PNG文件格式解析
* 利用文件类型判断文件头

一、PNG描述

百度百科

  • 体积小 网络通讯中因受带宽制约,在保证图片清晰、逼真的前提下,网页中不可能大范围的使用文件较大的bmp格式文件。
  • 无损压缩PNG文件采用LZ77算法的派生算法进行压缩,其结果是获得高的压缩比,不损失数据。它利用特殊的编码方法标记重复出现的数据,因而对图像的颜色没有影响,也不可能产生颜色的损失,这样就可以重复保存而不降低图像质量。
  • 索引彩色模式 PNG-8格式与GIF图像类似,同样采用8位调色板将RGB彩色图像转换为索引彩色图像。图像中保存的不再是各个像素的彩色信息,而是从图像中挑选出来的具有代表性的颜色编号,每一编号对应一种颜色,图像的数据量也因此减少,这对彩色图像的传播非常有利。
  • 更优化的网络传输显示 PNG图像在浏览器上采用流式浏览,即使经过交错处理的图像会在完全下载之前提供浏览者一个基本的图像内容,然后再逐渐清晰起来。它允许连续读出和写入图像数据,这个特性很适合于在通信过程中显示和生成图像。
  • 支持透明效果 PNG可以为原图像定义256个透明层次,使得彩色图像的边缘能与任何背景平滑地融合,从而彻底地消除锯齿边缘。这种功能是GIF和JPEG没有的。

1.1 格式

详细的各种辅助块的介绍见PNG文件格式解析
在这里插入图片描述

1.2 rgba

色相环(rgb之和加起来是255所形成的一个圆,比如R到G的线就是:B=255,R+G=255)
在这里插入图片描述

每一个像素由三原色和明暗表示:Red(红色)Green(绿色)Blue(蓝色)和Alpha(亮度)。
所以rgba就是这个4个byte组成,每个byte有255个值。
所以用8个16进制表示比如#7FFF0000

二、隐写数据

上面介绍的chunk中我们可以使用
tEXt加信息
png decoder
png_encoder

2.1 写入数据&解析 text chunk

三个类

  • PNG 封装png格式信息
  • ImageInfo 图片的信息:id=UUID,name=图片名称,path=图片路径
  • transformer类有两个核心方法

1 .transorm(srcDir,targetDir),接受srcDir下所有png图片,写入targetDir中。写入的过程中,插入tExtchunk—ImageInfo的key和value。
具体为" imageInfo uuid_name "

  1. praseInfoFrom(String srcDir),解析tExtCunk,被还原成ImageInfo

png图片格式

package com.pngimage;

import java.util.UUID;

/**
 * <code>ImageInfo</code> description
 *
 * @author sunqiyuan
 * @date 2020-06-05
 */
public class ImageInfo {
   
    private String id;
    private String name;
    private String path;

    public ImageInfo(String name, String path) {
   
        this.id = UUID.randomUUID().toString().replace("-", "");
        this.name = name;
        this.path = path;

    }

    public ImageInfo(String id, String name, String path) {
   
        this.id = id;
        this.name = name;
        this.path = path;
    }

    public String getId() {
   
        return id;
    }

    public void setId(String id) {
   
        this.id = id;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public String getPath() {
   
        return path;
    }

    public void setPath(String path) {
   
        this.path = path;
    }

    @Override
    public String toString() {
   
        return "ImageInfo{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", path='" + path + '\'' +
                '}';
    }
}

package com.pngimage;

import java.io.IOException;
import java.util.zip.CRC32;

import sun.security.krb5.internal.crypto.crc32;

/**
 * <code>PNG</code> PNG模型信息
 *
 * @author sunqiyuan
 * @date 2020-06-05
 */
public class PNG {
   
    final byte[] identifier = {
   -119, 80, 78, 71, 13, 10, 26, 10};
    private static final int bKGDChunk = 0x624B4744;
    private static final int cHRMChunk = 0x6348524D;
    private static final int gAMAChunk = 0x67414D41;
    private static final int hISTChunk = 0x68495354;
    private static final int IDATChunk = 0x49444154;
    public static final int IENDChunk = 0x49454E44;
    private static final int IHDRChunk = 0x49484452;
    private static final int PLTEChunk = 0x504C5445;
    private static final int pHYsChunk = 0x70485973;
    private static final int sBITChunk = 0x73424954;
    public static final int tEXtChunk = 0x74455874;
    private static final int tIMEChunk = 0x74494D45;
    private static final int tRNSChunk = 0x74524E53;
    private static final int zTXtChunk = 0x7A545874;

    public int pos;

    /**
     * png的chunk格式
     */
    public static class Chunk {
   

        /**
         * 总长度
         * 4 个字节
         */
        int length;
        /**
         * 4 个字节 标识chunk类型
         */
        int type;
        /**
         * 可变长度, chunk块格式长度,属于每个chunk的长度
         */
        byte[] chunkData;

        /**
         * 4个字节的冗余校验码
         */
        int crc;

        public Chunk(int length, int type, byte[] chunkData, int pos) {
   
            this.length = length;
            this.type = type;
            this.chunkData = chunkData;
            this.crc = readInt(chunkData, pos + length - 4);
        }

        public Chunk(byte[] chunk, int pos) {
   
            this.length = readInt(chunk, pos);
            this.type = readInt(chunk, pos + 4);
        }

        public Chunk() {
   
        }
    }

    /**
     * IHDR_Chunk
     */
    class IHDR_Chunk extends Chunk {
   
        int width = 0;
        int height = 0;
        int bitdepth 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值