Skip to content

Instantly share code, notes, and snippets.

@ekovac
Created August 22, 2012 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ekovac/3427632 to your computer and use it in GitHub Desktop.
Save ekovac/3427632 to your computer and use it in GitHub Desktop.
Tool to create an ESC/P custom character stream from a monochrome image to enable graphical printing on some printers which fail to do so using the CUPS ESC/P driver.
#include <stdio.h>
#include <stdlib.h>
#include <pam.h>
#define CELL_HEIGHT 8
#define CELL_WIDTH 11
typedef struct
{
char* c;
int width;
int height;
} raw_image;
typedef struct
{
unsigned char cell_bytes[CELL_WIDTH];
} cell;
typedef struct
{
cell* cells;
int width;
int height;
} image;
image cellify_image(raw_image raw)
{
image img;
int ceil,x,y,subx, suby;
unsigned char imgbyte;
unsigned char tmpbyte;
size_t cell_location, global_location, tmp_location;
ceil = raw.width % CELL_WIDTH ? 1 : 0;
img.width = raw.width/CELL_WIDTH+ceil;
ceil = raw.height % CELL_HEIGHT ? 1 : 0;
img.height = raw.height/CELL_HEIGHT+ceil;
img.cells = malloc(img.height*img.width*sizeof(cell));
for (y = 0; y < img.height; y++)
{
for (x=0; x < img.width; x++)
{
cell_location = (size_t)(y*img.width+x);
global_location = (size_t)(y*CELL_HEIGHT*raw.width+CELL_WIDTH*x);
for (subx = 0; subx < CELL_WIDTH; subx++)
{
imgbyte = 0x00;
for (suby = CELL_HEIGHT - 1; suby > -1; suby--)
{
if (((suby+CELL_HEIGHT*y) >= raw.height)||
((subx+CELL_WIDTH*x) >= raw.width))
continue;
tmp_location = global_location +suby*raw.width+subx;
if (raw.c[tmp_location] == 0) imgbyte = imgbyte | (1 << (7-suby));
}
img.cells[cell_location].cell_bytes[subx] = imgbyte;
fprintf(stderr, "%x\n", imgbyte);
}
}
}
fprintf(stderr, "Cells %dx%d\n", img.width, img.height);
return img;
}
void printreset()
{
static unsigned char resetbytes[2] = {0x1b, 0x40};
fwrite(resetbytes, 2, 1, stdout);
}
void println()
{
static unsigned char newline[4] = { 0x1b, 0x41, 0x08, 0x0a };
fwrite(newline, 4, 1, stdout);
return;
}
void printcell(cell c)
{
int i;
unsigned char defineandprint[21] =
{
0x1b, 0x26, 0x00, 0x41, 0x41, 0x0b, /* Begin define */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* char data */
0x1b, 0x25, 0x01, /* switch to user-defined */
0x41, }; /* printing the defined character */
for (i = 0; i < CELL_WIDTH; i++)
{
defineandprint[6+i] = c.cell_bytes[i];
}
fwrite(defineandprint, 21, 1, stdout);
return;
}
void printimage(image img)
{
int x, y;
printreset();
for (y=0; y < img.height; y++)
{
for (x=0; x < img.width; x++)
{
printcell(img.cells[y*img.width+x]);
}
println();
}
printreset();
}
raw_image parse_image_to_array(FILE* f)
{
struct pam inpam, outpam;
tuple* tuplerow;
unsigned int row, column;
int x,y;
pm_init("./a.out", 0);
pnm_readpaminit(f, &inpam, PAM_PGM_TUPLETYPE);
tuplerow = pnm_allocpamrow(&inpam);
raw_image img;
img.c = (char*)malloc(inpam.height*inpam.width*sizeof(char));
for (y = 0; y < inpam.height; y++)
{
pnm_readpamrow(&inpam, tuplerow);
for (x = 0; x < inpam.width; x++)
{
img.c[y*inpam.width+x] = tuplerow[x][0];
// fprintf(stderr, "%x\n", tuplerow[x][0]);
}
}
img.height = inpam.height;
img.width = inpam.width;
fprintf(stderr, "Raw %dx%d\n", img.width, img.height);
fflush(stderr);
return img;
}
int main(int argc, char* argv[])
{
FILE* f = NULL;
int width;
char* image;
if (argc != 2)
{
fprintf(stderr, "You need to pass a file as an argument.\n");
return 1;
}
f = fopen(argv[1], "r");
if (f == NULL)
{
fprintf(stderr, "It broke.\n");
}
printimage(cellify_image(parse_image_to_array(f)));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment