Initial commit
authorAsbjørn Sloth Tønnesen <asbjorn@asbjorn.biz>
Wed, 7 Mar 2012 16:53:36 +0000 (16:53 +0000)
committerAsbjørn Sloth Tønnesen <asbjorn@asbjorn.biz>
Wed, 7 Mar 2012 16:53:36 +0000 (16:53 +0000)
Makefile [new file with mode: 0644]
ql570.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c2ad0b4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+CFLAGS=-g
+CFLAGS+= $(shell pkg-config --cflags libpng)
+LDFLAGS+= $(shell pkg-config --libs libpng)
+all: ql570
diff --git a/ql570.c b/ql570.c
new file mode 100644 (file)
index 0000000..8034ca7
--- /dev/null
+++ b/ql570.c
@@ -0,0 +1,226 @@
+/*
+ * Brother QL-570 thermal printing program
+ * It prints a mono PNG image directly to the printers block device
+ *
+ * Copyright 2011 Asbjørn Sloth Tønnesen <code@asbjorn.it>
+ *
+ * PNG reading based on:
+ *   A simple libpng example program
+ *   http://zarb.org/~gc/html/libpng.html
+ *   Copyright 2002-2011 Guillaume Cottenceau and contributors.
+ *
+ * This software may be freely redistributed under the terms
+ * of the libpng license.
+ * http://libpng.org/pub/png/src/libpng-LICENSE.txt
+ *
+ * Example usage:
+ *   ./ql570 /dev/usb/lp0 image.png
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define PNG_DEBUG 3
+#include <png.h>
+
+#define ESC 0x1b
+
+#define DEBUG
+
+FILE * fp;
+
+struct {
+       int16_t w;
+       int16_t h;
+       uint8_t * data;
+} typedef pngdata_t;
+
+FILE * ql570_open(const char * path)
+{
+       fp = fopen(path, "r+b");
+       if (fp == NULL) {
+               perror("fopen");
+               exit(EXIT_FAILURE);
+       }
+       return fp;
+}
+
+void check_img(pngdata_t * img)
+{
+       int i, j;
+       int lb = (img->w / 8) + (img->w % 8 > 0);
+       printf("lb: %d\n", lb);
+       for (i=0;i<img->h;i++) {
+               for (j=img->w-1;j!=0;j--) {
+                       if (img->data[i*lb+j/8] & (1 << (7-(j % 8)))) {
+                               printf("#");
+                       } else {
+                               printf(" ");
+                       }
+               }
+               printf("\n");
+       }
+
+}
+
+void ql570_print(pngdata_t * img)
+{
+       /* Init */
+       fprintf(fp, "%c%c", ESC, '@');
+
+       /* Set media type */
+       fprintf(fp, "%c%c%c%c%c%c%c%c%c%c%c%c%c", ESC, 'i', 'z', 0xa6, 0x0a, 29, 0, img->h & 0xff, img->h >> 8, 0, 0, 0, 0);
+
+       /* Set cut type */
+       fprintf(fp, "%c%c%c", ESC, 'i', 'K', 8);
+
+       /* Enable cutter */
+       fprintf(fp, "%c%c%c", ESC, 'i', 'A', 1);
+
+       /* Set margin = 0 */
+       fprintf(fp, "%c%c%c%c%c", ESC, 'i', 'd', 0, 0);
+
+       int i, j;
+       int lb = (img->w / 8) + (img->w % 8 > 0);
+       for (i=0;i<img->h;i++) {
+               fprintf(fp, "%c%c%c", 'g', 0x00, 90);
+               for (j=0;j<lb;j++) {
+                       fprintf(fp, "%c", img->data[i*lb+j]);
+               }
+               for (;j<90;j++) {
+                       fprintf(fp, "%c", 0x00);
+               }
+       }
+
+       /* Print */
+       fprintf(fp, "%c", 0x1a);
+}
+
+void abort_(const char * s, ...)
+{
+        va_list args;
+        va_start(args, s);
+        vfprintf(stderr, s, args);
+        fprintf(stderr, "\n");
+        va_end(args);
+        abort();
+}
+
+pngdata_t * loadpng(const char * path)
+{
+       png_structp png_ptr;
+       png_infop info_ptr;
+       png_bytep * row_pointers;
+       int width, height, rowbytes;
+       int x, y;
+        unsigned char header[8];    // 8 is the maximum size that can be checked
+       png_byte* ptr;
+       FILE *fp;
+       int type = 0;
+       int lb;
+       uint8_t * bitmap;
+
+        /* open file and test for it being a png */
+        fp = fopen(path, "rb");
+        if (!fp)
+                abort_("[read_png_file] File %s could not be opened for reading", path);
+        fread(header, 1, 8, fp);
+        if (png_sig_cmp(header, 0, 8))
+                abort_("[read_png_file] File %s is not recognized as a PNG file", path);
+
+        /* initialize stuff */
+        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+        if (!png_ptr)
+                abort_("[read_png_file] png_create_read_struct failed");
+
+        info_ptr = png_create_info_struct(png_ptr);
+        if (!info_ptr)
+                abort_("[read_png_file] png_create_info_struct failed");
+
+        if (setjmp(png_jmpbuf(png_ptr)))
+                abort_("[read_png_file] Error during init_io");
+
+        png_init_io(png_ptr, fp);
+        png_set_sig_bytes(png_ptr, 8);
+
+        png_read_info(png_ptr, info_ptr);
+
+       if (png_get_channels(png_ptr, info_ptr) == 1
+           && png_get_bit_depth(png_ptr, info_ptr) == 1) {
+               type = 1;
+       } else if (png_get_channels(png_ptr, info_ptr) == 4
+           && png_get_bit_depth(png_ptr, info_ptr) == 8) {
+               type = 2;
+       }
+
+       if (type == 0) {
+               fprintf(stderr, "Invalid PNG! Only mono or 4x8-bit RGBA PNG files are allowed\n");
+               exit(1);
+       }
+
+        width = png_get_image_width(png_ptr, info_ptr);
+        height = png_get_image_height(png_ptr, info_ptr);
+
+        png_read_update_info(png_ptr, info_ptr);
+
+        /* read file */
+        if (setjmp(png_jmpbuf(png_ptr)))
+                abort_("[read_png_file] Error during read_image");
+
+        row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
+
+        rowbytes = type == 1 ? (width / 8) + (width % 8 > 0) : width << 2;
+
+        for (y=0; y<height; y++)
+                row_pointers[y] = (png_byte*) malloc(rowbytes);
+
+        png_read_image(png_ptr, row_pointers);
+
+        fclose(fp);
+
+       lb = (height / 8) + (height % 8 > 0);
+       bitmap = malloc(width*lb);
+       memset(bitmap, 0, width*lb);
+
+       #define heat_on(x, y) bitmap[(x*lb)+(y/8)] |= 1 << (7-(y%8))
+        for (y=0; y<height; y++) {
+                png_byte* row = row_pointers[y];
+                       for (x=0; x<width; x++) {
+                       if (type == 1) {
+                               ptr = &(row[x/8]);
+                       } else {
+                               ptr = &(row[x<<2]);
+                       }
+                       if ((ptr[0] & (1 << (7-(x%8)))) == 0) {
+                               heat_on(x, y);
+                       }
+                       }
+               }
+
+
+       pngdata_t * ret = malloc(sizeof(pngdata_t));
+       ret->w = height;
+       ret->h = width;
+       ret->data = bitmap;
+       return ret;
+}
+
+int main(int argc, const char ** argv)
+{
+       if (argc <= 2) {
+               fprintf(stderr, "Usage: %s printer pngfile\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       ql570_open(argv[1]);
+       pngdata_t * data = loadpng(argv[2]);
+       //check_img(data);
+       printf("w: %d\th: %d\n", data->w, data->h);
+       //check_img(data);
+       ql570_print(data);
+       return EXIT_SUCCESS;
+}