[C++] Code pour compresser une image, ça marche pas... Help please

Code pour compresser une image, ça marche pas... Help please [C++] - Programmation

Marsh Posté le 08-10-2001 à 22:15:34    

J'ai écrit un code qui devrait normalement compresser grâce à la quantification vectorielle des images bitmaps, mais ça a pas l'air de marcher trop fort... Disons que le dictionnaire ne se crée pas correctement, si vous pouviez essayer de repérer les erreurs.
 
Merci d'avance.
:)
 
 
 
#include <windows.h>
#include <time.h>
#include <fstream>
#include <vector>
#include <iostream>
using namespace std;
 
#define for if(1) for
 
///////////////////////////////////////////////////////////////////
 
struct SBlock
{
 long vector[12];
 short tableref;
 long distance;
};
 
///////////////////////////////////////////////////////////////////
 
struct STable
{
 long vector[12];
 short nblock;
 vector<short> blockref;
};
 
///////////////////////////////////////////////////////////////////
 
int CompressImage(char szLoadPath[400], char szSavePath[400], short Width, short Height,
      short NVECTORTABLE, short NLOOPTABLE)
{
 //Chargement du bitmap à compresser
 
 cout << "Chargement du bitmap" << endl;
 
 HDC hdcImage;
 HBITMAP hbm;
 
 hbm = (HBITMAP)LoadImage( NULL, szLoadPath, IMAGE_BITMAP, Width, Height,
        LR_LOADFROMFILE | LR_CREATEDIBSECTION);
 
 if (hbm == NULL)
  return 1;
 
    hdcImage = CreateCompatibleDC(NULL);
    SelectObject(hdcImage, hbm);
 
 
 //Création des blocks 2*2 de vecteurs
 
 cout << "Creation des blocks" << endl;
 
 SBlock *block = new SBlock[(Width / 2) * (Height / 2)];
 short nBlock = 0;
 
 int pixelvalue;
 
 for (short y = 0; y < Height - 1; y += 2)
 {
  for (short x = 0; x < Width - 1; x += 2)
  {
   short r, g, b;
 
   pixelvalue = GetPixel(hdcImage, x, y);
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
   block[nBlock].vector[0] = r;
   block[nBlock].vector[1] = g;
   block[nBlock].vector[2] = b;
 
   pixelvalue = GetPixel(hdcImage, x+1, y);
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
   block[nBlock].vector[3] = r;
   block[nBlock].vector[4] = g;
   block[nBlock].vector[5] = b;
   
   pixelvalue = GetPixel(hdcImage, x, y+1);
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
   block[nBlock].vector[6] = r;
   block[nBlock].vector[7] = g;
   block[nBlock].vector[8] = b;
   
   pixelvalue = GetPixel(hdcImage, x+1, y+1);
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
   block[nBlock].vector[9] = r;
   block[nBlock].vector[10] = g;
   block[nBlock].vector[11] = b;
 
   nBlock++;
  }
 }
 
 
 //Création de la table initiale générée aléatoirement à partir des blocks
 
 cout << "Initialisation aleatoire de la table" << endl;
 
 STable *table = new STable[NVECTORTABLE];
 
 int randomblock = 0;
 int randomplus = nBlock / NVECTORTABLE;
 
 for (short i = 0; i < NVECTORTABLE; i++)
 {
  for (short y = 0; y < 12; y++)
   table[i].vector[y]= block[randomblock].vector[y];
 
  randomblock += randomplus - 1;
 }
 
 
 //Mise en référence de la table 0 pour tous les blocks
 
 cout << "Initialisation des blocks" << endl;
 
 for (short i = 0; i < nBlock; i++)
 {
  long distance = (table[0].vector[0] - block[i].vector[0]) * (table[0].vector[0] - block[i].vector[0]) +
      (table[0].vector[1] - block[i].vector[1]) * (table[0].vector[1] - block[i].vector[1]) +
      (table[0].vector[2] - block[i].vector[2]) * (table[0].vector[2] - block[i].vector[2]) +
      (table[0].vector[3] - block[i].vector[3]) * (table[0].vector[3] - block[i].vector[3]) +
      (table[0].vector[4] - block[i].vector[4]) * (table[0].vector[4] - block[i].vector[4]) +
      (table[0].vector[5] - block[i].vector[5]) * (table[0].vector[5] - block[i].vector[5]) +
      (table[0].vector[6] - block[i].vector[6]) * (table[0].vector[6] - block[i].vector[6]) +
      (table[0].vector[7] - block[i].vector[7]) * (table[0].vector[7] - block[i].vector[7]) +
      (table[0].vector[8] - block[i].vector[8]) * (table[0].vector[8] - block[i].vector[8]) +
      (table[0].vector[9] - block[i].vector[9]) * (table[0].vector[9] - block[i].vector[9]) +
      (table[0].vector[10] - block[i].vector[10]) * (table[0].vector[10] - block[i].vector[10]) +
      (table[0].vector[11] - block[i].vector[11]) * (table[0].vector[11] - block[i].vector[11]);
 
  block[i].tableref = 0;
  block[i].distance = distance;
 
  table[0].nblock++;
  table[0].blockref.push_back(i);
 }
 
 
 //Mise au point de la table
 
 cout << "Mise au point de la table" << endl;
 
 for (short loop = 0; loop < NLOOPTABLE; loop++)
 {
  //Recherche de la meilleur table pour chaque block
 
  cout << "1" << endl;
 
  for (short i = 0; i < nBlock; i++)
   for (short j = 0; j < NVECTORTABLE; j++)
   {
    long distance = (table[j].vector[0] - block[i].vector[0]) * (table[j].vector[0] - block[i].vector[0]) +
        (table[j].vector[1] - block[i].vector[1]) * (table[j].vector[1] - block[i].vector[1]) +
        (table[j].vector[2] - block[i].vector[2]) * (table[j].vector[2] - block[i].vector[2]) +
        (table[j].vector[3] - block[i].vector[3]) * (table[j].vector[3] - block[i].vector[3]) +
        (table[j].vector[4] - block[i].vector[4]) * (table[j].vector[4] - block[i].vector[4]) +
        (table[j].vector[5] - block[i].vector[5]) * (table[j].vector[5] - block[i].vector[5]) +
        (table[j].vector[6] - block[i].vector[6]) * (table[j].vector[6] - block[i].vector[6]) +
        (table[j].vector[7] - block[i].vector[7]) * (table[j].vector[7] - block[i].vector[7]) +
        (table[j].vector[8] - block[i].vector[8]) * (table[j].vector[8] - block[i].vector[8]) +
        (table[j].vector[9] - block[i].vector[9]) * (table[j].vector[9] - block[i].vector[9]) +
        (table[j].vector[10] - block[i].vector[10]) * (table[j].vector[10] - block[i].vector[10]) +
        (table[j].vector[11] - block[i].vector[11]) * (table[j].vector[11] - block[i].vector[11]);
 
    if (distance < block[i].distance)
    {
     for (short k = 0; k < table[block[i].tableref].nblock; k++)
     {
      if (table[block[i].tableref].blockref[k] == i)
      {
       table[block[i].tableref].nblock--;
       table[block[i].tableref].blockref.erase(table[block
[i].tableref].blockref.begin() + i);
 
       block[i].distance = distance;
       block[i].tableref = j;
 
       table[j].nblock++;
       table[j].blockref.push_back(i);
 
       break;
      }
     }
    }
   }
 
   
  //Affinage de la table en calculant les isobarycentres des groupes de blocks
 
  cout << "2"<< endl;
 
  for (short i = 0; i < NVECTORTABLE; i++)
  {
   for (short j = 0; j < 12; j++)
   {
    double coord = 0;
 
    for (short k = 0; k < table[i].nblock; k++)
     coord += block[table[i].blockref[k]].vector[j];
 
    coord = coord / table[i].nblock;
    table[i].vector[j] = (long) coord;
   }
  }
 
 
  //Mise à jour de la distance entre les blocks et la nouvelle table
 
  cout << "3" << endl;
 
  for (short i = 0; i <= nBlock; i++)
  {
   long distance = (table[block[i].tableref].vector[0] - block[i].vector[0]) * (table[block[i].tableref].vector[0] - block[i].vector[0]) +
       (table[block[i].tableref].vector[1] - block[i].vector[1]) * (table[block[i].tableref].vector[1] - block[i].vector[1]) +
       (table[block[i].tableref].vector[2] - block[i].vector[2]) * (table[block[i].tableref].vector[2] - block[i].vector[2]) +
       (table[block[i].tableref].vector[3] - block[i].vector[3]) * (table[block[i].tableref].vector[3] - block[i].vector[3]) +
       (table[block[i].tableref].vector[4] - block[i].vector[4]) * (table[block[i].tableref].vector[4] - block[i].vector[4]) +
       (table[block[i].tableref].vector[5] - block[i].vector[5]) * (table[block[i].tableref].vector[5] - block[i].vector[5]) +
       (table[block[i].tableref].vector[6] - block[i].vector[6]) * (table[block[i].tableref].vector[6] - block[i].vector[6]) +
       (table[block[i].tableref].vector[7] - block[i].vector[7]) * (table[block[i].tableref].vector[7] - block[i].vector[7]) +
       (table[block[i].tableref].vector[8] - block[i].vector[8]) * (table[block[i].tableref].vector[8] - block[i].vector[8]) +
       (table[block[i].tableref].vector[9] - block[i].vector[9]) * (table[block[i].tableref].vector[9] - block[i].vector[9]) +
       (table[block[i].tableref].vector[10] - block[i].vector[10]) * (table[block[i].tableref].vector[10] - block[i].vector[10]) +
       (table[block[i].tableref].vector[11] - block[i].vector[11]) * (table[block[i].tableref].vector[11] - block[i].vector[11]);
 
   block[i].distance = distance;
  }
 }
 
 
 //Création de l'image compressée
 
 cout << "Creation du fichier" << endl;
 
 ofstream file(szSavePath);
 file << Width << " ";
 file << Height << " ";
 file << nBlock << " ";
 file << NVECTORTABLE;
 
 for (short i = 0; i < NVECTORTABLE; i++)
 {
  file << " " << table[i].vector[0];
  file << " " << table[i].vector[1];
  file << " " << table[i].vector[2];
  file << " " << table[i].vector[3];
  file << " " << table[i].vector[4];
  file << " " << table[i].vector[5];
  file << " " << table[i].vector[6];
  file << " " << table[i].vector[7];
  file << " " << table[i].vector[8];
  file << " " << table[i].vector[9];
  file << " " << table[i].vector[10];
  file << " " << table[i].vector[11];
 }
 
 for (short i = 0; i < nBlock; i++)
  file << " " << block[i].tableref;
 
 file << endl;
 
 file.close();
 
 return 0;
}
 
