Feature Request - ZPL Format

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
rspadim
Posts: 2
Joined: 2012-08-10T21:34:57-07:00
Authentication code: 67789

Feature Request - ZPL Format

Post by rspadim »

Hi guys, today i convert images to ZPL format (Zebra label printer) using a PHP script
i want a solution in imagemagick, since some times i don´t have PHP to execute this job

i was reading corders/mono.c at source code, and zpl image representation is very near
instead of a binary string, we need string representation of hexdecimal bytes and rounded widths of image (rounded in 8 pixels -> zpl width = ceil(image width/8)*8)

for example
a image of 4x3 pixel (3=height) MUST be changed to 8x3 pixel and new pixels will be white (in binary = 0), image start from TOP LEFT and run to RIGHT each line, after line end, it jump one line down, and get back to left like a "\n\r" (new line, carrier return), as a standard each line end with a "\n" (newline) character (can be removed or use "\r\n" or "\n\r")

for example... a binary image of 4x3 black/white:

Code: Select all

1100  (black,black,white,white)
0110  (white,black,black,white)
0011  (white,white,black,black)
will be resized and converted to hexadecimal string

Code: Select all

binary => hexadecimal string
11000000 => "C0\n"
01100000 => "60\n"
00110000 => "30\n"
ZPL will interpret "C0" as black (1),black (1),white (0),white (0),white (0),white (0),white (0),white (0)

check that it ALWAYS need 2 bytes of hexadecimal information
in manual it say that each char is one niblle of pixel (4pixels), but using printer (ZEBRA S600, S4M, S400, Z4M) i checked that for each line we need one full byte information, in others words, we reaaalllyyyy need 8pixels, a line of 4 pixel don´t work
example, an image of 4x3: "C\nC\nC\n", MUST be converted to 8x3: "C0\nC0\nC0\n"

---
after convert to a hexadecimal string, we must set some info to send this image to printer, we can call this as ZPL Image HEADER... it tell what the name of file inside printer memory, image format (ascii,png,others) and tell the width/height of image, from my PHP script we have:

Code: Select all

"~DY$name,a,G,$bytes,$bytes_per_row,\n$zebra_image\n"

$name = name of file, 8 bytes + ".GRF", like FAT16 filesystem names, example: "ABCDEFGH.GRF"
as default (in manual) if we don´t know the name we could use: "UNKNOWN.GRF", since we have some problem with image names, we could put it to always use UNKNOWN.GRF or as a optional especific ZPL parameter at "convert" program, for example: "convert -format ZPL -zplname ABC.GRF image.png image.grf"

$bytes_per_row = ceil(width of image / 8)
"CO" = 8 bits = 1 byte, if we have a image of 3x4, we should resize to 8x4, and divide 8pixels of 'width' to 1byte of 'size'

$bytes = total number of bytes in image, in our example:
"C06030" => 8bits+8bits+8bits = 24bits = 24/8 = 3 bytes

$zebra_image = ASCII representation of image pixels from top left to right, after one line jump to next bottom line and get back to left, like a "\n\r" in bash terminal
now we can have the file:

Code: Select all

"~DYUNKNOWN.GRF,a,G,3,1,\n"
"CO\n"
"60\n"
"30\n"
any doubt? could anyone implement this?
there´s some compression that we can implement but as a first version this works for 90% of zpl files

compressions:
":" string in ZPL picture = repeat last line

if we repeat one line for example:
"CO\nCO\n60\n30\n"
we can rewrite it as:
"CO\n:\n60\n30\n"
this is good for very big lines of white or black pixels (normally a label have many white line, and just some black+white line, and more many white lines)

"," put 0 from current position to end of line
"!" put 1 from current position to end of line
for example
"!!!" = 3 lines of 1111111111111111111111111111111111111111111... (black)
",,," = 3 lines of 0000000000000000000000000000000000000000000... (white)
"12341!\n" = 12341+1111111111111111111111111111...
"FF," = FF+000000000000000...


