lundi 2 mars 2015

Transformer une image en BMP 2 couleurs pour une impression PCL

Dans le cadre du projet PythonPcl (GitHub), je me suis mis en tête d'imprimer un logo sur une page... en PCL bien entendu!

Les premiers travaux de  hp-ip-raster-unencoded-v2.py m'ont déjà permit d'envoyer une "image" dite Raster contrôlée point-par-point.  Pour le moment, l'image Raster envoyée en PCL n'est pas compressée (mode appelé "unencoded" dans le manuel HP).

Voyez les petits graphiques juste au dessus du texte "End of test".

Le but final n'est pas de coder une image en point-par-point dans le code Python... mais c'est déjà un début.
Il faudrait maintenant pouvoir envoyer une image noir et blanc (he oui! notre HP 3015 n'est pas en couleur!).

Mais un problème se pose:
comment obtenir une image noir et blanc sans que celle-ci soit immonde une fois imprimée?

La réponse:
Il faut faire du dithering au moment de la transformation noir et blanc.
Il est certainement possible de réaliser cette opération en Python... pour ma part, je vais opter pour une préparation avec Gimp.

Réaliser une bitmap 2 couleurs + dithering avec Gimp.

Le but de ce tutoriel - The aim of this tutorial
Le but de ce mini-tutoriel n'est pas de dégrader le logo "open source initiative" mais de montrer comment transformer une image pour qu'elle soit imprimée en PCL (Printer Command Langage) tout en préservant un aspect visuel agréable.

The aim of this tutorial is not to degrade the "open source initiative" logo but to explain how to transform one picture to be printed with PCL (Printer Command Langage) while preserving a nice printed visual aspect.

Commençons par charger notre image d'origine.
J'ai opté pour le logo open-source suivant que vous trouverez ici sur opensource.org
Source: opensource.org
Passer en deux couleurs
Une fois chargée dans Gimp, passez par le menu Image > Mode > Indexed... pour passer en couleur indexée.
Nous allons:
  • Limiter le nombre de couleur à 2 et 
  • Utiliser  de sélectionner "Floyd-Steinberg" comme "Color Dithering"
   
Cela produira une image deux couleurs mais pas forcement en noir et blanc!
image en 2 couleurs avec dithering
Mais nous allons corriger cela.

Passer en noir et blanc
Pour ce faire, nous allons rechanger le mode le l'image en niveau de gris.
Menu Image > Mode > Grayscale

Ce qui nous permettra ensuite d'appeler l'outil de seuil :-)
Menu Colors > Threshold  (ou Couleurs > Seuil)

En travaillant sur les paramètres (si cela est seulement nécessaire), vous tomberez vite sur une image en noir et blanc.

Repasser en 2 couleurs + sauver en Bitmap
maintenant que nous avons notre image en noir et blanc, nous allons la sauver en tant que bitmap deux couleurs (noir et blanc).

Menu Image > Mode > Indexed...

Fixez:
  • le nombre de couleur à deux couleurs
  • Retirer l'option de dithering (plus nécessaire cette fois)
  • convertissez une fois de plus 


Voila, il ne reste plus qu'a exporter notre belle image en BMP via le menu "File > Export..." (ou "Fichier > Exporter...").

Le but étant de recharger l'image en Python, il est important de faire attention aux paramètres d'exportation Bitmap.
  • Run-Length Encoded doit être décoché
  • Do not write color space information doit être coché

Nous avons maintenant une image prête pour nos impressions en PCL (Printer Command Langage)

Petite information complémentaire
Voulant imprimer une image sur ma Zebra ZPL2824, j'ai voulu réutiliser ce tutoriel pour produire une image 2 bits assez facile à lire. Le Hic, c'est que Gimp 2.8 pour Windows ne propose pas de modifier les options Run-Length Encoded... etc.
C'est franchement Agaçant!!!

Il est possible d'exporter au format SUNRAS avec l'extension IM1 (je suspecte ce format d'encoder 1 bit par pixel). Utilisez le format standard.
Une fois sauvez, nous pouvons ouvrir le fichier avec un editeur Hexa décimal.
Nous pouvons clairement constater une similitude entre les données et le graphique (voyez l'antenne de la voiture)

Il faudra juste sauter les premiers octets de l'entête du fichier (contenant une signature).


Une inspection attentive couplée à un unique point placé dans le coin supérieur de l'image (donc valeur binaire 1000000 correspondant à la valeur hexadécimale 80 révèle


qu'il faut enlever les 32 premiers octets :-)

J'ai également remarqué que chaque ligne (le 16ieme octet) se termine par un 00. Mon image ne faisant que 120px de large, il me faut uniquement 120/8 = 15 octets/bytes pour coder une ligne de mon image. Le format travaille certainement par multiple de 8 octets (à vérifier dans la spec)

Tadaa.

Aucun commentaire: