Sfoglia il codice sorgente

correction de la lecture des données

Jackbot 4 anni fa
parent
commit
d1b5f8ae14
1 ha cambiato i file con 124 aggiunte e 55 eliminazioni
  1. 124 55
      bmp2gcode.cc

+ 124 - 55
bmp2gcode.cc

@@ -17,6 +17,7 @@ class BMP2Gcode
 		int sortie();
 
 		unsigned int conversion(unsigned int valeur, unsigned int min, unsigned int max);
+		unsigned int consecutif(unsigned int indice, unsigned int min, unsigned int max, unsigned int puissance, int sens);
 
 		unsigned int BMP_largeur, BMP_hauteur, BMP_offset, BMP_profondeur, BMP_taille;
 		double conf_taille_laser, conf_puissance_min, conf_puissance_max, conf_vitesse, conf_taille_image;
@@ -54,18 +55,18 @@ int BMP2Gcode::entete()
 	/*lecture de l'en tête de 54 octets composé comme suit :
 	-2 octets [0-1] pour la signature
 	-4 octets [2-5] pour la taille du fichier en octets
-	-4 octets [5-8] de champ réservé
-	-4 octets [9-12] pour l'offset
-	-4 octets [13-17] pour la taille de l'en-tête de l'image (28 octets pour windows)
+	-4 octets [6-9] de champ réservé
+	-4 octets [10-13] pour l'offset
+	-4 octets [14-17] pour la taille de l'en-tête de l'image (28 octets pour windows)
 	-4 octets [18-21] pour la largeur de l'image
 	-4 octets [22-25] pour la hauteur de l'image
 	-2 octets [26-27] pour le nombre de plans (valeur toujours à 1)
 	-2 octets [28-29] pour la profondeur de l'encodage (nbr de bit pour la couleur)
 	-4 octets [30-33] pour la métode de compression (0 non compressé, 1 RLE 8bits/pixel, 2 RLE 4bits/pixel, 3 bitfields)
-	-4 octets [34-37] pour la taille de l'image
-	-4 octets [38-41] pour la résolution horizontale
-	-4 octets [42-45] pour la résolution verticale
-	-4 octets [46-49] pour la palette de couleur
+	-4 octets [35-38] pour la taille de l'image
+	-4 octets [39-42] pour la résolution horizontale
+	-4 octets [43-46] pour la résolution verticale
+	-4 octets [47-50] pour la palette de couleur
 	-4 octets [50-53] pour le nombre de couleurs importantes.
 	*/
 
@@ -90,7 +91,6 @@ int BMP2Gcode::entete()
 	de prendre sa valeur en faisant : *(int *)entete[indice]
 	*/
 
-	//pourquoi un indice de 9 ne correspond pas ????
 	BMP_offset = *(int*)&entete[10];
 
 	BMP_largeur = *(int*)&entete[18];
@@ -125,19 +125,46 @@ int BMP2Gcode::donnees()
 	if(BMP_offset == 0)
 	{entete();}
 
-	int limite = BMP_largeur*BMP_hauteur * BMP_profondeur/8 + BMP_offset;
+	/* /!\ATTENTION/!\
+	Contrairement à la plupart des formats d'images, les pixels de l'image sont codés en partant de la ligne inférieure de l'image. Chaque ligne (codée de gauche à droite) doit toujours occuper un nombre d'octets multiple de 4, excepté si l'image est compressée. Si la ligne ne possède pas un nombre d'octets multiple de 4, on ajoute FF, 00FF, ou 0000FF à la fin de chaque ligne
+	
+	Source : https://fr.wikipedia.org/wiki/Windows_bitmap#Disposition_des_donn%C3%A9es_de_l'image
+	
+	Il est donc nécessaire pour lire correctement les données de prévoir une limite qui est un multiple de 4
+	mais également de sauter ces éventuels informations
+	*/
+	
+	int reste = BMP_largeur % 4, longueur_ligne = BMP_largeur;
+	
+	if(reste != 0)
+	{
+		//Si la longueur d'une ligne n'est un multiple de 4
+		//il suffit alors d'ajouter à la ligne 4 - reste
+		longueur_ligne += 4 - reste;
+	}
+	
+
+	int limite = longueur_ligne*BMP_hauteur * BMP_profondeur/8 + BMP_offset;
 
 	char *donnees = new char [ limite ];
 	fichier.read(donnees, limite);
 
-	for(int i = BMP_offset ; i < limite ; i += BMP_profondeur/8)
+	std::cout << "données brutes : " << std::endl;
+	
+	int depart = BMP_offset;
+	for(int i = 0 ; i < BMP_hauteur ; i++)
 	{
-		if(donnees[i] < 0)
-		{tab_donnees.push_back(256 + (int)donnees[i]);}
-		else
-		{tab_donnees.push_back((int)donnees[i]);}
-	}
+		//on récupère une ligne
+		for(int j = depart ; j < depart + BMP_largeur * BMP_profondeur/8; j += BMP_profondeur/8)
+		{
+			if(donnees[j] < 0)
+			{tab_donnees.push_back(256 + (int)donnees[j]);}
+			else
+			{tab_donnees.push_back((int)donnees[j]);}
+		}
 
+		depart += longueur_ligne * BMP_profondeur/8;
+	}
 	delete[] donnees;
 	fichier.close();
 
@@ -153,10 +180,9 @@ int BMP2Gcode::sortie()
 	fichier_sortie.open (nom_fichier_gcode);
 
 	/****************************CONDITIONS INITIALES****************************/
-	double taille_pixel = (double)(conf_taille_image)/(double)(BMP_largeur), position_Y = 0;
+	double taille_pixel = (double)(conf_taille_image)/(double)(BMP_largeur);
 
-	int sens = 1;
-	unsigned int indice = 0, ligne = 0;
+	int sens = 1, nbr_passage = 1, ligne = 0, colonne = 0;
 
 	//on arrondi la taille du pixel pour quelle corresponde à un multiple de la taille du laser
 	double rapport = ceil(taille_pixel/conf_taille_laser);
