JAVA C# Zxing生成的二维码数据转换为1bit的bmp下发到点阵终端。QRCode去白边,以bmp格式字节流发送,BMP图片解析

121 篇文章 4 订阅
88 篇文章 8 订阅

BMP图像文件完全解析 - 知乎

注意:

  • 小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。越向后地址越高,比如00  01  02,02的地址是2,是高。
  • BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
  • 像素存储位置,即位图数据部分相对于文件的起始偏移量。数据部分偏移量的存在,说明图像数据部分并不一定要紧随图像参数或调色板之后放置,BMP图片的制作者其实可以在调色板之后、数据部分之前填充任何内容,只要正确地设置偏移量即可。所以不一定从54开始就是像素数据。

(图片来自上面链接)

字节顺序

数据结构

描述

1,2

word

高8位位字母‘B,低8位为字母’M‘

3,4,5,6

unit

文件尺寸

7,8

word

保留字1

9,10

word

保留字1

11,12,13,14

unit

位图数据部分相对于文件的起始偏移量

字节顺序

数据结构

描述

15,16,17,18

unit

当前结构体的大小,通常是40或56

19,20,21,22

int

图像宽度(像素)

23,24,25,26

int

图像高度(像素)

27,28

word

恒为1

29,30

word

每个像素占用的位数即bpp

31,32,33,34

unit

压缩方式

35,36,37,38

unit

图像的尺寸

39,40,41,42

int

水平分辨率

43,44,45,46

int

垂直分辨率

47,48,49,50

uint

引用色彩数

51,52,53,54

uint

关键色彩数

31-34字节表示图像数据的压缩方式,参数取值范围是0,1,2,3等

0 – RGB方式

1 – 8bpp的run-length-encoding方式

2 – 4bpp的run-length-encoding方式

3 – bit-fields方式

只有压缩方式选项被设置为bit-fileds时,当前结构体大小为56字节,否则,为40字节。

比如压缩方式为0,像素位数为1,那么像素数据为1bit一个点(0或1)

比如压缩方式为0,像素位数为0018,那么像素数据为24bit一个点,即3byte。由于BMP行固定为4字节倍数,不足倍数的,最后的一个字节用0填充。

示例:Zxing生成的二维码数据转换为1bit的bmp格式下发到点阵终端。

 bmp头部分数据我这用不到就不填了,要保存bmp格式文件还是要填的。

public int showQRCode(String content,int wX, int wY, int wWidth, int wHeight, int wDisplaySeconds) throws FTPosException {
        QRCodeWriter qr=new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>(3);
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 0);  //remove white side
        //创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix bitMatrix= null;
        try {
            bitMatrix = qr.encode(content, BarcodeFormat.QR_CODE,wWidth,wHeight,hints);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        //row turn
        final int width = bitMatrix.getWidth();
        final int height = bitMatrix.getHeight();
        final int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                pixels[y * width + x] = bitMatrix.get(x, height-1-y) ? 0:1; //反
            }
        }
        //8 bit compose 1 byte
        final byte[] pixelsBit = new byte[ pixels.length/8 ];
        for (int y = 0; y < pixelsBit.length; y++) {
            pixelsBit[y] = (byte) ((pixels[y*8+7]==0) ?  pixelsBit[y]&(0xFF- 1) : pixelsBit[y]|1);
            pixelsBit[y] = (byte) ((pixels[y*8+6]==0) ?  pixelsBit[y]&(0xFF- 2) : pixelsBit[y]|2);
            pixelsBit[y] = (byte) ((pixels[y*8+5]==0) ?  pixelsBit[y]&(0xFF- 4) : pixelsBit[y]|4);
            pixelsBit[y] = (byte) ((pixels[y*8+4]==0) ?  pixelsBit[y]&(0xFF- 8) : pixelsBit[y]|8);
            pixelsBit[y] = (byte) ((pixels[y*8+3]==0) ?  pixelsBit[y]&(0xFF-16) : pixelsBit[y]|16);
            pixelsBit[y] = (byte) ((pixels[y*8+2]==0) ?  pixelsBit[y]&(0xFF-32) : pixelsBit[y]|32);
            pixelsBit[y] = (byte) ((pixels[y*8+1]==0) ?  pixelsBit[y]&(0xFF-64) : pixelsBit[y]|64);
            pixelsBit[y] = (byte) ((pixels[y*8+0]==0) ?  pixelsBit[y]&(0xFF-128): pixelsBit[y]|128);
        }
        final byte[] bmpFile = new byte[ 0x3E+pixels.length/8 ]; //图片存储的位置+像素数据大小
        Arrays.fill(bmpFile, (byte) 0);
        bmpFile[0]=0x42; //‘B’
        bmpFile[1]=0x4d; //'M'
        bmpFile[10]=0x3E; //图片存储的位置
        System.arraycopy(pixelsBit,0,bmpFile,bmpFile[10],pixelsBit.length);
        int ret = showBitmap(bmpFile,bmpFile.length,wX,  wY,  wWidth,  wHeight,  wDisplaySeconds);
        return ret;
    }

C#版

 /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="text">内容</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <returns>二维码Bitmap</returns>
        public static Bitmap GenerateQRCode(string text, int width, int height)
        {
            BarcodeWriter writer = new BarcodeWriter();
            writer.Format = BarcodeFormat.QR_CODE;
            QrCodeEncodingOptions options = new QrCodeEncodingOptions()
            {
                //DisableECI = true,//设置内容编码
                //CharacterSet = "UTF-8",
                Width = width, //设置二维码的宽度和高度
                Height = height,
                Margin = 0//设置二维码的边距,单位不是固定像素
            };

            writer.Options = options;
            Bitmap map = writer.Write(text);
            return map;
        }
        /// <summary>
        /// 解码二维码
        /// </summary>
        /// <param name="barcodeBitmap">待解码的二维码图片</param>
        /// <returns>扫码结果</returns>
        public static string DecodeQRCode(Bitmap barcodeBitmap)
        {
            BarcodeReader reader = new BarcodeReader();
            //reader.Options.CharacterSet = "UTF-8";
            var result = reader.Decode(barcodeBitmap);
            return (result == null) ? null : result.Text;
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小黄人软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值