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

ESC/POS图片打印指令

一:实践前的理论部分

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

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

看看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

相关文章:

ESC/POS图片打印指令

一&#xff1a;实践前的理论部分 蓝牙/热敏打印机如何打印图片。 票据打印机的指令和条码打印机的指令对于打印图片的格式要求基本都相似 看看ESC/POS指令的文档 是的看不懂。。。干脆直接试试好了&#xff0c;从如何打印一个像素的小黑点开始。 注意到x的最小单位是字节数…...

Unity之如何在Linux上部署Dedicated Server专用服务器

文章目录 前言构建为专用服务器启动时获取参数在 DigitalOcean 上准备 Linux 服务器最后,让我们开始吧。前言 我们在使用Mirror,Fishnet或者Unity Netcode开发多人游戏时,一般有三种链接模式,分别是:Host,Server,Client。 Host:代表既是客户端又是服务器 Server:代表…...

十、Linux 故障排除专业案例分享

Linux 故障排除专业案例分享 在 Linux 操作系统漫长的使用历程当中&#xff0c;不可避免地会遭遇到各种各样不同类型的故障。本文将会深入而全面地阐述一些较为常见的 Linux 故障以及与之相对应的解决方案。其目的在于&#xff0c;当用户在实际使用过程中面临类似问题的时候&a…...

智慧楼宇平台,构筑未来智慧城市的基石

随着城市化进程的加速&#xff0c;城市面临着前所未有的挑战。人口密度的增加、资源的紧张、环境的恶化以及对高效能源管理的需求&#xff0c;都在推动着我们寻找更加智能、可持续的城市解决方案。智慧楼宇作为智慧城市建设的重要组成部分&#xff0c;正逐渐成为推动城市可持续…...

JVM 实战篇(一万字)

此笔记来至于 黑马程序员 内存调优 内存溢出和内存泄漏 内存泄漏&#xff08;memory leak&#xff09;&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在 GC ROOT 的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内…...

线程同步之双摄

如何实现两个摄像头进行同步&#xff0c;并利用同步的信号做一些事情&#xff0c; 比如stereo camera 做深度&#xff0c;如果是自己整的两个camera&#xff0c;同步就需要自己做&#xff0c; 那么这时候可以利用线程同步手写一个&#xff0c;下面给一个示例代码&#xff1a; …...

使用 PyTorch 构建 LSTM 股票价格预测模型

目录 引言准备工作1. 训练模型&#xff08;train.py&#xff09;2. 模型定义&#xff08;model.py&#xff09;3. 测试模型和可视化&#xff08;test.py&#xff09;使用说明模型调整结论 引言 在金融领域&#xff0c;股票价格预测是一个重要且具有挑战性的任务。随着深度学习…...

【C++篇】C++类与对象深度解析(五):友元机制、内部类与匿名对象的讲解

文章目录 前言 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助&#xff01…...

模型训练进度条的代码

这个内容难在什么地方呢&#xff1f; 我想要跳转到另一个页面的时候 如何保存当前的训练状态&#xff0c;本来还想着加一个页面去管理进度的。然后想到了localstorage&#xff0c;将一些信息存储到浏览器中去。 进度条展示 <el-form-item label"训练进度" v-show…...

直观理解反向传播 | Chapter 3 | Deep Learning | 3Blue1Brown

目录 前言1. 简介2. 回顾3. 直观的演绎示例4. 随机梯度下降相关资料结语 前言 3Blue1Brown 视频笔记&#xff0c;仅供自己参考 这个章节主要来直观地理解反向传播算法到底在做什么 官网&#xff1a;https://www.3blue1brown.com 视频&#xff1a;https://www.bilibili.com/vide…...

052_python基于Python高校岗位招聘和分析平台

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…...

基于物联网、大数据、人工智能等技术开发的Spring Cloud 智慧工地云平台源码,支持多端应用

系统概述&#xff1a; 智慧工地是指运用现代信息技术&#xff0c;如物联网&#xff08;IoT&#xff09;、大数据、人工智能&#xff08;AI&#xff09;、云计算、移动互联网等&#xff0c;对传统建筑工地进行智能化改造和管理的新型工地。它通过高度集成的系统和设备&#xff…...

常见的跨境电商平台对比【总结表】

常见的跨境电商平台对比【总结表】 平台目标市场费用结构物流服务支付方式推广工具适合卖家亚马逊全球销售佣金、月租费、FBAFBA支持全球配送多种支付方式广告工具、促销活动有一定资金实力的品牌和卖家eBay全球上市费、成交费第三方物流支持PayPal、信用卡广告工具、促销活动…...

perl批量改文件后缀

perl批量改文件后缀 如题&#xff0c;perl批量改文件后缀&#xff0c;将已有的统一格式的文件后缀&#xff0c;修改为新的统一的文件后缀。 #!/bin/perl use 5.010;print "Please input file suffix which U want to rename!\n"; chomp (my $suffix_old <>)…...

【Python中的字符串处理】正则表达式与常用字符串操作技巧!

Python中的字符串处理&#xff1a;正则表达式与常用字符串操作技巧 Python 在字符串处理方面提供了丰富的内置功能和模块&#xff0c;能够帮助开发者处理各种复杂的文本操作。无论是简单的字符串拼接、替换&#xff0c;还是借助正则表达式&#xff08;re 模块&#xff09;实现…...

又是一年一度的1024,那就记录一篇算法博客吧~ 【二进制加法探秘】

前言&#xff1a; 又是一年一度的1024&#xff0c;那就记录一篇算法博客吧~ 内容如下~ 1 题目介绍 给定两个二进制字符串 a 和 b&#xff0c;需要返回它们的和&#xff0c;结果以二进制字符串形式给出。 示例 1&#xff1a; 输入: a “11”, b “1” 输出: “100” 示例 2…...

LeetCode--买卖股票的最佳时机含冷冻期--动态规划

一、题目解析 二、算法原理 我们可以使用dp[i]来表示第i天买卖股票所获得的最大利润。由题可得我们只能持有一支股票&#xff0c;并且在卖出后有冷冻期的限制&#xff0c;因此我们会有三种不同的状态&#xff1a; 我们目前持有一支股票&#xff0c;对应的「累计最大收益」记为…...

装了Ubuntu和Windows双系统,如何设置默认启动Windows

可以将默认启动系统设置为Windows&#xff0c;以下是步骤&#xff1a; 1. 修改GRUB配置文件&#xff1a; • 启动到Ubuntu&#xff0c;打开终端。 • 编辑GRUB配置文件&#xff1a; sudo nano /etc/default/grub • 找到这一行&#xff1a; GRUB_DEFAULT0 将0改为对应Wi…...

WPF+MVVM案例实战-设备状态LED灯变化实现

文章目录 1、项目创建2、UI界面布局1. MainWindow.xaml2、颜色转换器实现2.MainViewModel.cs 代码实现 3、运行效果4.源代码下载 1、项目创建 打开 VS2022 &#xff0c;新建项目 Wpf_Examples&#xff0c;创建各层级文件夹&#xff0c;安装 CommunityToolkit.Mvvm 和 Microsof…...

MySQL--基本介绍

一.数据库前言 1.数据库的相关介绍 关系数据库管理系统&#xff08;Relational Database Management System&#xff1a;RDBMS&#xff09;是指包括相互联系的逻辑组织和存取这些数据的一套程序 (数据库管理系统软件)。关系数据库管理系统就是管理关系数据库&#xff0c;并将数…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...