diff --git a/after.png b/after.png new file mode 100644 index 00000000..96346068 Binary files /dev/null and b/after.png differ diff --git a/before.png b/before.png new file mode 100644 index 00000000..a8cf4c48 Binary files /dev/null and b/before.png differ diff --git a/pom.xml b/pom.xml index b4c99194..d32780fc 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,12 @@ + + org.openpnp + opencv + [4.3.0,) + + me.lemire.integercompression JavaFastPFOR diff --git a/src/main/java/cn/lihongjie/coal/common/TscPrinterUtil.java b/src/main/java/cn/lihongjie/coal/common/TscPrinterUtil.java index 7dfad807..1be25a8f 100644 --- a/src/main/java/cn/lihongjie/coal/common/TscPrinterUtil.java +++ b/src/main/java/cn/lihongjie/coal/common/TscPrinterUtil.java @@ -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 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(); diff --git a/src/main/java/cn/lihongjie/coal/tscprinter/controller/TscPrinterController.java b/src/main/java/cn/lihongjie/coal/tscprinter/controller/TscPrinterController.java index d4280f50..97830c8a 100644 --- a/src/main/java/cn/lihongjie/coal/tscprinter/controller/TscPrinterController.java +++ b/src/main/java/cn/lihongjie/coal/tscprinter/controller/TscPrinterController.java @@ -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()))); diff --git a/src/test/java/cn/lihongjie/coal/common/TscPrinterUtilTest.java b/src/test/java/cn/lihongjie/coal/common/TscPrinterUtilTest.java index a1d24ce6..51937de6 100644 --- a/src/test/java/cn/lihongjie/coal/common/TscPrinterUtilTest.java +++ b/src/test/java/cn/lihongjie/coal/common/TscPrinterUtilTest.java @@ -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 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 ); + + } } diff --git a/src/test/resources/cap.bin b/src/test/resources/cap.bin new file mode 100644 index 00000000..eb94e91e Binary files /dev/null and b/src/test/resources/cap.bin differ diff --git a/src/test/resources/image.hex b/src/test/resources/image.hex new file mode 100644 index 00000000..e69de29b