CODINGSDCC TUT'S PAR STEPHBB75 ★ Afficher une image ★

Sdcc - 22 - Afficher uneImageCoding Sdcc Tut's Par Stephbb75

Afficher une image

Alors la afficher une image n'a rien de très compliqué, surtout ci celle ci n'est pas compressé.
Bon ok, sous basic pour charger une image il suffit de faire un LOAD"file",49152, un ,49152 ??? oui 49152 = C000, l'adresse de départ de l'écran...

Donc en C il suffit de faire la même chose, on charge notre fichier image à l'adresse C000 et l'image s'affiche, mais bien souvent on n'a pas utilisé les couleurs par défaut du CPC, on les a redéfini pour notre image. Il faut donc avant changer les encres, mais il faut faire un code spécifique pour chaque image.
Ce qui serais bien mieux se serais de lire les couleurs en même temps que l'image, mais ces informations ne sont pas présentent dans l'image. Par contre on peut les avoir avec un autre fichier qui est bien souvent avec l'extension .PAL. Attention, tous les fichiers .PAL ne sont pas forcement identique, la on va voir les fichiers .PAL généré avec OCP art studio, ConvImgCpc, JavaPaint,...

Explication :
Ce fichier comporte le mode d'écran utilisé, la palette est bien d'autre choses, nous n'allons nous intéressé qu'a une petite partie du fichier, en effet il permet de sauver des animations de couleurs, les encre exclue, protégé,...
Le 1er octet c'est le mode d'écran, cela nous intéresse, les 2 octets suivant non, c'est pour l'animation de couleur. Ensuite on a un tableau de 16 * 12 pour les couleurs, puis 12 octets pour la couleur du border, puis 32 octets d'on on ne s'occuperas pas !.
Un mot sur les couleurs sauvé, on ne peut pas les utiliser comme cela avec les fonctions systèmes car c'est les valeurs pour le CRT qui est directement sauvé, comme la on utilise les fonctions système pour changer les couleur, il faut donc les transformer, pour cela on vas utiliser un tableaux.
Voici donc le code pour utiliser les données en mémoire venant d'un fichier .PAL :

const unsigned char CpcVGA[ 28 ] = {84,68,85,92,88,93,76,69,77,86,70,87,94,64,95,78,71,79,82,66,83,90,89,91,74,67,75,0};

void main()
{
    char* BufPal;

    unsigned char i;
    unsigned char j;

    
    // chargement du fichier .pal
    ReadFileBin( "001.pal", 0x4000);
    BufPal = (char*)((unsigned int)0x4000);
    // met le bon mode
    if ( BufPal[0] == 0 )
        SCR_SET_MODE0_s;
    if ( BufPal[0] == 1 )
        SCR_SET_MODE1_s;
    if ( BufPal[0] == 2 )
        SCR_SET_MODE2_s;
    
    // met les couleurs
    BufPal = (char*)((unsigned int)0x4000+3);
    for ( i = 0; i < 16; i++ )
    {
        for ( j = 0; j < 27; j++ )
        {
            if ( BufPal[ i*12 ] == CpcVGA[ j ] )
            {
                SetColor_s( i, j );
            }
        }
    }
    
    // chargement de l'images non compresse.
    ReadFileBin( "001.SCR", 0xC000);

    // attente d'une touche
    KM_WAIT_CHAR_s;
}


Ici il n'y a pas toute les fonctions, il faut la lecture du fichier, mettre les couleurs, les modes, ... tout ceci est dans le ZIP final.