some others compressions exists, for example a big line of "0000000000000" can be rewrite in another string using some algorithm like RLE, but i never used and never tested, i know it exists but i don´t know if anyone use it...
MORE ABOUT THIS TYPE OF COMPERSSION CAN BE FOUNDED IN MANUAL... (CHECK END OF POST)





---------------
some more information can be founded here:
http://www.ptshome.com/kb/Manuals/ZPL_Vol2.pdf

at page 38: ~DG COMMAND OPTIONS (CHECK THAT WE CAN USE ~DY OR ~DG, ANYONE WORKS, but DY have more parameters - allow png,ascii compressed and others options, but not all ZPL printers support compression and PNG...)

at page 39: explanation about ASCII image parameter of ~DG command
The data string defines the image and is an ASCII hexadecimal representation of the image. Each character represents a horizontal nibble of four dots.

more about image format can be founded here:

http://www.omnihost.us/files/Zebra/1390 ... Stripe.pdf
at page 105 (DG COMMAND)

more about compression can be founded here, but it uses ~DG and not ~DY
http://www.ptshome.com/kb/Manuals/ZPL_Vol2.pdf
page 71




----------------
now... how to read from a GRF file to write a picture...
first... find ~DY or ~DG string....
after founded...
if ~DY the format is: ~DY[FILENAME],[FORMAT],[EXTENSION],[BYTES IN FILE],[BYTES PER ROW],[DATA]
so first find format.. it must be = "a"
find EXTENSION.. it must be = "G"
find bytes in file.. it must be a unsigned interger, zebra memory have about 32MB of ram, we could use a unsigned int of 32 bits to handle any kind of image...
find bytes per row... it must be multiple of bytes in file, for example...
bytes in file = 10, 10/bytes per row must be a integer, in other words...
10/1 = 10 (integer => 10 lines, 1*8 pixels per line)
10/2 = 5 (integer => 5 lines, 2*8 pixels per line)
10/3 = 3.333 ( not a integer, invalid information, don´t convert image)
10/4 = 2.5 (not a integer, invalid information, don´t convert image)
10/5 = 2 (integer => 2 lines, 5*8 pixels per line)
....
10/10 = 1 (integer => 1 lines, 10*8pixels per line)

for ~DG command-> format is: ~DG[FILENAME],[BYTES IN FILE],[BYTES PER ROW],[DATA]

check that ~DY and ~DG can have "\n" (new line) and "\r" (carrier return) after last "," (comma) for example
~DGABC.GRF,10,2,
ADAD
ADAD
ADAD
ADAD
ADAD
-- end of file
that´s because [DATA] when interpreted by print will only accept some characters... (we will not implement cancel commands: "~JA", "~JP", "~JX", "~DN")
the characters accepted as pixel informations are [0-9][a-z][A-Y][:][!][,]

--
well now to convert data to pixels...
we have bytes per line... start painting pixel per pixel, start from top left, go to right on first line, end of line, go to next line return to first pixel of left, starting painting again... i don´t know if exists a function to paint without 2d (x,y) information... some thinking like: 5 pixels per line... paint(black,20) it will paint black on y=5 x=0, if it exists well paint will be more more easy... just read pixel information and write, doesn´t matter line... the file is a continous string of each pixel in image....

ok... start reading file... allow caracters: [0-9][A-F][:][!][,] i never used [a-f] but i think it should work like [A-F]...

for others compressions [G-Y][g-z]
check that for compression [G-Y] != [g-y]

image will be always BLACK AND WHITE


--------------------
if you want more help please contact me, i have a IMAGE to GRF, and a GRF to IMAGE PHP script, my email: rspadim at gmail dot com
but please only contact if you want to develop it to imagemagick code

thanks guys!
rspadim
Posts: 2
Joined: 2012-08-10T21:34:57-07:00
Authentication code: 67789

Re: Feature Request - ZPL Format

Post by rspadim »

example of IMAGE and GRF representation:
BLACK/WHITE GIF:
http://www.spadim.com.br/friozer.gif

