I'm working on some code to print an image from an Android device to a Bixolon SPP-R200. From what I can tell, it emulates ESC POS. I noticed that there are two commands for printing images. "Select bit-image mode" (ESC *) or "Print raster bit image" (GS v 0).
What's the difference between these two commands? Why would I choose one command over the other?
Related
I'm trying to batch scale a load of xpm images to double pixel size. I can do this using ImageMagick like this:
convert infile.xpm -sample 200% outfile.xpm
However, the symbolic colour names are lost.
In the original input, the colour entries are as follows:
". c #007EBF s active_hilight_1",
"+ c #0A5E89 s active_color_1",
"# c #143D52 s active_shadow_1",
In the up-scaled version:
" c #143D52",
". c #0A5E89",
"X c #007EBF",
The colour names changed, which is fine, but as you can see the s <symbolic-name> suffixes are stripped.
Does anyone know a quick way to do this using ImageMagick or a similar (open-source) utility?
Thanks
EDIT: Seems ImageMagick can't due this due to a bug, but does anyone know any other tool which may be able to do this?
mogrify -sample 200% *.xpm
^ This works as long as you have a new (post 2019-09-02) version of ImageMagick with the xpm output bug fixed, as described here:
https://github.com/ImageMagick/ImageMagick/issues/1684
Today's master branch, for example, passes symbolic colour names through properly.
I want to print a bitmap logo file with ESC POS command ESC*.
Following is the link for technical documentation of the command.
https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=88
According to me, the printer requires the image data in the form of 1s and 0s. So, it prints a dot, with the occurrence of 1 and blank, with the occurrence of 0.
But I am not able to figure out how to send multi line bit image data with the help of above command, since the command accepts only the image data in the horizontal direction. Please help me with the problem.
ESC * is one of several "bit image" commands in ESC/POS. It accepts "column format" data, which can only represent a single line of either 8 or 24 pixels. So there are two good options here.
Print multiple lines using ESC *
It sounds like you are able to print one line, so I will assume that the data format itself is not an issue.
You can print multiple lines by simply repeating the command to print the extra lines, separated by line breaks \n. This requires chopping up the image, and padding it with whitespace so that it is a multiple of 8 or 24 pixels in height (again, due to the format).
Because of line spacing, you need to issue a command to change the size of line feeds during the image print, then another command to reset them at the end.
I use ESC 3 0x10 for 16-unit line feeds (bytes 0x1b 0x33 0x10) and ESC 2 (bytes 0x1b 0x32) to reset.
Example of column format bit image printing in Python using ESC *
Example of column format bit image printing in PHP using ESC *
This method of printing has excellent compatibility with old printers, but you can get some thin horizontal lines in the output.
Print the entire image with GS v 0
This bit image command accepts the different "raster format" data. I make use of the fact that the blob in this format is identical to the binary data in the widely implemented PBM bitmap format (specifically the binary data in files with the P4 header).
The height of the image will be limited by your print buffer size, but could go up to 65535 pixels. The width must be divisible by 8 because of the representation.
Example of raster format bit image printing in Python using VS v 0
Example of raster format bit image printing in PHP using GS v 0
Side note: These snippets the actual prototypes of the image processing code that now appears in the popular open source escpos-php and python-escpos libraries. Using an existing library has a number of benefits, and you should consider it if it's an option.
We have a POS application we have developed that can use any ESC/POS printer via MS POS.Net v1.12. Our application runs fine with Epson printers, but with a Star TSP700 it prints correctly, but it "stutters"/line-by-line (think calling PrintNormal repeatedly rather than using a StringBuilder and dumping it all at once into the queue). Setting the dip switch to what should be ESCPOS emulation does nothing, as I don't think the USB interface supports that according to the docs found on page 98 of https://www.star-m.jp/eng/service/usermanual/tsp700um.pdf. I am building a string and dumping it all at once using Transaction printing in OPOS. The print speed to the customer is unacceptable and replacing 100 printers is also not acceptable. There is another mode we use to connect to the printer aside from OPOS, and that is setting up the printer as a "Generic / Text Only" printer and then I send the escape codes to the printer, but it doesn't print everything out correctly at all - I imagine this is because the printer is expecting Star Line commands.
Phew. Anyone have any input on what to try? Worst case scenario I build in printing via Star commands, so all is not lost, and I'm going to try HexDump mode first to see if I am missing anything, but I would much prefer to not write out a whole library just to handle Star printers if I can avoid it.
ESC + | + N on an Epson printer resets the font to normal after setting it to big, bold, etc. However, this causes the Star to stutter to the point of shaking violently. I was able to remove that escape sequence from my code and have it not affect the output from Epson printers, so now the Star stutters less. Note, it doesn't stop stuttering, it prints 50 lines, flips out for 2 or 3 lines, and repeats. It's really a huge improvement if you are able to see the printer print before and after the fix.
When I run Apple's Automator to simply cut a bunch of images in their size Automator will also reduce the quality of the files (jpg) and they get blurry.
How can I prevent this? Are there settings that I can take control of?
Edit:
Or are there any other tools that do the same job but without affecting the image quality?
If you want to have finer control over the amount of JPEG compression, as kopischke said you'll have to use the sips utility, which can be used in a shell script. Here's how you would do that in Automator:
First get the files and the compression setting:
The Ask for Text action should not accept any input (right-click on it, select "Ignore Input").
Make sure that the first Get Value of Variable action is not accepting any input (right-click on them, select "Ignore Input"), and that the second Get Value of Variable takes the input from the first. This creates an array that is then passed on to the shell script. The first item in the array is the compression level that was given to the Automator Script. The second is the list of files that the script will do the sips command on.
In the options on the top of the Run Shell Script action, select "/bin/bash" as the Shell and select "as arguments" for Pass Input. Then paste this code:
itemNumber=0
compressionLevel=0
for file in "$#"
do
if [ "$itemNumber" = "0" ]; then
compressionLevel=$file
else
echo "Processing $file"
filename="$file"
sips -s format jpeg -s formatOptions $compressionLevel "$file" --out "${filename%.*}.jpg"
fi
((itemNumber=itemNumber+1))
done
((itemNumber=itemNumber-1))
osascript -e "tell app \"Automator\" to display dialog \"${itemNumber} Files Converted\" buttons {\"OK\"}"
If you click on Results at the bottom, it'll tell you what file it's currently working on. Have fun compressing!
Automator’s “Crop Images” and “Scale Images” actions have no quality settings – as is often the case with Automator, simplicity trumps configurability. However, there is another way to access CoreImage’s image manipulation facilities whithout resorting to Cocoa programming: the Scriptable Image Processing System, which makes image processing functions available to
the shell via the sips utility. You can fiddle with the most minute settings using this, but as it is a bit arcane in handling, you might be better served with the second way,
AppleScript via Image Events, a scriptable faceless background application provided by OS X. There are crop and scale commands, and the option of specifying a compression level when saving as a JPEG with
save <image> as JPEG with compression level (low|medium|high)
Use a “Run AppleScript” action instead of your “Crop” / “Scale” one and wrap the Image Events commands in a tell application "Image Events" block, and you should be set. For instance, to scale the image to half its size and save as a JPEG in best quality, overwriting the original:
on run {input, parameters}
set output to {}
repeat with aPath in input
tell application "Image Events"
set aPicture to open aPath
try
scale aPicture by factor 0.5
set end of output to save aPicture as JPEG with compression level low
on error errorMessage
log errorMessage
end try
close aPicture
end tell
end repeat
return output -- next action processes edited files.
end run
– for other scales, adjust the factor accordingly (1 = 100 %, .5 = 50 %, .25 = 25 % etc.); for a crop, replace the scale aPicture by factor X by crop aPicture to {width, height}. Mac OS X Automation has good tutorials on the usage of both scale and crop.
Eric's code is just brilliant. Can get most of the jobs done.
but if the image's filename contains space, this workflow will not work.(due to space will break the shell script when processing sips.)
There is a simple solution for this: add "Rename Finder Item" in this workflow.
replace spaces with "_" or anything you like.
then, it's good to go.
Comment from '20
I changed the script into a quick action, without any prompts (for compression as well as confirmation). It duplicates the file and renames the original version to _original. I also included nyam's solution for the 'space' problem.
You can download the workflow file here: http://mobilejournalism.blog/files/Compress%2080%20percent.workflow.zip (file is zipped, because otherwise it will be recognized as a folder instead of workflow file)
Hopefully this is useful for anyone searching for a solution like this (like I did an hour ago).
Comment from '17
To avoid "space" problem, it's smarter to change IFS than renaming.
Back up current IFS and change it to \n only. And restore original IFS after the processing loop.
ORG_IFS=$IFS
IFS=$'\n'
for file in $#
do
...
done
IFS=$ORG_IFS
Many printers have a "feed and cut" or "cut paper" command (I'm talking about POS - printers here).
Since using POS.NET is not always possible (horrific driver incompatibilities) and GDI can do so much more, we would like to utilize the paper cutter also when printing using GDI.
Is there a way to do so? Possibly when issuing EndDocument()?
Or maybe even from .NET?
GDI and even the abstract Windows printing model are probably not going to help you here. You're going to have to send the feed and cut command to the printer in the language that it expects to typically receive data.
For example, an Epson TM-T88III thermal receipt printer speaks the ESC/POS language natively, not a sequence of GDI or PCL commands. However, most of these printers do come with printer drivers that make Windows see them as regular GDI printers. The way these drivers typically work is that they rasterize all of the GDI commands into one big bitmap in software, and then dole out the bitmap to the printer for printing via its native-language "print the bit-image" command. This usually has less-than-desirable effects:
It is much less efficient (in sense of time required and data transmitted) to send a lot of bitmap data to the printer than a sequence of binary commands that it knows how to interpret. (Would you rather send an image of text to print, or just the actual text and a font size specification? Analogies with HTML/CSS vs. an image of text.)
These printers typically have low resolutions and are monochrome (that is, all black or all white, no grayscale or color). Their pre-loaded fonts are designed to work well under these limitations for crisp, clear rendering. By rasterizing to a bitmap, we lose this careful design as pixels are snapped and rounded off of the grid, resulting in jagged text rendering on the actual printout. If you're trying to draw something that's really sensitive to this kind of rounding, like a barcode, you're SOL, unless you're painstakingly keeping the DPI of the printer device context in mind while working with GDI.
For example, here is a snippet of code from an extensive example on my usually-irrelevant blog. You can see near the end how I fill the BinaryWriter with the necessary sequence of bytes that equals the "feed paper and cut" command on our Epson thermal receipt printer (AsciiControlChars is just a static class with constants):
using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
{
// Reset the printer bws (NV images are not cleared)
bw.Write(AsciiControlChars.Escape);
bw.Write('#');
// Render the logo
RenderLogo(bw);
// Feed 3 vertical motion units and cut the paper with a 1 point cut
bw.Write(AsciiControlChars.GroupSeparator);
bw.Write('V');
bw.Write((byte)66);
bw.Write((byte)3);
bw.Flush();
return ms.ToArray();
}
You can then just send the bytes directly to the printer as a RAW document, either using the code at the end of that article, which works against various Win32 printer functions, or Microsoft's RawPrinterHelper class.
You'll need to look up the commands specific for your printer. Chances are that its not too different from the one that you see here: POS languages are beginning to standardize, but that's also like saying SQL is a standard--mutually intelligible by humans but not really interoperable without some adjustments.
If you really still want to use GDI, you can print the GDI document in the usual way to the printer (again, assuming that a GDI printer driver exists, which it probably does), and then issue a second, small, RAW document to the printer that contains the native feed and cut command. (Alternatively, some of the GDI printer drivers let you specify "always cut after printing a document" right in the Printers control panel--but good luck accessing that driver feature in a well-documented fashion programmatically!)
Hope this helps to paint a picture of GDI's relationship to POS printers.