2 * Brother QL-570 thermal printing program
3 * It prints a mono PNG image directly to the printers block device
5 * Copyright 2011 Asbjørn Sloth Tønnesen <code@asbjorn.it>
7 * PNG reading based on:
8 * A simple libpng example program
9 * http://zarb.org/~gc/html/libpng.html
10 * Copyright 2002-2011 Guillaume Cottenceau and contributors.
12 * This software may be freely redistributed under the terms
13 * of the libpng license.
14 * http://libpng.org/pub/png/src/libpng-LICENSE.txt
17 * ./ql570 /dev/usb/lp0 image.png
41 FILE * ql570_open(const char * path)
43 fp = fopen(path, "r+b");
51 void check_img(pngdata_t * img)
54 int lb = (img->w / 8) + (img->w % 8 > 0);
55 printf("lb: %d\n", lb);
56 for (i=0;i<img->h;i++) {
57 for (j=img->w-1;j!=0;j--) {
58 if (img->data[i*lb+j/8] & (1 << (7-(j % 8)))) {
69 void ql570_print(pngdata_t * img)
72 fprintf(fp, "%c%c", ESC, '@');
75 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);
78 fprintf(fp, "%c%c%c", ESC, 'i', 'K', 8);
81 fprintf(fp, "%c%c%c", ESC, 'i', 'A', 1);
84 fprintf(fp, "%c%c%c%c%c", ESC, 'i', 'd', 0, 0);
87 int lb = (img->w / 8) + (img->w % 8 > 0);
88 for (i=0;i<img->h;i++) {
89 fprintf(fp, "%c%c%c", 'g', 0x00, 90);
91 fprintf(fp, "%c", img->data[i*lb+j]);
94 fprintf(fp, "%c", 0x00);
99 fprintf(fp, "%c", 0x1a);
102 void abort_(const char * s, ...)
106 vfprintf(stderr, s, args);
107 fprintf(stderr, "\n");
112 pngdata_t * loadpng(const char * path)
116 png_bytep * row_pointers;
117 int width, height, rowbytes;
119 unsigned char header[8]; // 8 is the maximum size that can be checked
126 /* open file and test for it being a png */
127 fp = fopen(path, "rb");
129 abort_("[read_png_file] File %s could not be opened for reading", path);
130 fread(header, 1, 8, fp);
131 if (png_sig_cmp(header, 0, 8))
132 abort_("[read_png_file] File %s is not recognized as a PNG file", path);
134 /* initialize stuff */
135 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
138 abort_("[read_png_file] png_create_read_struct failed");
140 info_ptr = png_create_info_struct(png_ptr);
142 abort_("[read_png_file] png_create_info_struct failed");
144 if (setjmp(png_jmpbuf(png_ptr)))
145 abort_("[read_png_file] Error during init_io");
147 png_init_io(png_ptr, fp);
148 png_set_sig_bytes(png_ptr, 8);
150 png_read_info(png_ptr, info_ptr);
152 if (png_get_channels(png_ptr, info_ptr) == 1
153 && png_get_bit_depth(png_ptr, info_ptr) == 1) {
155 } else if (png_get_channels(png_ptr, info_ptr) == 4
156 && png_get_bit_depth(png_ptr, info_ptr) == 8) {
161 fprintf(stderr, "Invalid PNG! Only mono or mono 4x8-bit RGBA PNG files are allowed\n");
165 width = png_get_image_width(png_ptr, info_ptr);
166 height = png_get_image_height(png_ptr, info_ptr);
168 png_read_update_info(png_ptr, info_ptr);
171 if (setjmp(png_jmpbuf(png_ptr)))
172 abort_("[read_png_file] Error during read_image");
174 row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
176 rowbytes = type == 1 ? (width / 8) + (width % 8 > 0) : width << 2;
178 for (y=0; y<height; y++)
179 row_pointers[y] = (png_byte*) malloc(rowbytes);
181 png_read_image(png_ptr, row_pointers);
185 lb = (height / 8) + (height % 8 > 0);
186 bitmap = malloc(width*lb);
187 memset(bitmap, 0, width*lb);
189 #define heat_on(x, y) bitmap[(x*lb)+(y/8)] |= 1 << (7-(y%8))
190 for (y=0; y<height; y++) {
191 png_byte* row = row_pointers[y];
192 for (x=0; x<width; x++) {
198 if ((ptr[0] & (1 << (7-(x%8)))) == 0) {
205 pngdata_t * ret = malloc(sizeof(pngdata_t));
212 int main(int argc, const char ** argv)
215 fprintf(stderr, "Usage: %s printer pngfile\n", argv[0]);
220 pngdata_t * data = loadpng(argv[2]);
222 printf("w: %d\th: %d\n", data->w, data->h);