GRF:

Code: Select all

~DYUNKNOWN.GRF,a,G,4980,30,
0000000000000000000001FFF77777FF0000000000000000000000000000
00000000000000000001FF5204888825BF00000000000000000000000000
0000000000000000007EA244A244440242DE000000000000000000000000
00000000000000000FE4952914891249080AFC0000000000000000000000
0000000000000001F51149108910890480800B6000000000000000000000
000000000000001F4A4A924A524924921221002F00000000000000000000
00000000000000FA54A444A52424424020002201F0000000000000000000
000000000000074949492912494889248484000017800000000000000000
0000000000007A94A4929249109110900808888800F80000000000000000
000000000003E52949292494A522224000420000000B8000000000000000
00000000000E529444944942424444225A00222200007800000000000000
000000000074A5252A5292949488888815FD000000000600000000000000
0000000001D512929109250909110040E80AF500000001C0000000000000
000000000F2AA52524AA4A525222251057E816F500000060000000000000
000000003A94A9525544942424444244903FC815F0000018000000000000
00000000D52952A549292949488889106F4037A80A000008000000000000
00000003529495112492509252511088817E88AF68000004000000000000
0000000EA552A4AA4AA4A524892222217D017D4157800002000000000000
0000003954A9524524494949444444100BEA05BD20400001000000000000
000000EAA9254AAA5292929128888842D017EA02DE800001800000000000
000003552A9295112949250891111110AF5017F505400000800000000000
00000EA94955294AA52A4A5522224448416FD02B6A000000400000000000
00003A9554A494A44944942249442222BC80BEA02BE00000400000000000
00006AAAA549294A92925294A4924880037D015F50200000200000000000
0001D552552A92515129094911091051688AF5016F500000200000000000
0002AA54AA54A4AA4A5254922252450057D406FA82B00000200000000000
000D554A95255544A524924494242242A05BD20BFA000000100000000000
003AAA952A54A4A94A492529494A49105EA02DE815F00000100000000000
006A9552955252522524911090911088817F505764100000100000000000
00D4AAA552A494A5524AA4A5252222226D016EA05B600000000000000000
01AAA4AA55554A5249244A424244440015EA02BD41500000180000000000
01555554AA4A94A492A924949488912B680BF501BE800000080000000000
0352AA9292A5491251129125091109FFB76416F402F00000080000000000
03554954A5492A54A4A44A5252225FB6EEDED00BF4000000080000000000
02AAAAAA54A4954A544A44242445EADBBBBBBDA01BD00000080000000000
01555552A95529294A912949488DB7B77777777FA0280000000000000000
06A529292A529294914A92509276EEEEEEEEEFAEFF500000080000000000
05554A5554A52A52A529252525DDDDDDDDDDDB7B6DB78000080000000000
06AAAAA495549529525448924BEEEEEEEEEEEDBDBBDBE000080000000000
055555552A492A524A9291249EDDDDBBBBBBB6F6F76EDC00000000000000
0529292A92A5512925492491776F776EEEEEEF6F6EF76F00080000000000
05554A54A5552A52492A4A52EDBDB6DDDDDDB6DDBB6DBDE0000000000000
054AAAA55494952544949525BBDBDBBBBBBBDBBBDDBBDBBA080000000000
0D55554AA92924A92A52524B776DB77777776EEDB6EDB6EF000000000000
0D2AA9292A95525491090917BBB6EEEEEEEEF776EF76EF76CC0000000000
0D54954AA5529492A4AA54A6EEDBBBBBBBBB6EDBB6EDDEDB740000000000
0AAAAAA552494A495544924DBBEDDDDDDDDDBBBDDBBBBBBDBC0000000000
0D55552A9552A95249294A9B76DBBBBBB52244DBB7777776EE0000000000
0A92A552A929252924922536EF76EEEE400000005BBBBBBB778000000000
05555555254A4A524AA4926DDEEDDDD80000000000377776EDC000000000
0AAA4AA4AA555525444A495BBBBBBBA0000000000002DDDDBBE000000000
0D55552954AA4A5492949277776EEEC000000000000056DB777000000000
0A92A9552512A5292949257BBBB77740000000000000076EEEF800000000
055555554AA54A9252924AB776EEEE8000000000000000DDBB6C00000000
1AAA4AA4A4A954A5244924DB001BBB00000000000000002BDDBE00000000
1552AA552952494A4A92496E000376800000000000000005BB7700000000
1AAA952A95292525254925B60002EF000000000000000000EEEF80000000
154AA554AA954A4A492A52EC0001DD0000000000000000001DDD80000000
1AA954A5494A54A5449489BA0001BB00000000000000000007EEC0000000
1555552952A94A94A949256C0000EE80000000000000000002DDE0000000
1AAAAA952955254A549252F40000F7000000000000000000006F70000000
155554AA552A49294924A5EC00016D800000000000000000001DB8000000
1A4A4AA54A94A494249449BA0000BB800000000000000000000BD8000000
1555552A9529552AAA52936C00006E8000000000000000000005BC000000
1AA95292A5525291510927B40000F740000000000000000000016C000000
154A95554A94A52A4AAA4AEC00006EC000000000000000000000DE000000
1AAAAAA4A54A5244A44495BA00005B80000000000000000000003B000000
155552552A5294A949292B6C0000B6C00000000000000000000057000000
1AAAAAAA92A94A52255253B400006F40000000000000000000001B800000
15495554A55294A54924A6EC00005EC0000000000000000000000D800000
1AAAA4955494555254924BBA00006BA00000000000000000000006C00000
1555552AA92AA4A549249774000037600000000000000000000005C00000
0AAA555255525250A5124BB800007BA00000000000000000000002E00000
0D54AAA55294A52A94A49774000037600000000000000000000001600000
0AAAA554A94A52944A5245B800002DC00000000000000000000001B00000
0A954AA94A54A54A914A977400005B600000000000000000000001700000
0AAAA92AA552525128912FB800002EE80000000000000000000000F80000
0CA955554AAA94A4A52496E800001DD00000000000000000000000D80000
0B554A94A4454A4A52954BB800003EE00000000000000000000000B80000
0AAA95292AAA94A94A524F7400002DB000000000000000000000006C0000
0D5552AA92512514950916E8000016E80000000000000000000000B40000
0AAAA55554AA4AA95254ADD800001BB000000000000000000000005C0000
0D555494AA55544449244EE800001DD000000000000000000000006E0000
02AAAAA9254A92AA92A92BB800001BB80000000000000000000000360000
0552555552A5291149129EE8000016E800000000000000000000007A0000
06AAAAAA954A52AA94A52DD800000DD80000000000000000000000370000
0555494954A549444A485EE800001EE800000000000000000000002D0000
06A55552AA94952AA4952DD800000DB800000000000000000000001B0000
05552AAA51525291124956F000000B6C00000000000000000000002F0000
07554A54AAA4A52AA4929B6800000DB400000000000000000000001D0000
06AAA94A545549444A485DB800000BDA00000000000000000000001B8000
01555552A54A92AA949296E80000076C0000000000000000000000178000
02A92AA92AA5291149252F7000000EF400000000000000000000001E8000
0355554AA94A4A4A924A56E800000B6C00000000000000000000000B8000
02A54954421254A448449BB0000005BA00000000000000000000001D8000
035552A80000094A902957680000077600000000000000000000000BC000
032AAA411540025144922FB0000007BA00000000000000000000000EC000
0155551FFFFF002A3C295AE80000037600000000000000000000000DC000
014A4AFFFFFFC000FC443DB0000005BC000000000000000000000007C000
015555FFFFFFF803FC29576803F002ED000000000000000000000006C000
01AAABFFFFFFFFFFFC94BBB007F807768000000000000000000000074000
00A95FFFFFFFFFFFF94957700FFE02DB000000000000000000000006C000
00AABFFFFFFFFFFFFA545BD01FFF03BD800000000000000000000005C000
00D57FFFFFFFFFFFF492AED81FFE8376C000000002B6A8000000000343B0
00D2FFFFFFFFFFFFF54937683FFE06EF60000000FF6F6F6000000003DEE8
0055FFFFFFFFFFFFEA92ADB43FFE03B6E8000007B6DDDDDD800000037BDC
0055FFFABFFFFFFFE4495BDA3FFC25DBBC00005BDBBBEDBEF4000002DDFA
006BFF5552FFFFFFD294ADB63FFC076EDB50136DB76EB6EDDB8000017B6F
006BFEAA952FFFFFA94936EFBFF88FB76FAFEFB6EFF77B76EEE80001EEF6
0037FAA52A55FFFF52925BBB7FF89B6DBB76B6DDDD6DB6DBDDDD0001BBDB
002FF554A54A1FFD24495DDDBFF13DDBDDBBDBEEEEBBDBBDBBBEC001DDBD
0037EAA94A9107F54A94BBB6FFE0DB6DB6EF6EDDDDF76EDB6EEDBC0176FB
003FC52AA557C91290892EEF7F036EF6EF76F76F776EF76EF7770741FB6E
001FCA544A9F92A440525DB6E805DDDBB6DB6DBB6DBB6EDDEEEE01B16DBB
001F9540257FA94A5824BEDBBC3EEEEDDBBDBBDDBBDDBBBBBBBDA3DDDBDD
001F8AA80A7F9292FC092B6EDBEDDDDBB776EDB6EDBB7777777FE1BB77BB
001F957E92FF2955FE2576F76EF6F7740AEF76C176EEEFBAAEFFF2EEFEEE
001F897F05FF524BFE4A0B6DA1DBDB6801B6DB80ADCBB6D00BBFF1D81BBA
001F8AFF95FE2955FE2402BB81BDBDA7C1DBBDF83B85DB8005FFF3C01DDC
001F85FF8BFE254BFE01A1F7F076DBBFF0B777FC05476E3FC1BFF22E1774
001F8AFF93FC9257FE0FF2FFF0AF6E7FF8EEEFFF01EBB5FFE17FF0BF16F8
001F85FF17FC54ABFE7FF1AFFC36DDFFFC3BBFFFC7CEDBFFF0FFF3FF9BE8
000FC2FF2FFC0247FFFFF3DFFC5BBBFFFC5DDFFFFFDBBFFFF1BFFFFF9DB0
000FC1FF2FFC00ABFFFFF37FFE2F7FFFFC7B7FFFFFB6FFFFF97FFFFF9760
0007E1FE9FFF6013FFFFEEFFFE76FFFFFC6EFFFFFF7BFFFFF8FFFFFF3BC0
0007FBFF1FFFF855FFFFF5FFFE6DFFF87E5DFFFFFEEFFFFFF9BFFFFF2E80
0003FFFE3FFFFC27FFFFEEFFFE5BFFF47C7FFFFFFDBDFFF3F9DFFFFE3800
0001FFFFFFFFFC2BFFFFCBFFFE6FFFF07E6BFFFFFB6FFFE3FAFFBFFE0000
00007FFFFFFFFC97C3FFDFFFFCF7FFE0FCB7F1FFF6FFFFC7FB7E3FFC0000
000000FFFFFFFCAFC7FF9BFFFCDFFFC0FE5FE07FDBBFFFC7F5FC3FFC0000
0000007FFFFFFC5F87FF3FFFFDBFFFC0FCEFC07FEDFFFF8FF7FA3FFA0000
0000003FFFF9FCBF0FFF1FFFF97FFF80FCBF80FFB6FFFF0FEFF87FF80000
0000001FFFF0FA7E1FFE9FFFFAFFFF80FCFF41FF6FFFFF1FDFF0FFF00000
00000007FFF0F57C1FFE1FFFF1FFFF91F8FF03FEDBFFFE1FBFE0FFF00000
00000001FFF0F9F83FFC1FFFF7FFFF3FF9FE07FFFFFFFE7FFFC1FFE00000
00000003FFE0FFF07FFC3FFFF0FFFF7FF8FC0FF807FFFFFF1F83FFE00000
00A00003FFE003E07FF87FFFE1FFFE7FF8F80FF00FFFFFFE3F07FFC0E000
0BF80007FFE007C0FFF8FDFFE3FFFE7FF1F01FE00FFFFFFC7F07FFC1E000
1FFE0007FFE007C1FFF1FBFFC3FFFC7FFBE03FE01FFFFFF0FE0FFF83C000
3FFE000FFFC00781FFF3FBFFC7FFFC7FFFE07FF03FFFFFE1FC1FFF87C000
7FFF001FFFC00703FFE3F7FFCFFFF83FFFC0FFF8FFFFFF81F81FFF8F8000
7FFF001FFFC00007FFE7E7FFFFFFF83FFF80FFFFFFFFFF03F03FFFFF8000
FFFF003FFFA00007FFFFC7FFFFFFF87FFF81FFFFFFFFF807E07FFFFF8000
FFFF007FFF80000FFFFF8FFFFFFFFCFFFF03FFFFFBFFF01FC07FFFFE0000
FFFE007FFF80000FFFFF0FFFFFFFFFFFFE07FFFFF3FFF03F80FFFFFC0000
FFFE00FFFF00001FFFFF0FFFFEFFFFFEF80FFFFFE3FFFAFF00FFFFF80000
FFFC01FFFF00001FFFFE0FFFF8FFFFFC001FFFFFC3FFFFFE00FFFFF00000
FFF801FFFE00001FFFFC0FFFF07FFFF8001FFFFF01FFFFFE00FFFFE00000
FFF003FFFC00001FFFF80FFFE07FFFF0001FFFFF01FFFFFC00FFFFC00000
FFF003FFFC00000FFFF00FFF803FFFF0003FFFFE01FFFFF800FFFF000000
FFF007FFF800000FFFC00FFE003FFFC0001FFFFC00FFFFE0007FFE000000
FFF01FFFF0000007FF0007FC001FFF80001FFFF0007FFFC0003FF8000000
7FF83FFFE8000001F80003E0000FFF0000060FE0003FFF00000FC0000000
3FFFFFFFE0000000000000000003F80000000000000FFC00000000000000
3FFFFFFFC000000000000000000000000000000000000000000000000000
1FFFFFFFC000000000000000000000000000000000000000000000000000
0FFFFFFF80000180000C0080078C003C00C0F00002000380C000C0080000
03FFFFFE000003E0001C008007EC183C00C0F00002000F06C000C6080000
01FFFFFC000007667F19EC9C066DFFFFB2CCF383820C7EFFCCF0CF79C000
007FFFF00000062F7FBFFEBE066FFFFFB2FFF7C7C21FFEFFDFF0CFFBE000
001FFFC000000619EDFFB2B6066FDBBEF2F7F6C7C233DFF6F3F8C6DBE000
0001FC0000000679EDFFB0B6066FFB3CF6F1F6C7E233FEF6F1F8C6CBE000
000000000000077B6DF7B6B6C6EF7B3EF6F7B6C6C21BE7BEF7B8C6DB6C00
00000000000003EF6DBF9EBEC7EFFF3FBEFFF7C7C3FEFEF7DFF8FF7BEC00
000000000000018600180C0880018603080CC101800CCC630C4003218000
00000000000000000000000180000000001C00000000F800000000000000



check that this lines:

Code: Select all

0000000000000000000001FFF77777FF0000000000000000000000000000
00000000000000000001FF5204888825BF00000000000000000000000000
can be rewrite with "," compression character...

Code: Select all

..||..||..||..||..||..||..||..||..||..||..||..||..||..||..||
0000000000000000000001FFF77777FF,
00000000000000000001FF5204888825BF,
..||.. are only to see the "byte", we can´t cut a byte... for example:
"F," -> don´t work!
"F0," -> this work!
Post Reply