Obligement - L'Amiga au maximum

Vendredi 24 mai 2019 - 04:47  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

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

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


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


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


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - Convertisseur d'image IFF en source ASCII C ou assembleur
(Article écrit par Denis Genot et extrait d'Amiga News Tech - décembre 1991)


Qui n'a pas rêvé de se faire de beaux gadgets ou de superbes images agrémentant la présentation d'un logiciel que l'on sait en son fort intérieur être le précurseur d'une nouvelle génération de logiciels ?

Ne désespérez plus, voici l'outil ultime, j'ai nommé le Transformeur. La démarche est la suivante : vous prenez votre logiciel de DAO préféré, vous faîtes le dessin de vos rêves, puis, grâce ce programme, vous transformez l'image (ou la brosse) en une suite de nombres au format ASCII, ce qui constitue (comme chacun sait) un fichier source que vous pouvez insérer ou relier... Ah que ouais !

Images IFF

Il est nécessaire de sauvegarder votre dessin au format IFF, ce que font les 9/10e des utilitaires de dessin (sinon, prenez-en un autre !). Les images IFF sont codées sous une forme standard qui permet le chargement par d'autres logiciels (mon mari).

Pour mieux saisir le fonctionnement, un bref rappel du format IFF n'est sans doute pas inutile ; suivez sur le listing, à la fonction "analyse()". Chaque image IFF comporte une suite de blocs de données (chunks) dont l'ordre n'est pas imposé. Un bloc de données peut être représenté par une structure C :

struct Chunk
{   ULONG ckID;
    LONG ckSize;
/*  UBYTE ckData[cksize]; */
};

Où "ckID" est un mot long servant d'identificateur au bloc de données et dont la valeur est exprimée sous forme ASCII (FORM, BMHD, CMAP, BODY, etc.), où "ckSize" représente la taille du bloc de données en octets et où "ckData" (qui suit directement le bloc de données) contient les octets de données (de longueur variable, donc).

Si le fichier IFF est uniquement constitué d'une image, son premier bloc de données doit avoir pour identificateur "FORM". Les autres identificateurs possibles (CAT, PROP, LIST) sont donc rejetés, car ils indiquent un mélange de divers types, par exemple texte et dessin.

Les données de ce premier bloc de données sont elles-mêmes formées d'autres blocs de données. Si le fichier étudié est une image, le second identificateur qui se présente doit être de type ILBM. Les autres identificateurs (FTXT, SMUS, 8SVX) sont rejetés car ils indiquent respectivement un fichier texte, musique ou instrument.

On arrive alors aux blocs de données utilisables : BMHD, BODY, CMAP (il y en a d'autres, mais seuls ces trois-là nous intéressent ici) :
  • BMHD contient les caractéristiques de l'image : largeur, hauteur, nombre de bitplanes, compression, etc. (voir "case ID_BMHD" dans le listing).
  • BODY contient les bitplanes eux-mêmes, la valeur de chaque bit déterminant la couleur du pixel correspondant (voir "case ID_BODY"). Quand ce bloc de données a été trouvé, il importe de décompacter les données si c'est nécessaire, c'est ce que fait la fonction "transfert()".
  • CMAP contient les couleurs de l'image, à noter pour pouvoir restituer l'image dans sa pureté primitive... Là encore, voyez la partie "case ID_CMAP".
Ces trois blocs de données peuvent être trouvés dans n'importe quel ordre, ce qui explique l'étude du fichier sur toute sa longueur et un test final pour savoir si les données nécessaires ont été trouvées. Il ne reste plus alors qu'à sortir les valeurs des bitplanes en fichier source.

Comment ça marche

Le Transformeur vous demande le type de source que vous désirez créer : "C" si vous programmez en C et "A" si vous programmez en assembleur (logique !). Il vous demande alors le nom du fichier à charger : image ou brosse. Il travaille quelque temps, affiche les couleurs de l'image en hexadécimal, vous demande le nom du source qu'il va créer et ça baigne.

Ah, j'oubliais : ce programme utilise l'arp.library, qui doit figurer dans le tiroir LIBS: de votre disquette système.

Les sources produits en C sont de type "USHORT data[]". Les bitplanes sont séparés par une remarque qui rappelle le nombre de lignes et de colonnes. Un programme d'exemple est fourni sur la manière d'utiliser ces sources.

Les sources produits en assembleur sont aussi en hexadécimal, de type "dc.w" avec une séparation des bitplanes comme ci-dessus. Le programme d'exemple pourra être adapté de celui qui est fourni en C.

/***************************************************
* Convertit une image IFF en SOURCES-ASCII         *
*                                                  *
* par D.GENOT sous LATTICE SAS v5.10 :             *
*        options de compil :  -L                   *
***************************************************/                 

#include<exec/types.h>
#include<stdio.h>
#include<libraries/dos.h>
#include<string.h>
#include<libraries/dosextens.h>
#include<exec/memory.h>
#include<intuition/intuition.h>
#include<graphics/gfx.h>
#include<graphics/view.h>

#pragma libcall ArpBase FileRequest 126 801

/********** déclarations ******************/

LONG FileRequest(); 
LONG input(UBYTE *);
void output_C();
void output_A();

struct FileLock *Lock();
struct FileLock *clef=NULL;
struct FileInfoBlock bloc;
short Examine();
short ExNext();
void UnLock();
void cleanexit();
void load_fichier();
void analyse();
void lib_mem();
void transfert(UBYTE *);

/********* variables ****************/
short res;
ULONG filesize;
ULONG planes_long;
ULONG plane1;
UBYTE fdir;		/*flag DIR */
UBYTE prof;
UWORD haut;

char categ=' ';
LONG resul;
int dummy=0;
int hdle;
int ncoul;
ULONG nom,mode;
ULONG taille;
int vu;
int long_forme;
SHORT bpr;		/* Bytes Per Row = par rangée */

APTR *filemem=NULL;
UBYTE *pteurb=NULL;
ULONG *pteurl=NULL;
UBYTE *planeptr=NULL;

char fname[80];
char dirname[120];
char nom_complet[200];

APTR ArpBase=NULL;

/***********************************************************
* definitions diverses utilisées pour le maniement des     *
* images IFF (simples...)                                  *
***********************************************************/

#define MAKEID(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|d)

#define ID_CAT    MAKEID('C', 'A', 'T', ' ')
#define ID_FTXT   MAKEID('F', 'T', 'X', 'T')
#define ID_PROP   MAKEID('P', 'R', 'O', 'P')
#define ID_8SVX   MAKEID('8', 'S', 'V', 'X')
#define ID_SMUS   MAKEID('S', 'M', 'U', 'S')
#define ID_LIST   MAKEID('L', 'I', 'S', 'T')
#define ID_FORM   MAKEID('F', 'O', 'R', 'M')
#define ID_ILBM   MAKEID('I', 'L', 'B', 'M')
#define ID_BMHD   MAKEID('B', 'M', 'H', 'D')
#define ID_CMAP   MAKEID('C', 'M', 'A', 'P')
#define ID_GRAB   MAKEID('G', 'R', 'A', 'B')
#define ID_DEST   MAKEID('D', 'E', 'S', 'T')
#define ID_CAMG   MAKEID('C', 'A', 'M', 'G')
#define ID_BODY   MAKEID('B', 'O', 'D', 'Y')

/********** structures *****************/

struct Chunk
{
LONG ckID;
LONG ckSize;
};

struct Chunk *chk=NULL;

#define isodd(a) ((a) & 1)	        /* --> 1 si impair */
#define wa(size) ((size) + isodd(size)) /* complète au mot près */
#define chsize(datasize) (wa(datasize) + 8) /* taille du chunk */

struct FileRequester
{
UBYTE *fr_titre;     /* texte fenetre */
UBYTE *fr_file;      /*    filename   */
UBYTE *fr_dir;       /*    dirname    */
struct Window *fr_window; /*  Win voulue ou NULL */
UBYTE fr_flags;       /*    flags            */
UBYTE fr_reserved1;       /*    mettre à 0       */
APTR fr_fonction;         /*  UserFunction       */
LONG fr_reserved2;        /*    occupe !         */
};

struct FileRequester Freq=
{"   Mon Requester  ",fname,dirname,NULL,NULL,NULL,NULL,NULL};

struct BMHD 
	{
	UWORD bmhd_w;
	UWORD bmhd_h; 	/* largeur et hauteur */
	UWORD bmhd_x;
	UWORD bmhd_y;	/*  position de l'image */
	UBYTE bmhd_nplanes;
	UBYTE bmhd_masking;
	UBYTE bmhd_compress;
	UBYTE bmhd_pad1;
	UWORD bmhd_transpcolor;
	UBYTE bmhd_xaspect;
	UBYTE bmhd_yaspect;
	UWORD bmhd_pagew;
	UWORD bmhd_pageh;
	};
struct BMHD *bmhd=NULL;


/***** ROUTINES ********/
  
LONG input(UBYTE *txt)
{
register LONG reponse;

Freq.fr_titre=txt;

ArpBase=(APTR)OpenLibrary("arp.library",0);
if (ArpBase==NULL)	
    {
    printf("Il me faut la 'ARP.LIBRARY' ...");
    exit(FALSE);
    }

reponse=FileRequest(&Freq);  

CloseLibrary(ArpBase);

if(reponse)
  strmfp(nom_complet,dirname,fname);

return(reponse);
}

void cleanexit()
{
if(clef)
	UnLock(clef);
if(hdle)
	Close(hdle);
if(planeptr)
	FreeMem(planeptr,planes_long);
if(filemem)
	FreeMem(filemem,filesize);

exit(RETURN_OK);
}

void load_fichier()
{

filemem=(APTR *)AllocMem(filesize,MEMF_CLEAR|MEMF_PUBLIC);
if(filemem==NULL)
	{
	printf("\n Impossible de réserver la mémoire ...\n");
 	cleanexit();
	}

hdle=Open(nom_complet,MODE_OLDFILE);	/* lecture */
if(hdle==NULL)
	{
	printf("\n Impossible d'ouvrir ce #&!!§/ù? fichier ...\n");
	cleanexit();
	}
else
	{
	Read(hdle,filemem,filesize);
	Close(hdle);
	hdle=0;
	printf("\n Fichier lu ...\n");
	}
}

void analyse()
{
BOOL filbm=FALSE;
BOOL fbmhd=FALSE;
BOOL fbody=FALSE;
SHORT var;
UWORD couleur;
int ncoul;
UBYTE re,gr,bl;		/* red ,green ,blue */

chk=(struct Chunk *)filemem;
switch (chk->ckID)
	{
	case ID_CAT:
	case ID_PROP:
	case ID_LIST:
		printf("\n C'est un fichier IFF composé\n");
		filbm=FALSE;
		break;
	case ID_FORM:
 		filbm=TRUE;
		break;
	default:
		printf("\n Ce n'est pas un fichier IFF ...\n");
		filbm=FALSE;
		break;
	}
if( !filbm )
	cleanexit();

taille=chk->ckSize;
long_forme=taille;

pteurl=(ULONG *)chk;
pteurl++;
pteurl++;
chk=(struct Chunk *)pteurl;

vu=8;

switch (chk->ckID)
	{
	case ID_FTXT:
		printf("\n C'est un TEXTE ...\n");
		filbm=FALSE;
		break;
	case ID_SMUS:
		printf("\n C'est de la MUSIQUE ...\n");
		filbm=FALSE;
		break;
	case ID_8SVX:
		printf("\n C'est un INSTRUMENT musical ...\n");
		filbm=FALSE;
		break;
	case ID_ILBM:
		filbm=TRUE;
		break;
	default:
		printf("\n Ce n'est pas un format ILBM\n");
		filbm=FALSE;
		break;
	}
if( !filbm )
	cleanexit();

vu+=4;

pteurl=(ULONG *)chk;
pteurl++;
chk=(struct Chunk *)pteurl;
		
do
	 {
	 taille=chsize(chk->ckSize);	/* taille du CHUNK */
	 vu+=taille;
	 
	 switch(chk->ckID)
		{
		case ID_BMHD:
			fbmhd=TRUE;

			pteurl=(ULONG *)chk;
			pteurl++;
			pteurl++;
			bmhd=(struct BMHD *)pteurl;

			prof = bmhd->bmhd_nplanes;
			haut = bmhd->bmhd_h;

			bpr=bmhd->bmhd_w;
			var=bpr%16;
			var=16-var;
			bpr+=var;	/* multiple de 16 */
			bpr/=8;		/* octets / rangée */
			break;

		case ID_BODY:
			if ( fbmhd )
				{
				/* taille datas : chk->ckSize */
				pteurl=(ULONG *)chk;
				pteurl++;
				pteurl++;
			        fbody=TRUE;
				transfert( (UBYTE *)pteurl );
				}
			else
				fbody=FALSE;
         break;
		case ID_CMAP:
			pteurl=(ULONG *)chk;
			pteurl++;
			pteurl++;
			pteurb=(UBYTE *)pteurl;
			ncoul=(int)( (chk->ckSize)/3);
			printf("\n      %d COULEUR(S) = '$RGB'\n ",ncoul);
			while(ncoul--)
			{
				re=*pteurb++;
				gr=*pteurb++;
				bl=*pteurb++;
				couleur=((UWORD)(re)*0x100+(UWORD)(gr)*0x10+(UWORD)bl)/0x10;
				
				printf("$%3X ",couleur);
			}
			break;
		default:
			break;
		}
	
	 pteurb=(UBYTE *)chk+taille;
	 chk=(struct Chunk *)pteurb;

	 }while( vu < long_forme );

if( !fbody )
	cleanexit();

printf("\n Analyse terminée ...\n");
}

void transfert(dptr)
UBYTE *dptr;
{
register UBYTE pixel,*pixelptr;
register SHORT plane,row,nbytes,count;


planes_long=bpr * bmhd->bmhd_h;		/* 1 bitplane             */
plane1=planes_long;					/* long d'un bitplane	 */
planes_long*=prof;		/* 4 bitplanes ou plus ...*/

planeptr=(UBYTE *)AllocMem(planes_long,MEMF_CLEAR|MEMF_PUBLIC);
if(planeptr==NULL)
	{
	printf("\n Impossible de réserver la mémoire des datas ...\n");
 	cleanexit();
	}

if(bmhd->bmhd_compress==1)   /* compression habituelle */
	{
	for(row=0;row<bmhd->bmhd_h;row++)
		{
		for(plane=0;plane<bmhd->bmhd_nplanes;plane++)
			{
			pixelptr=planeptr+(plane*plane1)+(row*bpr);
			nbytes=bpr;
			while(nbytes > 0)
				{
				count=(char)*dptr++;
				if(count >= 0)			/* copier n+1 littéral */
					{
					count++;
	 				nbytes-=count;
					while(count--)
						*pixelptr++=*dptr++;
					}
				else if(count >= -127)	/* répéter next -n+1 fois */
					{
					count=1-count;
					nbytes-=count;
					pixel=*dptr++;
					while(count--)
						*pixelptr++=pixel;
					}
				}
			}
		}
	}
else             /* pas de compression ( ou inconnue !! ) */
	{
	for(row=0;row<bmhd->bmhd_h;row++)
		{
		for(plane=0;plane<bmhd->bmhd_nplanes;plane++)
			{
			pixelptr=planeptr+(plane*plane1)+(row*bpr);
			nbytes=bpr;
			while(nbytes--)
				*pixelptr++=*dptr++;
			}
		}
	}
}

void lib_mem()
{
if(hdle)
	Close(hdle);
hdle=0;

if(filemem)
	FreeMem(filemem,filesize);
filemem=0;
}

void output_C()
{
register SHORT plane,row,nword,wpr;
UWORD *wordptr;
FILE *fp,*fopen();
char tpn[80];
SHORT cpt;
int i;

fp=fopen(nom_complet,"w");	/* écriture               */

if(fp==NULL)
	{
	printf("\n Impossible d'ouvrir ce #&!!§/ù? fichier ...\n");
	cleanexit();
	}

wpr=bpr/2;

for(plane=0;plane<prof;plane++)
	{
	fputc('\12',fp);		/* ligne suivante	*/
	sprintf(tpn," /* bitplane No %d : %d lignes de %d mots */ ",plane+1,haut,wpr);
	fwrite(tpn,1,(UBYTE)strlen(tpn),fp);
	fputc('\12',fp);		/* ligne suivante	*/
	cpt=0;
	sprintf(tpn,"     ");
	fwrite(tpn,1,5,fp);		/*  # tabulation */

	for(row=0;row<haut;row++)
		{
		wordptr=(UWORD *)( planeptr+(plane*plane1)+(row*bpr) );
		nword=wpr;
	
		while(nword--)
			{
			sprintf(tpn,"0x%4X,",*wordptr);
			for(i=0;i<=3;i++)
				{
				if( tpn[2+i] == ' ' )
					tpn[2+i]='0';
				}	
			fwrite(tpn,1,(UBYTE)strlen(tpn),fp);
			wordptr++;
			cpt++;
			if( cpt==8 )
				{
				fputc('\12',fp);		/* ligne suivante	*/
				sprintf(tpn,"     ");
				fwrite(tpn,1,5,fp);			/*  # tabulation */
				cpt=0;
				}
			}/*fin de la rangée */
	
		}/* fin du bitplane	*/
	}
fclose(fp);
}

void output_A()
{
register SHORT plane,row,nword,wpr;
UWORD *wordptr;
FILE *fp,*fopen();
char tpn[80];
SHORT cpt;
int i;

fp=fopen(nom_complet,"w");			/* écriture               */

if(fp==NULL)
	{
	printf("\n Impossible d'ouvrir ce #&!!§/ù? fichier ...\n");
	cleanexit();
	}

wpr=bpr/2;

for(plane=0;plane<prof;plane++)
	{
	fputc('\12',fp);		/* ligne suivante	*/
	sprintf(tpn," ; bitplane No %d : %d lignes de %d mots  ",plane+1,haut,wpr);
	fwrite(tpn,1,(UBYTE)strlen(tpn),fp);
	fputc('\12',fp);		/* ligne suivante	*/
	cpt=0;
	sprintf(tpn,"    DC.W ");
	fwrite(tpn,1,9,fp);			/*  # tabulation */

	for(row=0;row<haut;row++)
		{
		wordptr=(UWORD *)( planeptr+(plane*plane1)+(row*bpr) );
		nword=wpr;
	
		while(nword--)
			{
			sprintf(tpn,"$%4X",*wordptr);
			for(i=0;i<=3;i++)
				{
				if( tpn[1+i] == ' ' )
					tpn[1+i]='0';
				}	
			fwrite(tpn,1,(UBYTE)strlen(tpn),fp);
			wordptr++;
			cpt++;
			if( cpt==8 )
				{
				fputc('\12',fp);		/* ligne suivante	*/
            if( (row != haut-1)||(nword != 0) )
              {
				  sprintf(tpn,"    DC.W ");
				  fwrite(tpn,1,9,fp);			/*  # tabulation */
              }
				cpt=0;
				}
			else
				{
				if( (row != haut-1)||(nword != 0) )
					fputc(',',fp);		/* + la virgule */
				}

			}/*fin de la rangée */
	
		}/* fin du bitplane	*/
	}
fclose(fp);
}


/***************  ROUTINE PRINCIPALE  **********/

void main()
{

do
	{
	printf("\n Type de SOURCE voulu :");
   printf("\n 'C' pour LATTICE ");
   printf("\n 'A' pour DEVPAC    ");
	categ=fgetchar();
	if(categ == 'a')
		categ='A';
	if(categ == 'c')
		categ='C';
	}while( (categ != 'C')&&(categ != 'A') );

resul=input("NOM de l'IMAGE IFF à LIRE");
if( resul == 0)
 	cleanexit();

printf("\n       CHEMIN : '%s'    ; FICHIER : '%s' \n",dirname,fname);

clef=Lock(nom_complet,ACCESS_READ);
if(clef==NULL)
	{
	printf("\n Accès lecture impossible : le chemin existe ?\n");
	cleanexit();
	}

res=Examine(clef,&bloc);

if(bloc.fib_DirEntryType>0)
	{
	printf("\n C'est un répertoire ...\n\n");
	cleanexit();
	}

filesize=bloc.fib_Size;

if(filesize != 0)
	{	
	load_fichier();
	analyse();
	}
lib_mem();		/* libère une partie de la mémoire et le handle */

UnLock(clef);
clef=0;

if(categ == 'C')
	resul=input("NOM du SOURCE-C à CREER");
else
	resul=input("NOM du SOURCE-ASSEMBLEUR à CREER");
	
if( resul == 0)
 	cleanexit();

printf("\n       CHEMIN : '%s'    ; FICHIER : '%s' \n",dirname,fname);

printf("\n Sortie en cours ... \n");

if(categ == 'C')
	output_C();
else
	output_A();

cleanexit();

}


[Retour en haut] / [Retour aux articles]