Jump to content
legd1991

Kiosk Printer

Recommended Posts

legd1991

Boas pessoal.

Tenho uma impressora de talões (Fenix Imvico TK51), daquelas que estão em kiosk como em bancos ou segurança social quando tiram uma senha para serem atendidos.

Já consegui por a impressora a fazer quase tudo menos definir uma imagem na memória para imprimir em todos os talões-

Isto funciona através do envio de comandos, no meu caso, pela porta COM.

Estou com um problema para perceber a especificação. Aqui fica a especificação. Se alguém me conseguir ajudar agradeço.

FS q n [xL xH yL yH d1…dk]1…[xL xH yL yH d1…dk]

[Name] Define NV bit image

[Format] ASCII FS q n [xL xH yL yH d1...dk]1...[ xL xH yL yH d1...dk]

Hex 1C 71 n [xL xH yL yH d1...dk]1...[ xL xH yL yH d1...dk]

Decimal 28 113 n [xL xH yL yH d1...dk]1...[ xL xH yL yH d1...dk]

[Range] n = 1

xL ≤ 48 xH = 0 (when 1≤ (xL+ xH × 256) ≤ 48)

0 ≤ yL ≤ 255 0 ≤ yH ≤ 1 (when 1≤ (yL+ yH × 256) ≤ 288)

0 ≤ d ≤ 255 k = (xL+ xH × 256) × (yL+ yH × 256) × 8

Total available data area = 16380 bytes (16KB-4Bytes)

[Description]

  • Define the NV bit image specified by n .
  • n specifies the NV bit image number (always 1).
  • xL, xH specifies (xL+ xH × 256) × 8 dots in the horizontal direction for the NV bits image you are defining.
  • yL, yH specifies (yL+ yH × 256) × 8 dots dots in the vertical direction the NV bit image you are defining.

[Notes]

From the beginning of the processing of this command till the finish,

mechanical operations (including initializing the position of the printer

head when the cover is open, paper feeding by using the FEED button,

etc.) cannot be performed.

• NV bit image means a bit image which is defined in a non-volatile memory by FS q and printed by FS p.

• This command is effective only when processed at the beginning of the command is effective when 7 bytes <FS∼yH> is processed as a normal value.

• When the amount of data exceeds the capacity left in the range defined by xL, xH, yL, yH, the printer processes xL, xH, yL, yH out of the range.

• The d indicates the definition data. In data (d) a 1 bit specifies a dot to printed and a 0 bit specifies a dot not to be printed.

• The definition area in this printer is a maximum of 16KBytes-4Bytes.

• Once a NV bit image is defined, it is not erased by performing ESC @, or power off.

• This command performs only definition of a NV bit image and does not printing. Printing of the NV bit image is performed by the FS p.

Cumprimentos.

Edited by legd1991

Share this post


Link to post
Share on other sites
pmg

Segundo percebi, tens que ter imagens com tamanhos multiplos de 8 linhas e colunas.

Por exemplo, um smiley

. . . . . . . .
. # # . . # # .
. # # . . # # .
. . . . . . . .
. . . . . . . .
. # . . . . # .
. . # # # # . .
. . . . . . . .

a primeira linha seria o d1, a segunda o d2, ... até ao d8

d1 = 00000000 = 0

d2 = 01100110 = 102

d3 = 01100110 = 102

d4 = 00000000 = 0

d5 = 00000000 = 0

d6 = 01000010 = 66

d7 = 00111100 = 60

d8 = 00000000 = 0

O tamanho desta imagem é 1x1 ou seja xL = 1; xH = 0 e yL = 1; yH = 0

E pronto, está tudo definido.

Manda para a impressora os valores seguintes, em decimal

/* FS  q  n [xL xH yL yH d1 d2  d3  d4 d5 d6 d7 d8]1... */
  28 113 1  1  0  1  0  0  102 102 0  0  66 60 0

Se a tua imagem for mais comprida e/ou mais alta vais ter mais valores para defini-la, e tens de fornecer mais 'd's.

Nos exemplos abaixo os 'd's são iguais, só muda o comprimento e altura

. . . . . . . . . . . . . . . #
. # # . . # # . . . . . . . # .
. # # . . # # . . . . . . # . .
. . . . . . . . . . . . # . . .
. . . . . . . . . . . # . . . .
. # . . . . # . . . # . . . . .
. . # # # # . . . # . . . . . .
. . . . . . . . # . . . . . . .

