ESC-POS codes for printing image data in page mode - printing

I'm having difficulty printing an image data in page mode. I'm been able to print image data in standard mode as follows:
data[] = { ESC ,
'*' ,
0 , // 8-dot single density mode
width , // nl: image width
0 } // nh: image width
for each 8 x image_width block of pixels in a monochrome image
for each 8 x 1 (vertical) strip of pixels in the block
append pixel (0 or 1) data to the array, data[]
write data to COM port
My (unsuccessful) attempt at printing in page mode is a variation of the above and proceeds as follows:
select page mode by writing the chars, ESC and 'L' to the COM port
write pixel data as described above
print by writing the characters ESC and FF
What am I doing wrong? Do I have to specify a print region or something of the sort?
BTW, I'm programming an Epson TM-T88III.

Found the answer. Write ESC J n (print and paper feed) command after writing after each 8 x image_width block of pixels to the COM port.

Related

OpenCV Encoding to H264 changing original RGB pixel values for gray images

I have the following issue:
I'm creating a uniform gray color video (for testing) using OpenCV VideoWriter. The output video will reproduce a constant image where all the pixels must have the same value x (25, 51, 76,... and so on).
When I generate the video using MJPG Encoder:
vw = cv2.VideoWriter('./videos/input/gray1.mp4',
cv2.VideoWriter_fourcc(*'MJPG'),
fps,(resolution[1],resolution[0]))
and read the output using the VideoCapture class, everything just works fine. I got a frame array with all pixel values set to (25,51,76 and so on).
However when I generate the video using HEV1 (H.265) or also H264:
vw = cv2.VideoWriter('./videos/input/gray1.mp4',
cv2.VideoWriter_fourcc(*'HEV1'),
fps,(resolution[1],resolution[0]))
I run into the following issue. The frame I got in BGR format follows the next configuration:
The blue channel value is the expected value (x) minus 4 (25-4=21, 51-4=47, 76-4=72, and so on).
The green channel is the expected value (x) minus 1 (25-1=24, 51-1=50, 76-1=75).
The red channel is the expected value (x) minus 3 (25-3=22, 51-3=48, 76-3=73).
Notice that the value is reduced with a constant value of 4,1,3, independently of the pixel value (so there is a constant effect).
What I could explain is a pixel value dependable feature, instead of a fixed one.
What is worse is that if I choose to generate a video with frames consisting in every color (pixel values [255 0 0],[0 255 0] and [0 0 255]) I get the corresponding outputs values ([251 0 0],[0 254 0] and [0 0 252])
I though that this relation was related to the grayscale Y value, where:
Y = 76/256 * RED + 150/256 * GREEN + 29/256 * BLUE
But this coefficients are not related with the output obtained. Maybe the problem is the reading with VideoCapture?
EDIT:
In case that I want to have the same output value for the pixels (Ej: [10,10,10] experimentally I have to create a img where the red and blue channel has the green channel value plus 2:
value = 10
img = np.zeros((resolution[0],resolution[1],3),dtype=np.uint8)+value
img[:,:,2]=img[:,:,2]+2
img[:,:,1]=img[:,:,1]+0
img[:,:,0]=img[:,:,0]+2
Anyone has experience this issue? It is related to the encoding process or just that OpenCV treats the image differently, prior encoding, depending on the fourcc parameter value?

8086 Assembly: wrong data reading video memory

I'm working for a school project on a little game programmed in 8086 Assembly language.
I have to draw on the screen (color some pixels), to do so I use interrupt 10h with mode 13h (ax = 13h). This is a 320px X 200px video mode.
(Note: you can best read the text underneath with the code opened in another tab (you will better understand what I'm explaining in words))
I want to first initialize the screen so I'm sure each pixel is black. To do so I first initialize a palette with black = color number 0.
After that I use a primitive for loop procedure I wrote to initialize the screen (set each pixel black). I pass as arguments respectively the start index (index in video memory (i.e 0 for the first pixel)), the stop index (64 000, last pixel (320px X 200px = 64 000)) and the step size with which the index has to be incremented.
So all it does is looping from the specified begin adres to the specified stop adres in memory and for each adres putting it on 0 (because black = color number 0 of the palette).
So normally now every pixel of my screen is black. Indeed when I launch my little program, the 320x200 video mode appears and the screen is black.
Further in the program I often have to compare the color of a pixel on the screen. Normally when i acces a certain adress in the video memory it has to be 0 (because I initialized the whole screen on black (color number 0)) except if I colored that pixel with another color.
But when testing my program I found out that certain pixels were black on the screen (and since the initialization I never changed their color) but when I displayed their value, it appeared to be 512 instead of 0. I can not understand why, since I never changed the color since I initialized them.
I spent hours trying to debug it but I cannot figure out why that pixel suddenly changes from color number 0 of the palette (black) to 512.
Because the pixel with color value 512 is also black on the screen I suppose that is also a value for that color but I want explicitly use color number 0 for black so that I can compare it (because now there is 0 but also 512 for black and maybe other black values).
Relevant part of the code:
mov ax, 0a000h ; begin address of video memory
mov es, ax
mov ax, [bp+4][0] ; We put the 1st argument (index) in register ax
mov di, ax
;;;; FOR DEBUGGING PURPOSES
mov ax, es:[di]
push ax ; We print the color of the pixel we are checking (normally has to be 0 if that pixel is black on the screen)
call tprint ; 70% of the time the printed color number is 0 but sometimes it prints color number 512 (also a black color but I don't want that, I initialized it to 0!!)
;;;; END DEBUG
;;;; ALSO STRANGE IS THAT WHEN I OUTCOMMENT THESE 3 LINES ABOVE, THE LAST PIXEL OF THE FIRST ROW IS COLORED
;;;; WHEN I LEAVE THESE 3 LINES LIKE NOW (PRINTING THE VALUE OF THAT PIXEL) IT IS THE NEXT PIXEL THAT IS COLORED
;;;; (strange but i don't really care since it was introduced only to debug)
CMP es:[di], 0 ; Comparison to see if the pixel we are checking is black.
; But when it is 512, my program will think it isn't the black color, and will stop executing (because after this call I do a JNZ jump to quit the loop)
Thanks for your help!
As #nrz hinted, the problem is with data size, although slightly different than what he described. Actually you are loading 2 bytes, so 2 pixels at once instead of 1. You get a value of 512 if a pixel with color 0 is beside a pixel with color 2.
You need to change line 182 to movzx ax, byte ptr es:[di] and line 190 to cmp byte ptr es:[di], 0 (use whatever syntax your assembler supports for byte operations).

Plot an array into bitmap in C/C++ for thermal printer

I am trying to accomplish something a bit backwards from everyone else. Given an array of sensor data, I wish to print a graph plot of it. My test bench uses a stepper motor to move the input shaft of a sensor, stop, get ADC value of sensor's voltage, repeat.
My current version 0.9 bench does not have a graphical output. The proper end solution will. Currently, I have 35 data points, and I'm looking to get 90 to 100. The results are simply stored in an int array. The index is linear, so it's not a complicated plot, but I'm having problems conceptualizing the plot from bottom-left to top-right to display to the operator. I figure on the TFT screen, I can literally translate an origin and then draw lines from point to point...
Worse, I want to also print out this to a thermal printer, so I'll need to translate this into a sub-384 pixel wide graph. I'm not too worried about the semantics of communicating the image to the printer, but how to convert the array to an image.
It gets better: I'm doing this on an Arduino Mega, so the libraries aren't very robust. At least it has a lot of RAM for the code. :/
Here's an example of when I take my data from the Arduino test and feed it into Excel. I'm not looking for color, but I'd like the graph to appear and this setup not be connected to a computer. Or the network. This is the ESC/POS printer, btw.
The algorithm for this took three main stages:
1) Translate the Y from top left to bottom left.
2) Break up the X into word:bit values.
3) Use Bresenham's algorithm to draw lines between the points. And then figure out how to make the line thicker.
For my exact case, the target bitmap is 384x384, so requires 19k of SRAM to store in memory. I had to ditch the "lame" Arduino Mega and upgrade to the ChipKIT uC32 to pull this off, 32k of RAM, 80 MHz cpu, & twice the I/O!
The way I figured out this was to base my logic on Adafruit's Thermal library for Arduino. In their examples, they include how to convert a 1-bit bitmap into a static array for printing. I used their GFX library to implement the setXY function as well as their GFX Bresenham's algorithm to draw lines between (X,Y)s using my setXY().
It all boiled down to the code in this function I wrote:
// *bitmap is global or class member pointer to byte array of size 384/8*384
// bytesPerRow is 384/8
void setXY(int x, int y) {
// integer divide by 8 (/8) because array size is byte or char
int xByte = x/8;
// modulus 8 (%8) to get the bit to set
uint8_t shifty = x%8;
// right shift because we start from the LEFT
int xVal = 0x80 >> shifty;
// inverts Y from bottom to start of array
int yRow = yMax - y;
// Get the actual byte in the array to manipulate
int offset = yRow*bytesPerRow + xByte;
// Use logical OR in case there is other data in the bitmap,
// such as a frame or a grid
*(bitmap+offset)|=xVal;
}
The big point is to remember with an array, we are starting at the top left of the bitmap, going right across the row, then down one Y row and repeating. The gotchya's are in translating the X into the word:bit combo. You've got to shift from the left (sort-of like translating the Y backwards). Another gotchya is one-off error in bookkeeping for the Y.
I put all of this in a class, which helped prevent me from making one big function to do it all and through better design made the implementation easier than I thought it would be.
Pic of the printout:
Write-up of the project is here.

image processing bitwise instruction conceptual interpretation

the code comes from a Qt library that helps produce buttons with the shape of an image; it scans through all lines y and all the width x, generating the following change when the rgb part of the pixel coincides with the masking one (mp is the pointer at the start of the line and it is prefilled with 0xff):
*(mp + (x >> 3)) &= ~(1 << (x & 7));
I can't really interpret it; anyone with background to give a hand?
From the looks of the code, mp points to the current line of a 1 bit per pixel image. The code clears the bit representing the pixel at X. It converts the X offset into a byte offset (x >> 3) and then logical AND's the byte with a mask created from the inverse 1 shifted left by the X position within the byte.
for the mortals; ok, background: http://www.cprogramming.com/tutorial/bitwise_operators.html; &= means we are gonna do a bitwise multiplication; in the rhs, the ~ is for the complement, so it flips 1s with 0s and viceversa; 7 in binary has 3 ones in the end and all zeros at front, so x & 7 preserves the last 3 bits in x; combined with << this will move the 1 in the first bit from the char 1 to the left a certain number of places in accordance with the exponent; since the exponent is only using the last 3 bits of x, it is smaller than 8(2^3); so the bit with the one will get in the position 1-8 within the 8 bits of the char; the flip ~ will turn the thing into all 1s except in that magic position; the multiplication performed by the &= will preserve everything in the lhs except that one bit. now for the lhs; we are kicking the last byte or the last 3 bits of x out with >> in a right shift operation; this means the location we'll modify the same byte (char type of mp) for every 8 increments of x; when we "jump", we'll do so by only one byte; when x=9 it will go to mp+1, when x= 17 it will go to mp+2; so it is like x/2^3 in integer operations, but in one shift operation; ok, now we have the elements to understand the whole thing;
tmask has been prefilled with 0xff, all ones; which means that it will be passive upon the &= operation, preserving what the rhs dictactes; this means that in case the there's a hit in an if statement that checks if the particular pixel is equal to the background, then this line is executed and we will wipe the specific bit related to the pixel;

How to convert monochrome image to bitwise format for thermal printer

I'm using a Custom s'print DPT100-S thermal printer to made a receipt printing application.
It is able to print graphics using 384 pixels in one line. This data has to be passed on to the printer using 48 bytes (48x8=384). So, each 'bit' represents one dot to be printed (bit will be '0' for white and '1' for black).
So, I need to create a program which will read a monochrome BMP generated in Windows Paint(or any other program) and convert it into this bit format using a C program in Linux.
Please guide me.
Pseudo code:
Read BMP
For each row in BMP
For each group of 8 pixels in row
output_byte = 0
For each pixel in current group of 8
output_byte <<= 1 // shift output_byte left by one bit
output_byte |= (pixel != 0) // set rightmost bit in output_byte
// according to input pixel value
Save output_byte in bitmap
Take a look at halftoning.
A quick Google will get you references and Java applet like here: http://www.markschulze.net/halftone/index.html
If you don't have to create your own program and you are happy to use off the shelf software, try ImageMagick's convert command: http://www.imagemagick.org/Usage/quantize/#halftone
e.g.
convert myfile.jpg -colorspace Gray -ordered-dither h4x4a printable-file.bmp
This link has a software called LCD assistant which does the same thing as you need. You have to use paint to convert any image to bitmap and then import that bmp image into the software. The output you can choose to be 384 X xyz. You get the output pixels in HEX.

Resources