Obligement - L'Amiga au maximum

Samedi 31 mai 2025 - 15:13  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : Programmation graphique système - 3e partie : afficher une image chunky
(Article écrit par l'équipe de GuruMed et extrait de GuruMed.net - juillet 2002)


Nous avons vu la dernière fois comment allouer un pinceau, afin de tracer une ligne (ou autre chose) de la couleur souhaitée.

Tracer des lignes et afficher du texte, c'est bien beau, mais ça reste assez limité. Comment faire pour afficher une image en utilisant un algorithme qui fonctionne aussi bien sous AGA que sous CyberGraphX et Picasso96 ?

Tout d'abord, l'image doit faire au maximum 256 couleurs pour pouvoir être affichée en AGA sur le Workbench. Nous allons donc nous limiter à des images de 256 couleurs maximum.

Les écrans de 256 couleurs ou moins étant forcément basés sur une palette (chaque pixel contient le numéro d'un pinceau dans la palette et non pas directement la couleur RVB), il nous faut un format d'image dont les couleurs sont facilement recalculables dans la palette de l'écran. Le format Chunky est idéal pour cela : chaque pixel tient dans un octet ayant pour valeur le numéro de pinceau dans la palette de l'image. De plus, la graphics.library d'AmigaOS contient des fonctions servant à tracer des images à ce format.

Convertir une image en chunky

Vous pourriez croire le contraire, mais il n'existe, à ma connaissance, aucun outil permettant de convertir facilement une image en un fichier contenant des données au format chunky directement utilisables par un programme C. Il existe différents outils faisant plus ou moins ce que l'on désire, mais, malheureusement, soit ils le font plutôt moins que plus, soit ils sont bogués.

En définitive, j'ai choisi Personal Paint et ArtPro.

Personal Paint n'est pas indispensable, mais il est très utile pour réduire le nombre de couleurs d'une image en voyant en temps réel le résultat, et ceci vers un nombre quelconque de couleurs, pas seulement une puissance de 2. Quand à ArtPro, il permet à priori de faire tout ce dont on a besoin, y compris la conversion 24 bits vers un nombre quelconque de couleurs (sans prévisualisation), mais il n'est malheureusement pas exempt de bogues.

GfxMaster permet également de sauver des images chunky, mais il est moins puissant. A essayer en cas de problèmes avec ArtPro, mais vous aurez alors probablement besoin d'un outil pour convertir un fichier binaire en source C, ou d'un assembleur pour créer un objet reliable.

1. Réduction du nombre de couleurs

Chargez votre image dans Personal Paint, puis utilisez le menu "Couleurs->Moins de couleurs..." pour réduire le nombre de couleurs. Il vaut mieux diminuer le nombre de couleurs au maximum acceptable à ce moment, car le Workbench ne dispose que de 256 pinceaux au total ; donc si votre image utilise 256 couleurs différentes, il est très peu probable que toutes ses couleurs soient les bonnes une fois affichée sur le Workbench.

Si vous utilisez un programme de dessin pour réduire le nombre de couleurs, le résultat sera bien meilleur que si vous laissez ObtainBestPen() faire tout le travail.

Si votre image utilise un nombre de couleurs différent d'une puissance de 2, faites bien attention à ce que toutes les couleurs inutilisées de la palette soient les mêmes qu'une couleur utilisée... Sinon, des pinceaux seront alloués inutilement ! Si nécessaire, recopiez la couleur 0 dans toutes les couleurs non utilisées de la palette. Une autre solution est de noter le nombre de couleurs utilisées et de s'en servir par la suite pour n'allouer que le nombre de couleurs nécessaire (explications ci-dessous).

2. Conversion en chunky

Lancez ArtPro, et vérifiez dans les réglages que le mode d'écran ("Screenmode") et les autres options sont corrects ; ça peut toujours servir. Chargez votre image en cliquant sur "Load" (Charger). En cas de problème, choisissez un chargeur approprié en cliquant sur "1".

Si votre image n'a pas été réduite en 256 couleurs ou moins, cliquez sur "3" et choisissez un mode 8 bits ou inférieur. Cliquez ensuite sur "Render Ctrl" (contrôle du rendu), réglez "Mode" sur "Palette", puis choisissez le nombre de couleurs. Si vous voulez un nombre de couleurs différent d'une puissance de 2, cochez "Custom Palette" (palette personnalisée) et entrez le nombre désiré dans "Colors Used" (couleurs utilisées). Ensuite, cliquez sur "Render" (faire le rendu). Cliquez pour faire disparaitre l'image.

Maintenant, cliquez sur "2" pour choisir le format de sauvegarde. Choisissez "Chunky". Cliquez sur "Config" (configuration) et sélectionnez :
  • Save Format :
    Output : Source
    Type : Byte

  • Source Format :
    Language : C
    Width : Bytes
Cliquez sur "Ok", puis "Accept and Operate" (accepter et opérer) et sauvez cela dans un fichier "image.h".

Éditez ce fichier pour changer le nom du tableau généré. Appelez-le par exemple "image" (au lieu de "data").

Il faut aussi sauver la palette. Cliquez à nouveau sur "2", choisissez "Palette" et cliquez sur "Config" (configuration) et sélectionnez :
  • Save Format :
    Output : Source
    Depth : 8 Bit
    Type : LoadRGB

  • Source Format :
    Language : C
    Width : Longs
Cliquez sur "Ok", puis "Accept and Operate" (accepter et opérer) et sauvez cela dans un fichier "palette.h".

Cette opération crée un fichier contenant un tableau avec des "ULONG" décrivant la palette, au format LoadRGB32. Le premier ULONG contient dans ses 16 bits de poids fort le nombre de couleurs de la palette, et dans ses 16 bits de poids faible le numéro du premier pinceau à utiliser (vous pouvez l'ignorer pour cette fois). Ensuite, suivent les couleurs proprement dites, à raison de trois ULONG par couleur (Rouge, Vert, Bleu). Enfin, le dernier ULONG vaut toujours zéro. Vous remarquerez au passage qu'ArtPro ne calcule pas les valeurs des couleurs comme je l'ai expliqué dans le précédent article, mais se contente de rajouter des 0 dans les 24 bits de poids faible... Ce qui n'est certe pas gênant actuellement, vu que seuls les huit premiers bits sont pris en compte dans le meilleur des cas.

Si vous voulez une palette avec un nombre de couleurs différent d'une puissance de 2, éditez le fichier "palette.h". Remplacez les 16 bits de poids fort de la première valeur du tableau par le nombre de couleurs effectif. Par exemple, si votre palette ne fait que 200 couleurs (0xc8) au lieu de 256 (0x100), remplacez "0x01000000" par "0x00c80000". Ensuite, supprimez toutes les couleurs en trop à la fin du tableau.

Changez le nom du tableau de "data" en "palette" ; et puis rajoutez un retour à la ligne à la fin des deux fichiers, car ça peut poser des problèmes...

Afficher l'image...

Trois choses à faire :
  • Allouer les pinceaux nécessaires.
  • Recalculer les couleurs de la palette de l'image chunky avec les numéros des pinceaux obtenus.
  • Tracer l'image chunky.
Allouer la palette

Nous allons simplement balayer le tableau "palette" et allouer chaque pinceau comme expliqué dans le précédent article. Les numéros des pinceaux obtenus seront stockés dans un tableau afin de pouvoir recalculer les couleurs de la palette de l'image chunky, puis libérer les pinceaux à la fin du programme.

Le premier UWORD du tableau est le nombre de couleurs de la palette. Le second peut ici être ignoré et devrait valoir 0.

LONG tmpPen;
WORD pen;
UBYTE pens[256];

for( pen=0; pen<(palette[0]>>16); pen++ ) {
   tmpPen = ObtainBestPen( cm,
               palette[pen*3+1],
               palette[pen*3+2],
               palette[pen*3+3],
               OBP_Precision, PRECISION_ICON, TAG_END );
   if( tmpPen==-1 ) { puts( "Impossible d'allouer les pinceaux." ); break; }
   else pens[i]=tmpPen;
}

Pour varier un peu, j'ai rajouté cette fois-ci une balise (OBP_Precision) permettant de choisir la précision de la couleur obtenue. PRECISION_ICON signifie que l'on n'y accorde pas beaucoup d'importance... Mais cela ne veut pas dire que les couleurs seront forcément mauvaises :-).

Recalculer les couleurs de la palette de l'image ("remap")

Maintenant, afficher l'image telle quelle ne marcherait pas : elle n'aurait pas les bonnes couleurs. En effet, si dans notre palette la couleur 0 est du noir, ce n'est pas le cas de la palette du Workbench qui contient généralement du gris en position 0. Le pinceau qu'on a obtenu en faisant un ObtainBestPen() sur cette couleur ne vaut donc certainement pas 0. Il faut donc changer tous les 0 de l'image chunky en la valeur obtenue par ObtainBestPen() sur la couleur 0 de notre palette... et faire de même pour toutes les autres couleurs.

ULONG pixel;

for( pixel=0; pixel<IMAGE_WIDTH*IMAGE_HEIGHT; pixel++ ) {
   image[pixel] = pens[image[pixel]];
}

Vous le voyez, c'est une opération extrêmement simple. Je suppose ici que les constantes IMAGE_WIDTH et IMAGE_HEIGHT ont été définies et valent respectivement la largeur et la hauteur de l'image à afficher.

Tracer l'image

Enfin, il ne reste plus qu'à tracer l'image chunky obtenue. Il existe deux fonctions de la graphics.library permettant de faire cela : WritePixelArray8() et WriteChunkyPixels(). La première est disponible sous AmigaOS 3.0 mais nécessite l'allocation d'un RastPort temporaire et ne fonctionne qu'avec une image multiple de 16 pixels en largeur, tandis que la seconde n'existe que depuis AmigaOS 3.1 et est plus simple d'utilisation. Une autre chose à noter en ce qui concerne WritePixelArray8() est que cette fonction efface l'image chunky ! (note : si j'en crois le fichier "readme" de NewWPA8, ce bogue affecte aussi WriteChunkyPixels(); mais ceci ne concerne pas les utilisateurs de cartes graphiques).

Nous utiliserons ici WriteChunkyPixels().

WriteChunkyPixels( win->RPort,        // RastPort sur lequel tracer
   win->BorderLeft, win->BorderTop,   // Position de l'angle supérieur gauche dans le RPort
   win->BorderLeft+IMAGE_WIDTH-1, win->BorderTop+IMAGE_HEIGHT-1,  // Angle inférieur droit
   image,                             // Données chunky à tracer
   IMAGE_WIDTH );                     // Nombre d'octets par ligne de l'image

Voyez l'AutoDoc de WriteChunkyPixels() pour les détails.

Voici le programme final, reprenant en partie la base mise en place dans les articles précédents. N'oubliez pas d'adapter IMAGE_WIDTH et IMAGE_HEIGHT à la taille de votre image.

#include <intuition/intuition.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <stdio.h>

#define IMAGE_WIDTH 320
#define IMAGE_HEIGHT 240

#include "image.h"
#include "palette.h"

int main(void)
{
   struct Window *win=NULL;
   struct ColorMap *cm;
   LONG tmpPen,pixel;
   WORD pen;
   UBYTE pens[256];

   // Ouverture de la fenêtre
   win = OpenWindowTags( NULL,
            WA_Title,       (ULONG)"Pouet",
            WA_InnerWidth,  IMAGE_WIDTH,
            WA_InnerHeight, IMAGE_HEIGHT,
            WA_DragBar,     TRUE,
            WA_CloseGadget, TRUE,
            WA_DepthGadget, TRUE,
            WA_IDCMP,       IDCMP_CLOSEWINDOW,
            TAG_END );

   if( !win ) {
      puts( "Impossible d'ouvrir la fenêtre." );
      return 10;
   }

   // Allocation des couleurs
   cm = win->WScreen->ViewPort.ColorMap;
   for( pen=0; pen<(palette[0]>>16); pen++ ) {
      tmpPen = ObtainBestPen( cm,
                  palette[pen*3+1],
                  palette[pen*3+2],
                  palette[pen*3+3],
                  OBP_Precision, PRECISION_ICON, TAG_END );
      if( tmpPen==-1 ) break;
      else pens[pen]=tmpPen;
   }

   if( tmpPen==-1 ) {
      puts( "Impossible d'allouer un pinceau !" );
      CloseWindow( win );
      return 10;
      // Note : en l'absence de la balise OBP_FailIfBad, s'il est impossible
      // d'allouer un pinceau, alors il est impossible d'allouer tous les
      // pinceaux. Il est donc inutile de les libérer avant de quitter...
   }

   // Recalcul des pixels
   for( pixel=0; pixelRPort,        // RastPort sur lequel tracer
      win->BorderLeft, win->BorderTop,   // Position de l'angle supérieur gauche dans le RPort
      win->BorderLeft+IMAGE_WIDTH-1, win->BorderTop+IMAGE_HEIGHT-1,  // Angle inférieur droit
      image,                             // Données chunky à tracer
      IMAGE_WIDTH );                     // Nombre d'octets par ligne de l'image

   WaitPort( win->UserPort );

   CloseWindow( win );

   // Libération des pinceaux
   for( pen=0; pen<(palette[0]>>16); pen++ ) {
      ReleasePen( cm, pens[pen] );
   }

   return 0;
}

Vous pouvez voir que, dans un souci de simplification, il n'y a plus d'ouverture de bibliothèques. En effet, la plupart des compilateurs disposent d'un mécanisme d'ouverture automatique des bibliothèques système telles qu'intuition.library et graphics.library (avec vbcc, il suffit de rajouter "-lauto" sur la ligne de commande). L'inconvénient de cette méthode est qu'on a moins de contrôle sur les versions des bibliothèques et qu'on ne peut pas afficher de message d'erreur adéquat en cas d'échec. Mais afin de ne pas surcharger les programmes d'exemple, j'ai décidé de laisser faire le compilateur ; vous pouvez toujours remettre les ouvertures et fermetures de bibliothèques si nécessaire.

Une précision importante au sujet de la libération des pinceaux que j'ai oubliée de mentionner dans le précédent article : si vous libérez un pinceau alors que votre image est toujours affichée, ses couleurs risquent de changer si un autre programme alloue lui aussi des pinceaux à ce moment-là. Donc il ne faut libérer les pinceaux qu'une fois que l'image n'est plus visible ! A noter cependant que ce problème ne se pose pas sur les écrans HiColor/TrueCOlor, puisqu'ils ne sont pas réellement palettisés...

Enfin, si votre application utilise beaucoup WriteChunkyPixels(), recommandez à vos utilisateurs sous AGA l'installation d'un correctif tel que NewWPA8 ou BlazeWCP qui accélère énormément les fonctions de tracé chunky. De plus, il devrait corriger le bogue de WritePixelArray8() faisant que l'image est effacée lors du tracé.


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]