Winarkeo POSPicPrinter est l'aboutissement du projet détaillé dans l'article ci-dessous, et vous permettra d'imprimer des images de la manière la plus confortable!

Téléchargement

pospicprint_setup.exe

Source incluse dans le dossier d'installation

Bonnes créations!


Nous avons vu dans un article précédent comment tirer partie d'une imprimante thermique, et comment celle-ci pouvait s'avérer une bonne solution économique pour l'impression de tous les jours (brouillons, listes de courses, adresses pour enveloppes, notes...). Toutefois, ce modèle ne se limitait qu'au texte (bien que nous ayons poussé l'expérimentation un peu plus loin), et, après l'acquisition d'une imprimante thermique plus moderne, prenant en charge l'impression graphique à 90mm par seconde, il est temps de passer au niveau supérieur.

Pour le photographe ou dessinateur hardcore (de même que pour ceux du dimanche), pouvoir imprimer ses créations à l'infini, sans souci du délai de développement et du coût est un gros plus. Certes, les tirages seront limités à 58 ou 79mm de largeur (cela ne devrait pas gêner la génération Instax), certes il s'agira là de noir et blanc (pour ceux qui préfèrent la couleur), et tout cela sera plus ou moins éphémère. Mais pouvoir imprimer sans attendre, faire des albums physiques de manière rapide, obtenir du matériel de collage pour les amateurs de montage, ou encore des affichettes pour les street artists, cela est top. Payer une blinde en borne pour un gros plan couleur sur la raclette des dernières vacances en Savoie, c'est peut être un peu du gâchis. Réserver en tirage classique ce qui est vraiment important, pour imprimer des clichés plus banaux sur des tickets de caisse recyclés d'IKEA (ou de l’addition de ladite raclette) peut s'avérer une approche intéressante de l'appréhension de nos souvenirs.

Voilà pourquoi dans cet article nous tenterons d'exploiter au mieux les capacités graphiques de la machine.

L'imprimante

L'imprimante thermique est de la marque KKmoon, compatible avec des rouleaux de papier de 58mm de largeur.

Le projet

Nous allons développer une application console Windows à l'aide de SharpDevelop (C#), .NET 4.0. En glissant une image sur le programme, l'impression se lancera automatiquement après la saisie de paramètres que nous verrons. Veillez à ce que votre imprimante se nomme "POS-58" afin que celui-ci puisse fonctionner.

Cela car l'assistant d'impression Windows, Word ainsi que la plupart des logiciels ne sont pas adaptés aux imprimantes thermiques. Vu que la longueur du papier est quasi infinie, cela mène à des marges énormes lors de l'impression d'une image, ainsi qu'une impression qui ne s'arrête jamais, la bobine se déroulant à l'infini même après les derniers pixels dépassés. Nous voulons une impression propre et bien ajustée.

Logique du programme

Je ne vais pas détailler tout le code, mais voici la logique mise en place:

Nous allons utiliser la classe PrintDocument de l'espace de noms System.Drawing afin d'envoyer l'image à l'impression.

PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.Landscape = false; //en portrait, s'il vous plait
pd.PrinterSettings.PrinterName = "POS-58"; //nom de l'imprimante (Panneau de Config > Périph. et Imprimantes)
//pd.DefaultPageSettings.Margins = new Margins(0,0,0,0); les marges de l'imprimantes ne peuvent être réduites plus
pd.PrintPage += (o, e) =>
{
    Image img = Image.FromFile(args[0]); //on prend l'image glissée
    if(img.Width > img.Height) img.RotateFlip(RotateFlipType.Rotate90FlipNone); //si en paysage, on pivote en portrait 

    e.Graphics.DrawImage(img, resizeKeepAspect(img, (int)pd.DefaultPageSettings.PrintableArea.Width, img.Height));
};          
pd.Print();

Si l'image est en paysage, alors elle sera orientée en portrait pour l'impression, afin que sa longueur puisse bénéficier de toute la surface du papier thermique. Nous allons ensuite redimensionner l'image proportionnellement afin qu'elle puisse remplir toute la surface du papier, en nous servant d'une version modifiée de la bien utile fonction ResizeKeepAspect présentée dans ce fil Stackoverflow. Comme DrawImage prend du Rectangle et non du Size comme second argument, alors nous allons lui changer ses type et valeur de retour:

public static Size ResizeKeepAspect(Size src, int maxWidth, int maxHeight)
{
    decimal rnd = Math.Min(maxWidth / (decimal)src.Width, maxHeight / (decimal)src.Height);
    return new Size((int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));
}

devient

public static Rectangle resizeKeepAspect(Image src, int maxWidth, int maxHeight)
{
    decimal rnd = Math.Min(maxWidth / (decimal)src.Width, maxHeight / (decimal)src.Height);
    return new Rectangle(0, 0, (int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));
}

Notez que nous utilisons

pd.DefaultPageSettings.PrintableArea.Width

pour obtenir la largeur maximale en pixels de la bande de papier (surface d'impression, sans les marges donc), afin de remplir au mieux la surface.

Voilà donc de quoi faire de bons tirages! Toutefois, il y a un problème. Quand il y a trop de tons sombres, c'est à dire de noir pur, l'imprimante a du mal à couvrir toute la surface. En gros, elle ne peut pas se maintenir à une certaine température élevée de manière constante. Il faut donc trouver une valeur de noir qui puisse être imprimée uniformément, sans variations détériorant l'intégrité de l'image. Pour cela, nous allons modifier l'alpha de l'image. Ainsi, le noir absolu de valeur 0 (sur 255) pourra être éclairci, disons à 64 (soit 25%). Pour ce faire, nous pouvons changer la luminance de chaque pixel (par modification RGB ou par ajout d'une valeur alpha), ce qui, même en utilisant Bitmap.LockBits n'est pas très ergonomique. Ou bien nous pouvons choisir comme astuce de changer l'opacité de l'image, tout en apposant celle-ci sur un calque de couleur blanche (Alpha Blending). La luminance en serait ainsi modifiée de manière beaucoup plus simple. Nous allons nous inspirer de cette fonction Stackoverflow, que nous allons légèrement modifier, remplaçant

//qui crée une image vide
var output = new Bitmap(image.Width, image.Height);

par

//qui crée un fond blanc
var output = new Bitmap(image.Width, image.Height);
using (Graphics graph = Graphics.FromImage(output))
{
    Rectangle ImageSize = new Rectangle(0,0,image.Width, image.Height);
    graph.FillRectangle(Brushes.White, ImageSize);
}

Nous pouvons désormais imprimer la même image, de 100% d'opacité (soit le noir le plus profond, 0), à 75% (la valeur maximale du noir passant à 64), 50% (128 128 128), en passant par la profondeur 96 96 96. Nous notons que le noir le plus profond et constant que nous pouvons obtenir est de valeur 128, soit 50%. Un bon gris, quoi.

Comme la répartition de tons sombres est différente pour chaque image, nous laissons à l'utilisateur le soin de spécifier le pourcentage d'opacité qu'il souhaite appliquer à l'image imprimée, avec un Console.ReadLine().

Article précédent Article suivant