/* FS  q  n [xL xH yL yH d1 d2  d3  d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16] */
  28 113 1  2  0  1  0  0  102 102 0  0  66 60 0  1  2   4   8   16  32  64  128
/*          ^^^ 2 de comprimento e 1 de altura */

. . . . . . . .
. # # . . # # .
. # # . . # # .
. . . . . . . .
. . . . . . . .
. # . . . . # .
. . # # # # . .
. . . . . . . .
. . . . . . . #
. . . . . . # .
. . . . . # . .
. . . . # . . .
. . . # . . . .
. . # . . . . .
. # . . . . . .
# . . . . . . .

/* FS  q  n [xL xH yL yH d1 d2  d3  d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16] */
  28 113 1  1  0  2  0  0  102 102 0  0  66 60 0  1  2   4   8   16  32  64  128
/*                ^^^ 2 de altura e 1 de comprimento */

O que nao percebi foi o "1" e a duplicacao seguinte ... experimenta sem e com

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
legd1991

Obrigado pela resposta @pmg Eu tinha percebido isso. O meu maior problema é pegar numa imagem e converte-la para um array de bytes para enviar para impressora. Já tentei, consegui gravar mas não ficou como devia ter ficado

Share this post


Link to post
Share on other sites
HappyHippyHippo

ui ... isso parece como o BASIC trabalhava no Spectrum :D

@legd1991 : pois, mas sem ver o teu código é impossível saber o que tens de errado ...


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
legd1991

O código encontrei na net, fiz algumas alterações para o meu caso, mas nada

