当前位置: 首页 > news >正文

asp access网站开发实例精讲做门户网站赚钱吗

asp access网站开发实例精讲,做门户网站赚钱吗,wordpress 干嘛的,山东省乡镇网站建设一:实践前的理论部分 蓝牙/热敏打印机如何打印图片。 票据打印机的指令和条码打印机的指令对于打印图片的格式要求基本都相似 看看ESC/POS指令的文档 是的看不懂。。。干脆直接试试好了,从如何打印一个像素的小黑点开始。 注意到x的最小单位是字节数…

一:实践前的理论部分

蓝牙/热敏打印机如何打印图片。

票据打印机的指令和条码打印机的指令对于打印图片的格式要求基本都相似

看看ESC/POS指令的文档

在这里插入图片描述
是的看不懂。。。干脆直接试试好了,从如何打印一个像素的小黑点开始。

注意到x的最小单位是字节数,而一个字节等于8个比特也就是说如果其实我能一次性控制8个点的打印
所以打印一个小黑点的指令就得出是:1D 76 30 00 01 00 01 00 80
如果想要八个点全黑,对应的指令是:1D 76 30 00 01 00 01 00 FF

我们能改变的最小单位也就是 80 和 FF

在这里插入图片描述

所以按这个公式理论上可以在一张小票纸上的任意位置打出黑点。

二、理论后的实践部分

实践:
从打印一个黑点开始,用到 get-pixels这个库可以获取到图片的宽高以及每个像素点的 rgba

仓库地址:https://github.com/scijs/get-pixels.git

1、打印一个黑点

getPixels('test/576.jpg',(err, { data, shape }) => {data = [0, 0, 0, 255]//这里直接赋值了一个黑点像素点的 rgba 信息shape = [1, 1, 4]//const imgData = rgba2hex(data, shape);const width = shape[0];const height = shape[1];const xL = Math.ceil((width / 8) % 256);  // 1const xH = Math.floor((width / 8) / 256); // 0const yL = height % 256; // 1const yH = Math.floor(height / 256); // 0const buffer = Buffer.from([0x1d, 0x76, 0x30, 0, xL, xH, yL, yH, ...imgData]);console.log("🚀 ~ getPixel ~ buffer:", buffer)//<Buffer 1d 76 30 00 01 00 01 00 80>const tenBuffer = blutoothEncode(buffer)console.log("🚀 ~ getPixels ~ tenBuffer:", tenBuffer.toString())
})

2、打印一排24个黑点

getPixels('test/576.jpg',(err, { data, shape }) => {data = [0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,]shape = [24, 1, 4]const imgData = rgba2hex(data, shape);const width = shape[0];const height = shape[1];const xL = Math.ceil((width / 8) % 256);  // 1const xH = Math.floor((width / 8) / 256); // 0const yL = height % 256; // 1const yH = Math.floor(height / 256); // 0const buffer = Buffer.from([0x1d, 0x76, 0x30, 0, xL, xH, yL, yH, ...imgData]);console.log("🚀 ~ getPixel ~ buffer:", buffer)//<Buffer 1d 76 30 00 01 00 01 00 80>const tenBuffer = blutoothEncode(buffer)console.log("🚀 ~ getPixels ~ tenBuffer:", tenBuffer.toString())
})

3、打印宽24,高8的黑点图