@@ -180,46 +206,66 @@ int BMP2Gcode::sortie()
 	while(ligne < BMP_hauteur)
 	{
 		//pour graver une ligne on fera des aller-retour tant que :
-		while(position_Y < ligne * taille_pixel)
+		do
 		{
-			//traitement d'une ligne
-			//indice = ligne * BMP_largeur + colonne;
-			do
-			{
-				unsigned int puissance = conversion(255 - tab_donnees[indice], conf_puissance_min, conf_puissance_max);
-
-				//on détermine le nombre de pixels successifs pour lesquels la puissance du laser sera la même
-				int nbr = 1;
-				while( puissance == conversion(255 - tab_donnees[indice + sens * nbr], conf_puissance_min, conf_puissance_max)
-					&& (indice + sens * nbr) % BMP_largeur != 0)
-				{nbr ++;}
-
-				fichier_sortie << "M106 P1 S" << puissance << std::endl;
-
-				//on se déplace selon le sens
-				fichier_sortie << "G1 X" << sens * taille_pixel * nbr << std::endl;
-
-				//et on se déplace dans le tableau selon le sens
-				indice += sens * nbr;
-			}
-			while(indice % BMP_largeur != 0);
-
-			//une fois que la ligne est finie, on décale d'une taille de laser sur l'axe Y
-			fichier_sortie << "G1 Y" << conf_taille_laser << std::endl;
-			position_Y += conf_taille_laser;
-
-			//on change de sens
-			sens *= -1;
+			fichier_sortie << ";colonne numéro : " << colonne << std::endl;
+			fichier_sortie << ";ligne numéro : " << ligne << std::endl;
+			fichier_sortie << ";sens : " << sens << std::endl;
+
+			int indice = ligne * BMP_largeur + colonne; 
+			
+			fichier_sortie << ";indice : " << indice << std::endl;
+			
+			unsigned int puissance = 0, indice_min = 0, indice_max = 0, nbr = 1;
+			puissance = conversion(255 - tab_donnees[indice], conf_puissance_min, conf_puissance_max);
+			indice_min = ligne * BMP_largeur;
+			indice_max = indice_min + BMP_largeur - 1;
+			
+
+			//on détermine le nombre de pixels successifs pour lesquels la puissance du laser sera la même
+			nbr = consecutif(indice, indice_min, indice_max, puissance, sens);
+
+			fichier_sortie << "M106 P1 S" << puissance << std::endl;
+
+			//on se déplace selon le sens
+			fichier_sortie << "G1 X" << sens * taille_pixel * nbr << std::endl;
+			colonne += sens * nbr;
 		}
-
-		//une fois qu'une ligne de pixel est gravée on incrémente le nombre de ligne
-		ligne ++;
-		indice += BMP_largeur;
-
-		fichier_sortie << ";ligne numéro " << ligne << std::endl;
+		while(colonne < BMP_largeur && colonne >= 0);
+		
+		/*arrivé ici on vient de tracer une ligne et le paramètre colonne est hors limite, il faut donc le rectifier.
+		Il est peut être également nécessaire de faire un retour cela va dépendre du rapport
+		entre la taille du pixel et la taille du laser*/
+		
+		if(colonne < 0)
+		{colonne = 0;}
+		if(colonne >= BMP_largeur)
+		{colonne = BMP_largeur - 1;}
+		
+		if(taille_pixel > conf_taille_laser * nbr_passage)
+		{
+			/*si on a pas fait un nombre de passage suffisent pour égaler la taille du pixel
+			alors on repart dans l'autre sens en prennant soin de décaler la colonne
+			et on recommence*/
+			nbr_passage ++;
+			fichier_sortie << ";passage numéro : " << nbr_passage << std::endl;
+			fichier_sortie << ";colonne numéro : " << colonne << std::endl;
+		}
+		else
+		{
+			/*si le nombre de passage permet d'égaler la taille du pixel
+			alors on change de ligne et on recommence*/
+			ligne ++;
+			nbr_passage = 1;
+			fichier_sortie << ";changement de ligne : " << ligne << std::endl;
+			fichier_sortie << ";colonne numéro : " << colonne << std::endl;
+		}
+		
+		/*Dans les 2 cas il est nécessaire de se déplacer sur l'axe Y
+		et de changer de sens*/
+		fichier_sortie << "G1 Y" << conf_taille_laser << std::endl;
+		sens *= -1;
 	}
-	
-	std::cout << "indice = " << indice << std::endl;
 
 	//il ne faut pas oublier d'éteindre le laser à la fini
 	fichier_sortie << "M106 P1 S0" << std::endl;
@@ -243,6 +289,29 @@ unsigned int BMP2Gcode::conversion(unsigned int valeur, unsigned int min, unsign
 	return valeur * (max - min)/255 + min;
 }
 
+unsigned int BMP2Gcode::consecutif(unsigned int indice, unsigned int min, unsigned int max, unsigned int puissance, int sens)
+{
+	/*Cette fonction va déterminer le nombre de pixel consécutif
+	avec la même couleur que le premier pixel, dans un interval donné
+	
+	du fait de la calibration il se peut que des teintes de gris proches
+	soient associées à la même puissance laser,
+	il est donc nécessaire de comparer les puissance et non les données des pixel*/
+	
+	unsigned int nbr = 0;
+	
+	while(indice >= min && indice <= max)
+	{
+		if(puissance == conversion(255 - tab_donnees[indice], conf_puissance_min, conf_puissance_max))
+		{nbr ++;}
+		else
+		{return nbr;}
+		
+		indice += sens;
+	}
+	return nbr;
+}
+
 void BMP2Gcode::fichier_conf()
 {
 	//On regarde si le fichier de configuration existe déjà