//Esta função retorna uma classe com os dots da imagem apenas true ou false
private static BitmapData GetBitmapData(byte[] bytes)
 {
	 using (var ms = new MemoryStream(bytes))
	 using (var bitmap = (Bitmap)Bitmap.FromStream(ms))
	 {
		 var threshold = 127;
		 var index = 0;
		 var dimensions = bitmap.Width * bitmap.Height * 8;
		 var dots = new BitArray(dimensions);
		 for (var y = 0; y < bitmap.Height; y++)
		 {
			 for (var x = 0; x < bitmap.Width; x++)
			 {
				 var color = bitmap.GetPixel(x, y);
				 var luminance = (int)((color.R * 0.3) + (color.G * 0.59) + (color.B * 0.11));
				 dots[index] = luminance < threshold;
				 index++;
			 }
		 }
		 return new BitmapData()
		 {
			 Dots = dots,
			 Height = bitmap.Height,
			 Width = bitmap.Width
		 };
	 }

private string InsertImage(int top, int left, byte[]
{
	 var encoding = Encoding.ASCII;
	 var data = GetBitmapData(image);
	 var dots = data.Dots;
	 var bytes = (int)Math.Ceiling((double)data.Width / 8);
	 var imageWidth = data.Width;
	 var canvasWidth = bytes * 8;
	 StringBuilder _sb = new StringBuilder();
	 _sb.Append("(28)");
	 _sb.Append("(113)");
	 _sb.Append("(01)");
	 _sb.Append(string.Format("({0})",data.Width));
	 _sb.Append("(00)");
	 _sb.Append(string.Format("({0})",data.Height));
	 _sb.Append("(00)");
	 int offset = 0;
	 while (offset < data.Height)
	 {
		 // The third and fourth parameters to the bit image command are
		 // 'nL' and 'nH'. The 'L' and the 'H' refer to 'low' and 'high', respectively.
		 // All 'n' really is is the width of the image that we're about to draw.
		 // Since the width can be greater than 255 dots, the parameter has to
		 // be split across two bytes, which is why the documentation says the
		 // width is 'nL' + ('nH' * 256).
		 for (int x = 0; x < data.Width; ++x)
		 {
			 // Remember, 24 dots = 24 bits = 3 bytes.
			 // The 'k' variable keeps track of which of those
			 // three bytes that we're currently scribbling into.
			 byte slice = 0;
			 // A byte is 8 bits. The 'b' variable keeps track
			 // of which bit in the byte we're recording.
			 for (int b = 0; b < 8; ++b)
			 {
				 // Calculate the y position that we're currently
				 // trying to draw. We take our offset, divide it
				 // by 8 so we're talking about the y offset in
				 // terms of bytes, add our current 'k' byte
				 // offset to that, multiple by 8 to get it in terms
				 // of bits again, and add our bit offset to it.
				 int y = (((offset / 8)) * 8) + b;
				 // Calculate the location of the pixel we want in the bit array.
				 // It'll be at (y * width) + x.
				 int i = (y * data.Width) + x;
				 // If the image (or this stripe of the image)
				 // is shorter than 24 dots, pad with zero.
				 bool v = false;
				 if (i < dots.Length)
				 {
					 v = dots[i];
				 }
				 // Finally, store our bit in the byte that we're currently
				 // scribbling to. Our current 'b' is actually the exact
				 // opposite of where we want it to be in the byte, so
				 // subtract it from 7, shift our bit into place in a temp
				 // byte, and OR it with the target byte to get it into there.
				 slice |= (byte)((v ? 1 : 0) << (7 - b));
				 _sb.Append(string.Format("({0})", slice));

				 //_sb.Append("(" + slice.ToString() + ")");
				 //_sb.Append("(" + slice.ToString() + ")");
				 // Phew! Write the damn byte to the buffer
				 //bw.Write(slice);
			 }

		 }
		 // We're done with this 24-dot high pass. Render a newline
		 // to bump the print head down to the next line
		 // and keep on trucking.
		 offset += 1;
	 }
	 return _sb.ToString();
	 // bw.Write(Environment.NewLine);
}

Share this post


Link to post
Share on other sites
pmg

        _sb.Append("(28)");

Huh??? Estás a mandar parentesis para a impressora?

Aquela instrução vai gerar 4 bytes para serem mandados para a impressora?

A ideia com que eu fiquei é que aquele 28 é um único byte. Em C, o meu smiley simples acima, seria qualquer coisa como

unsigned char image[1000];
size_t index = 0;

image[index++] = 28; /* FS */
image[index++] = 113; /* q */
image[index++] = 1; /* n */
image[index++] = 1; /* xL */
image[index++] = 0; /* xH */
image[index++] = 1; /* yL */
image[index++] = 0; /* yH */
image[index++] = 0; /* q1 */
image[index++] = 102;
image[index++] = 102;
image[index++] = 0;
image[index++] = 0;
image[index++] = 66;
image[index++] = 60;
image[index++] = 0; /* q8 */
fwrite(image, 1, index, IMPRESSORA);


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
legd1991

Huh??? Estás a mandar parentesis para a impressora?

Aquela instrução vai gerar 4 bytes para serem mandados para a impressora?

A ideia com que eu fiquei é que aquele 28 é um único byte. Em C, o meu smiley simples acima, seria qualquer coisa como

unsigned char image[1000];
size_t index = 0;

image[index++] = 28; /* FS */
image[index++] = 113; /* q */
image[index++] = 1; /* n */
image[index++] = 1; /* xL */
image[index++] = 0; /* xH */
image[index++] = 1; /* yL */
image[index++] = 0; /* yH */
image[index++] = 0; /* q1 */
image[index++] = 102;
image[index++] = 102;
image[index++] = 0;
image[index++] = 0;
image[index++] = 66;
image[index++] = 60;
image[index++] = 0; /* q8 */
fwrite(image, 1, index, IMPRESSORA);

Eu tenho uma outra função que vai tratar a expressão e enviar direito para a impressora.

Share this post


Link to post
Share on other sites
legd1991

Alguém me consegue ajudar com a conversão da imagem para bytes de modo a gravar direito na impressora?

Cumprimentos

Share this post


Link to post
Share on other sites
pmg

Já conseguiste imprimir o "meu" smiley correctamente?

E o smiley com o traço diagonal? tanto à frente como em baixo?

Como é que fizeste?

Acho que é um exagero estar a tentar imprimir uma imagem grande quando não consegues um pequena.

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
legd1991

Já enviei para a impressora aquele comando comando, mas ao imprimir não fica direito

cumprimentos

Share this post


Link to post
Share on other sites
legd1991

Já consegui imprimir esta imagem:

0011100000111000
0011100000111000
0001100000110000
0001100000110000
0000111111100000
0000000000000000
0000000000000000
0000000000000000

com a seguinte instrução:

(28)(113)(01)(02)(00)(01)(00)(56)(56)(56)(56)(24)(48)(24)(48)(15)(224)(00)(00)(00)(00)(00)(00)

Agora falta-me converter uma imagem para para uma instrução como esta

Share this post


Link to post
Share on other sites
pmg

00111000 ( 56) 00111000 ( 56)
00111000 ( 56) 00111000 ( 56)
00011000 ( 24) 00110000 ( 48)
00011000 ( 24) 00110000 ( 48)
00001111 ( 15) 11100000 (224)
00000000 (  0) 00000000 (  0)
00000000 (  0) 00000000 (  0)
00000000 (  0) 00000000 (  0)

Entao parece que os bytes sao sequenciais, da esquerda para a direita e de cima para baixo.

Queres converter uma unica imagem especifica (o logotipo) ou queres converter varias imagens dependendo da vontade do utilizador, do hora do dia, etc, etc, ...?

Para uma imagem especifica, a solucao mais comoda e converte-la em bitmap de duas cores e especificar os valores literalmente no programa.

Para varias imagens variadas, tens de converter a imagem inicial (JPG? GIF? BMP? TIFF? ...) num bitmap de preto e branco e depois associar os valores as posicoes de saida para a impressora.

Nao faco ideia como converter, em C#, uma imagem num bitmap a preto e branco.

Tendo um ficheiro correspondendo ao bitmap a preto e branco, nao deve ser dificil apanhar os valores correctos para os sitios correctos.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
legd1991

00111000 ( 56) 00111000 ( 56)
00111000 ( 56) 00111000 ( 56)
00011000 ( 24) 00110000 ( 48)
00011000 ( 24) 00110000 ( 48)
00001111 ( 15) 11100000 (224)
00000000 ( 0) 00000000 ( 0)
00000000 ( 0) 00000000 ( 0)
00000000 ( 0) 00000000 ( 0)

Entao parece que os bytes sao sequenciais, da esquerda para a direita e de cima para baixo.

Queres converter uma unica imagem especifica (o logotipo) ou queres converter varias imagens dependendo da vontade do utilizador, do hora do dia, etc, etc, ...?

Para uma imagem especifica, a solucao mais comoda e converte-la em bitmap de duas cores e especificar os valores literalmente no programa.

Para varias imagens variadas, tens de converter a imagem inicial (JPG? GIF? BMP? TIFF? ...) num bitmap de preto e branco e depois associar os valores as posicoes de saida para a impressora.

Nao faco ideia como converter, em C#, uma imagem num bitmap a preto e branco.

Tendo um ficheiro correspondendo ao bitmap a preto e branco, nao deve ser dificil apanhar os valores correctos para os sitios correctos.

É o que estou a fazer, ja converto a imagem para preto e branco, agora estou a tentar converter para os bytes correctos para a impressora

Share this post


Link to post
Share on other sites
legd1991

O meu problema agora é: Ja tenho a imagem em 0 e 1, tenho de passar para decimal, o numero de 0 e 1 é largura * altura. mas para a impressora tenho de enviar d´s de 1 a k e k é (largura* altura) * 8. Ao passar para decimal este valor ainda vai ser menor

Share this post


Link to post
Share on other sites
pmg

Tendo largura em 0's e 1's o numero a passar em xL e xH e essa largura a dividir por 8.

Tendo altura em 0's e 1's o numero a passar em yL e yH e essa altura a dividir por 8.

Se os numeros nao sao divisiveis por 8, acrescenta 0's ate serem (os 0's nao se veem na impressao)

Por exemplo, se tens 0's e 1's num bloco de 343 de largura e 125 de altura tens que mandar d's como se fosse um bloco de 344 (43*8) por 128 (16*8); ou seja: tens de mandar 43*16*8=5504 d's.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
legd1991

Tendo largura em 0's e 1's o numero a passar em xL e xH e essa largura a dividir por 8.

Tendo altura em 0's e 1's o numero a passar em yL e yH e essa altura a dividir por 8.

Se os numeros nao sao divisiveis por 8, acrescenta 0's ate serem (os 0's nao se veem na impressao)

Por exemplo, se tens 0's e 1's num bloco de 343 de largura e 125 de altura tens que mandar d's como se fosse um bloco de 344 (43*8) por 128 (16*8); ou seja: tens de mandar 43*16*8=5504 d's.

É isso. Muito obrigado pela ajuda :)

Cumprimentos

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.