getPixels('test/576.jpg',(err, { data, shape }) => {data = [0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,0, 0, 0, 255,]shape = [24, 8, 4]const imgData = rgba2hex(data, shape);const width = shape[0];const height = shape[1];const xL = Math.ceil((width / 8) % 256);  // 1const xH = Math.floor((width / 8) / 256); // 0const yL = height % 256; // 1const yH = Math.floor(height / 256); // 0const buffer = Buffer.from([0x1d, 0x76, 0x30, 0, xL, xH, yL, yH, ...imgData]);console.log("🚀 ~ getPixel ~ buffer:", buffer)const tenBuffer = blutoothEncode(buffer)console.log("🚀 ~ getPixels ~ tenBuffer:", tenBuffer.toString())
})const rgba2hex = (data, shape) => {const bitArr = [];for (let i = 0; i < data.length; i = i + 4) {if (i[3] === 0) {bitArr.push(0);continue;}// 计算平均值判断const bit = (data[i] + data[i + 1] + data[i + 2]) / 3 > 160 ? 0 : 1;bitArr.push(bit);}// bitArr: [1]// 对bitArr做补0的动作let newBitArr = [];const width = shape[0];const isNeed = width % 8 !== 0;const height = shape[1];if (isNeed) {for (let i = 0; i < height; i++) {newBitArr.push(...bitArr.slice(i * width, (i + 1) * width));for (let j = 0; j < 8 - (width % 8); j++) {newBitArr.push(0);}}} else {newBitArr = bitArr;}// newBitArr: [1, 0, 0, 0, 0, 0, 0, 0]const byteArr = [];for (let i = 0; i < newBitArr.length; i = i + 8) {const byte =(newBitArr[i] << 7) +(newBitArr[i + 1] << 6) +(newBitArr[i + 2] << 5) +(newBitArr[i + 3] << 4) +(newBitArr[i + 4] << 3) +(newBitArr[i + 5] << 2) +(newBitArr[i + 6] << 1) +(newBitArr[i + 7]);byteArr.push(byte);}// byteArr: [128] = [0x80];return new Uint8Array(byteArr);
}/** 蓝牙十六进制指令 转换start */
const blutoothEncode = (buffer) => {let length = 0;buffer.forEach(item => {if (typeof item === "number") {length += 1;} else {length += item.length;}});const result = new Uint8Array(length);let index = 0;buffer.forEach(item => {if (typeof item === "number") {result[index] = item;index += 1;} else {result.set(item, index);index += item.length;}});// 取反码return handlePrintData(result);
}
// 处理打印机数据
function handlePrintData(arr) {let result = new Array(arr.length);for (let i = 0; i < arr.length; i++) {if (arr[i] < 128) {result[i] = arr[i];} else {// 减一let item = arr[i] - 1;// 反码let item2 = tenToTwo(item);let item3 = getReverseCode(item2);let item4 = twoToTen(item3);// 加上符号位result[i] = -item4;}}return result;
}
// 取反码
function getReverseCode(arr) {let result = [];for (let i = 0; i < arr.length; i++) {let item = arr[i];if (item === 1) {result.push(0);} else {result.push(1);}}return result;
}// 十进制转二进制
function tenToTwo(num) {let result = [];while (num > 0) {result.unshift(num % 2);num = Math.floor(num / 2);}return result;
}// 二进制转十进制
function twoToTen(arr) {let result = 0;for (let i = 0; i < arr.length; i++) {let item = arr[i];result += item * Math.pow(2, arr.length - i - 1);}return result;
}
/** 蓝牙十六进制指令 转换end */

十六进制的打印指令
getPixel ~ buffer: <Buffer 1d 76 30 00 03 00 08 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff>
十进制的打印指令
getPixels ~ tenBuffer: 29,118,48,0,3,0,8,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1

打印结果:

在这里插入图片描述

再测试打印一张图片:

在这里插入图片描述

三、实践结束理解图片打印指令

位图的基本概念?

位图: 是由许多像素点组成的图像表示方法。每个像素点都有其特定的颜色值或灰度值。
像素点: 是位图中的最小单位,每个像素点都有其特定的属性(如颜色、亮度等)。
字节存储:在打印指令中,位图数据通常以字节为单位进行存储和传输。

例如,在图中的xL、xH、yL、yH参数就是用于确定水平和垂直方向上的位图字节数和点数。

当打印机接收到包含位图数据的打印指令时,它会根据指令中的参数(如位图的大小、位置等)将位图数据转换为实际的打印输出。例如,指令中的xLxH确定了水平方向上的位图字节数,yLyH确定了垂直方向上的位图点数。打印机根据这些参数来安排位图在打印纸上的布局。

位图的分辨率(如纵向分辨率和横向分辨率)会影响打印输出的质量。在图中的指令格式中,不同的m值会选择不同的纵向和横向分辨率模式,从而影响位图在打印时的清晰度和大小。总之,位图在打印领域是一种重要的数据表示方式。

位图中像素点与字节、比特的关系?

在一般的位图表示中,一个像素点所占用的存储大小取决于位图的颜色深度。

黑白位图(1 - bit 位图)
如果是黑白位图,每个像素点只有两种状态:黑或白。这种情况下,一个像素点只需要 1 比特(1 bit)来表示。例如,0 可以表示白色,1 可以表示黑色。

灰度位图
对于灰度位图,如果有 256 级灰度,那么每个像素点需要 8 比特(1 字节,因为 1 字节 = 8 比特)来表示。这是因为 256 级灰度需要用 8 位二进制数(00000000 - 11111111)来区分不同的灰度级别。

彩色位图
在彩色位图中,情况更为复杂。例如,常见的 24 - bit 真彩色位图,每个像素点由红、绿、蓝(RGB)三个颜色通道组成,每个通道用 8 比特表示,所以一个像素点总共需要 24 比特(3 字节)来表示。

为什么 m 的取值范围有 2 个?

这个区间内的m值用于选择正常模式、倍宽模式、倍高模式和倍宽倍高模式。这些模式主要用于调整字符的宽度和高度。这个区间内的m值实际上是重复了 0 - 3 区间内的功能。这样设计可能是为了方便编程和指令的兼容性。这种设计使得在不同的编程环境或设备中,可以灵活地选择m值来实现相同的打印效果,提高了指令的通用性和易用性。

关于xL、xH、yL、yH的定义?

xL和xH:
xLxH表示水平方向位图字节数(xL + xH×256)。这里的xL是低字节xH是高字节。它们共同确定了水平方向上的位图字节数量。

例如,当xL + xH×256 = 64时,表示水平方向上有 64 个字节用于存储位图数据。

yL和yH:
yLyH表示垂直方向位图点数(yL + yH×256)。yL是低字节yH是高字节。它们共同确定了垂直方向上的位图点数。

例如,在图中的示例里,yL + yH×256表示垂直方向上的点数。

以水平方向为例,
如果xL = 1且xH = 0,那么水平方向位图字节数为1+0×256 = 1字节。
如果xL = 0且xH = 1,那么水平方向位图字节数为0 + 1×256=256字节。
在实际打印光栅位图时,通过这些参数可以准确地确定位图在纸张上的大小和位置,从而实现精确的打印输出。

字节顺序的概念?

在计算机中,数据常常以多个字节来存储。当一个数据需要用多个字节表示时,就存在字节顺序的问题。例如,一个 16 位的数据(在这个例子中类似xL + xH×256这样的数据)需要用两个字节来存储。
低字节(xL):指的是数据的低位部分。在数值表示中,它占的权重较小。
高字节(xH):指的是数据的高位部分。在数值表示中,它占的权重较大。

以xL + xH×256为例:

假设我们有一个水平方向位图字节数为 1000(十进制)。将 1000 转换为十六进制是03E8

在这种情况下:
低字节(xL):十六进制的E8(十进制的 232),这是低位部分。
高字节(xH):十六进制的03(十进制的 3),这是高位部分。

在 ESC/POS 指令中,当你看到xLxH这两个参数时,要知道它们组合起来表示一个较大的数值。xL总是代表低位部分,xH总是代表高位部分。在计算水平方向位图字节数时,就是按照xL + xH×256这样的公式来计算的。

到这里应该就比较清楚了类似 xL + xH×256 的式子就是在计算字节数的公式而已。

为什么 xL 等参数的取值范围是0 到 255?

在计算机中,一个字节(8 位)可以表示的数据范围是 0 - 255(十进制)。这是因为 8 位二进制数可以表示 个不同的值,从 00000000(十进制 0)到 11111111(十进制 255)。
xL、xH、yL、yH这些参数通常是用一个字节来存储的,所以它们的取值范围自然就限制在 0 - 255

对于大多数实际的打印应用场景,用一个字节来表示位图的大小或位置信息已经足够。常见的小票打印机或简单的标签打印机中,打印区域通常较小,不需要超过 255 个单位(字节数或点数)来表示位图的相关尺寸。如果超出这个范围,可能需要使用多个字节来表示更大的数值,但这会增加指令的复杂性和数据传输量。

总结

通过这个打印方式可以控制这张纸上能被热敏头接触到的任意地方都能打印出自己想要的信息,所以可以说是最好的打印方式。

缺点:从下发打印指令到打印机开始打印这个过程根据数据量的大小,会有不同程度的延迟,其次打印过程中并不能一次性的打完所有指令,会存在打一段停一段的情况,所以不适合大数据量的图片打印。

tip:某些打印机厂商的打印机没有好好实现规范于是按上述的图片指令打印方案图片高度超过一定程度就会出现乱码,需要把这张图片拆分成多张小图片才能正常打。

getPixels('test/576.jpg',(err, { data, shape }) => {const imgData = rgba2hex(data, shape);const width = shape[0];const height = shape[1];const xL = Math.ceil((width / 8) % 256);  // 1const xH = Math.floor((width / 8) / 256); // 0const yL = height % 256; // 1const yH = Math.floor(height / 256); // 0//const buffer = Buffer.from([0x1d, 0x76, 0x30, 0, xL, xH, yL, yH, ...imgData]);//const tenBuffer = blutoothEncode(buffer)//拆成小图const buffer = [];for(let i=0;i<height;i++) {let tempBuffer = [0x1d, 0x76, 0x30, 0, xL, xH, 1, 0, imgData.slice(i*(xL + 256*xH), (i+1)*(xL + 256*xH))]buffer[i] = tempBuffer;}
})

参考链接:
https://juejin.cn/post/7362537451170185252
https://juejin.cn/post/7297529039312158730
https://tech.youzan.com/retail-printer-picture

http://www.yayakq.cn/news/949523/

相关文章:

  • 做任务挣钱网站免费推广网站如何提高排名
  • 网站建设与管理工资网络工程毕业后干什么
  • 国外h5网站模板求2021没封的良心网址
  • 简单网站建设视频教程下载sharepoint网站制作
  • 怎么做网站教程视频网上推广产品怎么做
  • 专业的营销网站聊城公司网站建设
  • 公众号的微网站开发网站的设计开发
  • 网站透明导航代码万户网络技术
  • 重庆营销型网站设计电商网站建设标准
  • 做网站app需要多少钱网站主机免费申请
  • 定制网站开发介绍图wordpress在线主题导入
  • 网站建设有什么作用PR做视频需要放网站上
  • 企业网站咋做网站开发流程指什么
  • 广州建设行业网站网站建设 自查表
  • 研发网站要多久网站后台如何上传附件
  • 合同管理软件seo免费资源大全
  • html网站开发目标在线销售网站设计文献
  • 贵州讯玛网站建设做网站如何来钱
  • 阿里云里面网站建设工程造价信息网如何进入
  • 陕西渭南住房和城乡建设厅网站深圳坪山区最新通告
  • 江苏省职业建设注册管理中心网站做视频网站服务器多少钱
  • 安徽公路建设行业协会网站是哪个html文件如何转wordpress
  • 装饰公司网站源码下载不同网站相似的页面百度收录吗
  • 展示型网站 营销型网站个人网站主机的配置
  • 邢台网站制作哪里有连云港建设公司网站
  • 网站访问大小泉州网站的建设
  • seo推广营销网站群晖wordpress设为首页
  • 天河区网站建设公司wordpress登陆后台总是跳转首页
  • 推荐六款适合做小说阅读站及小说下载站的wordpress 模板可以做水印的网站
  • 网站布局设计景观规划设计公司