mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-24 23:41:21 +08:00
feat: 增加打印机接口
This commit is contained in:
BIN
before.png
Normal file
BIN
before.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
6
pom.xml
6
pom.xml
@@ -71,6 +71,12 @@
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.openpnp</groupId>
|
||||
<artifactId>opencv</artifactId>
|
||||
<version>[4.3.0,)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.lemire.integercompression</groupId>
|
||||
<artifactId>JavaFastPFOR</artifactId>
|
||||
|
||||
@@ -2,26 +2,38 @@ package cn.lihongjie.coal.common;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import nu.pattern.OpenCV;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.opencv.core.Mat;
|
||||
import org.opencv.core.MatOfByte;
|
||||
import org.opencv.imgcodecs.Imgcodecs;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
@Slf4j
|
||||
@UtilityClass
|
||||
public class TscPrinterUtil {
|
||||
|
||||
|
||||
static {
|
||||
OpenCV.loadLocally();
|
||||
}
|
||||
|
||||
public static String toHex(String text) {
|
||||
|
||||
return HexUtil.encodeHexStr(toBytes(text));
|
||||
@@ -48,44 +60,36 @@ public class TscPrinterUtil {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static byte[] base64ImageToTscBmpImage(String base64Image) {
|
||||
public static ImageInfo base64ImageToTscBmpImage(String base64Image) {
|
||||
|
||||
var image =
|
||||
ImageIO.read(new ByteArrayInputStream((Base64.getDecoder().decode(base64Image))));
|
||||
|
||||
int width = image.getWidth();
|
||||
byte[] bytes = Base64.getDecoder().decode(base64Image);
|
||||
|
||||
int height = image.getHeight();
|
||||
FileUtils.writeByteArrayToFile(new java.io.File("before.png"), bytes);
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
|
||||
|
||||
// width必须是8的倍数
|
||||
int newWidth = width % 8 == 0 ? width : width + 8 - width % 8;
|
||||
Mat mat1 = Imgcodecs.imdecode(new MatOfByte(input.readAllBytes()), Imgcodecs.IMREAD_GRAYSCALE);
|
||||
|
||||
BitSet bs = new BitSet();
|
||||
// 循环每一个像素
|
||||
ByteBuffer buffer = ByteBuffer.allocate(mat1.width() * mat1.height());
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < newWidth; j++) {
|
||||
|
||||
int idx = i * newWidth + j;
|
||||
if (j < width) {
|
||||
bs.set(idx, image.getRGB(j, i) != Color.black.getRGB());
|
||||
for (int i = 0; i < mat1.height(); i++) {
|
||||
|
||||
} else {
|
||||
for (int j = 0; j < mat1.width(); j++) {
|
||||
|
||||
bs.set(idx, true);
|
||||
}
|
||||
double[] data = mat1.get(i, j);
|
||||
buffer.put((byte) data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
TscPrinterUtil.printBS(bs, newWidth);
|
||||
|
||||
return bs.toByteArray();
|
||||
return new ImageInfo(mat1.width() , mat1.height(), bytebufferToBytes(buffer));
|
||||
}
|
||||
|
||||
public static void printBS(BitSet bs, int width) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(width);
|
||||
sb.append("\n");
|
||||
|
||||
for (int i = 0; i < bs.length(); i++) {
|
||||
@@ -97,20 +101,38 @@ public class TscPrinterUtil {
|
||||
sb.append(bs.get(i) ? "1" : "0").append(" ");
|
||||
}
|
||||
|
||||
log.debug(sb.toString());
|
||||
log.info(sb.toString());
|
||||
}
|
||||
|
||||
private static byte[] processBitMap(String s) {
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
int lasted = s.lastIndexOf(",");
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1000000);
|
||||
|
||||
List<String> list = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(s);
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
|
||||
buffer.put(list.get(i).getBytes(StandardCharsets.UTF_8));
|
||||
buffer.put(",".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
String prefix = s.substring(0, lasted + 1);
|
||||
|
||||
buffer.put(prefix.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// 剩下的内容为base64
|
||||
buffer.put(base64ImageToTscBmpImage(s.substring(lasted + 1)));
|
||||
ImageInfo imageInfo = base64ImageToTscBmpImage(list.get(list.size()-1));
|
||||
|
||||
buffer.put(String.valueOf(imageInfo.width / 8).getBytes(StandardCharsets.UTF_8));
|
||||
buffer.put(",".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put(String.valueOf(imageInfo.height).getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put(",".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put("1".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put(",".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put(imageInfo.data);
|
||||
|
||||
buffer.put("\r\n".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
@@ -121,7 +143,7 @@ public class TscPrinterUtil {
|
||||
|
||||
String[] lines = StringUtils.split(command, "\n");
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1000000);
|
||||
for (String line : lines) {
|
||||
|
||||
int i = line.indexOf(" ");
|
||||
@@ -131,13 +153,16 @@ public class TscPrinterUtil {
|
||||
buffer.put(Command.of(cmd).process(line));
|
||||
|
||||
} else {
|
||||
buffer.put(line.getBytes(StandardCharsets.UTF_8));
|
||||
buffer.put(Command.DEFAULT.process(line));
|
||||
}
|
||||
}
|
||||
|
||||
return bytebufferToBytes(buffer);
|
||||
}
|
||||
|
||||
public record ImageInfo(int width, int height, byte[] data) {
|
||||
}
|
||||
|
||||
public static byte[] bytebufferToBytes(ByteBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.position()];
|
||||
buffer.flip();
|
||||
|
||||
@@ -6,6 +6,7 @@ import cn.lihongjie.coal.tscprinter.dto.ProcessCommandRequest;
|
||||
import cn.lihongjie.coal.tscprinter.dto.ProcessCommandResponse;
|
||||
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -14,7 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class TscPrinterController {
|
||||
|
||||
@PostMapping("/processCommand")
|
||||
public ProcessCommandResponse processCommand(ProcessCommandRequest request) {
|
||||
public ProcessCommandResponse processCommand(@RequestBody ProcessCommandRequest request) {
|
||||
|
||||
return new ProcessCommandResponse(
|
||||
Base64.encode(TscPrinterUtil.processCommand(request.getCommand())));
|
||||
|
||||
@@ -5,7 +5,6 @@ import static cn.lihongjie.coal.common.TscPrinterUtil.processCommand;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -20,22 +19,16 @@ class TscPrinterUtilTest {
|
||||
|
||||
public static Stream<Arguments> hexData() {
|
||||
|
||||
|
||||
return Stream.of(
|
||||
Arguments.of("S", "53"),
|
||||
Arguments.of("T", "54"),
|
||||
Arguments.of("C", "43"),
|
||||
Arguments.of("A", "41"),
|
||||
Arguments.of("SET TEAR ON", "53 45 54 20 54 45 41 52 20 4f 4e".replace(" ", "")),
|
||||
Arguments.of("SET TEAR ON\nSET TEAR ON", "53 45 54 20 54 45 41 52 20 4f 4e 0d 0a 53 45 54 20 54 45 41 52 20 4f 4e".replace(" ", "")
|
||||
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
);
|
||||
|
||||
Arguments.of(
|
||||
"SET TEAR ON\nSET TEAR ON",
|
||||
"53 45 54 20 54 45 41 52 20 4f 4e 0d 0a 53 45 54 20 54 45 41 52 20 4f 4e"
|
||||
.replace(" ", "")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -43,38 +36,41 @@ class TscPrinterUtilTest {
|
||||
void name(String text, String expectHex) {
|
||||
|
||||
assertThat(TscPrinterUtil.toHex(text)).isEqualToIgnoringCase(expectHex);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test1() {
|
||||
|
||||
|
||||
byte[] bytes = TscPrinterUtil.base64ImageToTscBmpImage(Base64.encode(ResourceUtil.getStream("1.bmp")));
|
||||
|
||||
assertThat(bytes).asHexString().isEqualTo("FD");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void test2() {
|
||||
|
||||
|
||||
byte[] bytes = TscPrinterUtil.base64ImageToTscBmpImage(Base64.encode(ResourceUtil.getStream("2x2_1.bmp")));
|
||||
|
||||
assertThat(bytes).asHexString().isEqualTo("FEFD");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test3() {
|
||||
|
||||
assertThat(processCommand("SET TEAR ON")).asHexString().isEqualToIgnoringCase("53 45 54 20 54 45 41 52 20 4f 4e 0D 0A".replace(" ", ""));
|
||||
assertThat(processCommand("SET TEAR ON\nSET TEAR ON")).asHexString().isEqualToIgnoringCase("5345542054454152204F4E0D0A5345542054454152204F4E0D0A".replace(" ", ""));
|
||||
|
||||
assertThat(processCommand("SET TEAR ON"))
|
||||
.asHexString()
|
||||
.isEqualToIgnoringCase("53 45 54 20 54 45 41 52 20 4f 4e 0D 0A".replace(" ", ""));
|
||||
assertThat(processCommand("SET TEAR ON\nSET TEAR ON"))
|
||||
.asHexString()
|
||||
.isEqualToIgnoringCase(
|
||||
"5345542054454152204F4E0D0A5345542054454152204F4E0D0A".replace(" ", ""));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test4() {
|
||||
|
||||
byte[] bytes = ResourceUtil.readBytes("cap.bin");
|
||||
|
||||
bytes = Arrays.copyOfRange(bytes, 39, bytes.length);
|
||||
BitSet bs = new BitSet();
|
||||
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
byte b = bytes[j];
|
||||
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bs.set(j * 8 + i, (b & (1 << i)) != 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TscPrinterUtil.printBS(bs, 67*8 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/test/resources/cap.bin
Normal file
BIN
src/test/resources/cap.bin
Normal file
Binary file not shown.
0
src/test/resources/image.hex
Normal file
0
src/test/resources/image.hex
Normal file
Reference in New Issue
Block a user