Au vue de la capacité standard des disquettes du CPC (je vous le rappelle, c'est 178Ko) on ne pourra mettre que 178Ko / 16Ko (oui une image fait 16Ko !) donc 11 images, il reste un reliquat de 2Ko pour mettre notre programme. Donc si le programme pour afficher les images fait plus de 2Ko, on ne mettras que 10 images sur un face de disquette.

Il faut bien avouer que l'affichage de l'image n'est pas trop super, elle s'affiche quand elle se charge et vue la gestion mémoire de la vidéo, on voie l'image s'afficher 1 ligne sur 8, on vas voire pour faire un peut mieux.
Première solution, avant de charger l'image on passe l'affichage en la vidéo en 0x4000, on charge la palette et l'image en 0xC000 et on rebascule l'affichage vidéo en 0xC000, ce qui fait que notre image s'affiche d'un coup.
Mais avec cette il y a un petit problème quand même, pendant que l'image se charge, on a un écran vide, a moins de gérer le chargement à différent endroit en fonction de la page vidéo affiché.
On vas donc faire apparaitre notre image d'autre façon, avec comme seul contrainte de la charger en 0x4000 et affiché en 0xC000.
Le plus classique c'est faire apparaitre l'image de haut en bas ou de bas en haut, voici le code :

    // affichage de l'image en partant du haut de l'image vers le bas
    for (y = 0; y<200; y++)
    {
        // calcule de l'adresse de debut de al ligne
        iAdr = ( y >> 3 ) * 80 + ( y & 7 ) * 0x800;
        
        for (x = 0; x<80; x++)
        {
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }

    KM_WAIT_CHAR_s;
    CLS_WithPile();
    
    // affichage de l'image en partant du bas de l'image vers le haut
    for (yi = 199; yi>=0; yi--)
    {
        // calcule de l'adresse de debut de al ligne
        iAdr = ( yi >> 3 ) * 80 + ( yi & 7 ) * 0x800;
        
        for (x = 0; x<80; x++)
        {
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }


On peut faire la même chose de droite à gauche ou inversement :

    // affichage de l'image en partant de la droite vers la gauche
    for (x = 0; x<80; x++)
    {
        for (y = 0; y<200; y++)
        {
            // calcule de l'adresse de debut de al ligne
            iAdr = ( y >> 3 ) * 80 + ( y & 7 ) * 0x800;
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
    }


    KM_WAIT_CHAR_s;
    CLS_WithPile();
    
    // affichage de l'image en partant de la gauche vers la droite
    for (xc = 79; xc>=0; xc--)
    {
        for (y = 0; y<200; y++)
        {
            // calcule de l'adresse de debut de al ligne
            iAdr = ( y >> 3 ) * 80 + ( y & 7 ) * 0x800;
            BufScr[iAdr+xc] = BufDep[iAdr+xc];
        }
    }


On peut aussi faire apparaitre l'image par petits carré (aléatoire), la j'introduit la gestion pour les nombres aléatoire j'y reviens ensuite.
La cela se complique un peut, on fait une matrice de carré, puis on les mélange et on affiche :

    // affichage de l'image par carré (aléatoire):
    // les blocs font 16*8, il y a donc 20 blocs (4 octets par bloc) en X et 25 bloc en Y
    // on vas faire une matrice de bloc en mémoire

    //Initialise la matrice
    for(my=0;my<25;my++)
    {
        for(mx=0;mx<20;mx++)
        {
            Bufmatrice[mx][my].x = mx*16;
            Bufmatrice[mx][my].y = my*8;
        }    
    }

    //Melange la matrice
    m_randomize();
    for(my=0;my<25;my++)
    {
        for(mx=0;mx<20;mx++)
        {
            ir=m_random(19);    //Bloc aleatoire
            jr=m_random(24);
            
            //Echange avec un autre bloc
            BufmatriceTMP.x = Bufmatrice[mx][my].x;
            Bufmatrice[mx][my].x = Bufmatrice[ir][jr].x;
            Bufmatrice[ir][jr].x = BufmatriceTMP.x;

            BufmatriceTMP.y = Bufmatrice[mx][my].y;
            Bufmatrice[mx][my].y = Bufmatrice[ir][jr].y;
            Bufmatrice[ir][jr].y = BufmatriceTMP.y;
        }    
    }

    //Affiche la matrice
    for(my=0;my<25;my++)
    {
        WaitVbl();
        
        for(mx=0;mx<20;mx++)
        {
            for(y=0;y<8;y++)
            {
                // calcule de l'adresse de debut de la ligne
                iAdr = ( (Bufmatrice[mx][my].y+y) >> 3 ) * 80 + ( (Bufmatrice[mx][my].y+y) & 7 ) * 0x800;

                BufScr[iAdr+(Bufmatrice[mx][my].x/4)] = BufDep[iAdr+(Bufmatrice[mx][my].x/4)];
                BufScr[iAdr+(Bufmatrice[mx][my].x/4)+1] = BufDep[iAdr+(Bufmatrice[mx][my].x/4)+1];
                BufScr[iAdr+(Bufmatrice[mx][my].x/4)+2] = BufDep[iAdr+(Bufmatrice[mx][my].x/4)+2];
                BufScr[iAdr+(Bufmatrice[mx][my].x/4)+3] = BufDep[iAdr+(Bufmatrice[mx][my].x/4)+3];
            }
        }
    }


Alors la gestion pour les nombres aléatoire, j'ai refait des fonctions m_randomize et m_random un peut comme le C (du moins pour les prototypes) car pour le reste c'est une adaptation pour CPC.
Je ne vais pas rentré dans l'explication des nombres aléatoire, c'est en fait très très compliqué à faire (si si !!) car pour faire vite on n'a jamais des nombres aléatoire mais des suites ...
Je suis partit du timer du CPC pour faire les nombres aléatoire, quand on appel la méthode m_randomize, je conserve l'octet de poids fort que nous fournis le timer du CPC.
Puis à chaque fois que l'on appel la méthode m_random je fait un calcule super savant (la c'est du 4ème ou 5ème degré !!), je reprend le poids fort du timer du CPC et je le multiplie pas celui sauvé avant, puis un modulo avec la valeur max.
On a donc rien d'aléatoire en fait, mais cela vas nous convenir, vous pouvez trouver bien d'autre méthode pour faire cela ....
Pourquoi ce n'est pas vraiment des nombre aléatoire ?
Car quand vous allumer le CPC, sont timer part de 0 et tous les 1/300 de seconde s'incrémente de 1...
Dans notre cas, si vous allumer le CPC, exécuter le programme vous aurez donc une suite de nombres.
La il faut être très fort mais si vous allumer votre CPC, exécuter votre programme et que cela tome sur les même 1/300 de seconde que le 1er essai, vous aurez la même suite de nombre que la 1er fois !!!

Un dernier effet pour afficher une image, l'effet roulo :

unsigned char Roulo[12]={62,58,54,50,46,43,40,37,35,33,32,31};

    hroulo = 12;//23;
    for(i=0;i> 3 ) * 80 + ( yr & 7 ) * 0x800;
                iAdrd = ( y+i >> 3 ) * 80 + ( y+i & 7 ) * 0x800;
                for (x = 0; x<80; x++)
                {
                    BufScr[iAdrd+x] = BufDep[iAdr+x];
                }
                
            }
        }
        
        // calcule de l'adresse de debut de la ligne
        iAdr = ( y >> 3 ) * 80 + ( y & 7 ) * 0x800;
        for (x = 0; x<80; x++)
        {
            BufScr[iAdr+x] = BufDep[iAdr+x];
        }
        
    }


Voila, il n'y a plus qu'a utiliser, chercher d'autre effet, mais y'a plus de secret pour afficher une image avec sont fichier .PAL sur CPC.
Il ne reste plus qu'a faire des images pour faire un SlideShow.
Le seul inconvénient, on ne peut pas mettre plus de 11 images sur une face de disquette... sinon il faut compresser... c'est pour l'article suivant.


Voila, comme d'hab, le tout se trouve dans se ZIP, bon SlideShow ;-)

stephbb75

ANNÉE: 2013
★ AUTEUR: Stephbb75

Page précédente : Sdcc - 21 - 3D - Face Plaine 2

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 079 millisecondes et consultée 1221 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.