int main()
{
 int last = GetTickCount();
 int current;
 int total;
 
 cout << "Debut" << endl;
 
 int x = CompressImage( "source.bmp",
       "sortie.txt",
       250, 300,
       4, 2);
 
 if (x)
  cout << "Erreur pendant la compression";
 
 current = GetTickCount();
 total = current - last;
 total = (total / 1000) / 60;
 
 cout << "Temps mis pour compresser l'image: " << total << " minutes" << endl;
 
 while(1)
 {
 }
 
 return 0;
}

Reply

Marsh Posté le 08-10-2001 à 22:15:34   

Reply

Marsh Posté le 09-10-2001 à 08:36:17    

salut
 
 
J'ai pas tout lu, mais y'a un truc qui me chiffone
 
   if (distance < block[i].distance)
   {
    for (short k = 0; k < table[block[i].tableref].nblock; k++)
    {
     if (table[block[i].tableref].blockref[k] == i)
     {
      ....
      break;
     }
    }
   }
  }
donc avec ton break, tu t'arrete lorsque tu trouve un distance qui est inferieur a block[i].distance
S'pas ?
ce qui est pas bon, puisque rien ne te dis que la premiere entree dans le codebook pour laquelle (distance < block[i].distance) soit la bonne ....
OK ce sera peut etre affinee lors d'une passe ulterieur, a mois que tu n'atteignes ta limite de nombre de passes avant....
 
Ensuite, je ne suis pas convaincu que ta methode soit tres bonne
tu initialise ton codebook avec des valeurs choisies au hasard parmis l'image . et ensuite ton codebook n'est plus updater qu'avec ton calcul de barycentre  
Mais que se passe t'il si jamais tu a choisi deux fois le meme endroit lors de ton tirage aleatoire (ou deux endroits different de position mais identique de couleur) ?
tu te retrouve avec une ou plusieurs entree du codebook (presque) inutile  
 
Aussi faudrait que tu voye pour ajouter des conditions d'arret, le VQ c plutot long alors si on peut faire au plus vite..
 
Je m etends pas trop j'ai deja fait tout une doc sur le sujet :
 
http://www.alrj.org/docs/algo/vqfr/
 
 
 
 
PS : heuh, les #define for if(1) for , t'es sur ? :)

 

[edtdd]--Message édité par chrisbk--[/edtdd]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed