beankylla Posté(e) le 4 octobre 2014 Partager Posté(e) le 4 octobre 2014 Du C, Bête et méchant... Bonjour à tous! Je me suis lancé il y a quelques moi, et pour combler une de mes lacunes (je n'avais jamais fait de programmation ça manquait ne serait-ce qu'à ma geekulture) dans un MOOC d'informatique. (et puis j'ai toujours revé d'avoir un diplôme d'Harvard ^^'. Je ne vous la fait pas longue, la pour la première fois je suis aux prises avec un problème dont je ne trouve pas la solution. Le code suivant devrait pouvoir dupliquer et agrandir une image BMP. La commande est ./resize A petit.bmp grand.bmp ou A joue le role de multiplicateur. Si A=1 ça ne fait que copier l'image, et sinon chaque pixel est remplacé par un carré de pixels dont la taille est (pixel*A) Si vous pouviez m'aider sans me donner directement la solution (c'est pédagogique blababla) ca serait top! Merci d'avance! #include <stdio.h> #include <stdlib.h> #include "bmp.h" int main(int argc, char* argv[]) { // ensure proper usage if (argc != 4) { printf("Usage: ./resize multiplicator infile outfile\n"); return 1; } // remember filenames and set multiplier char* infile = argv[2]; char* outfile = argv[3]; int multi = atoi(argv[1]); // open input file FILE* inptr = fopen(infile, "r"); if (inptr == NULL) { printf("Could not open %s.\n", infile); return 2; } // open output file FILE* outptr = fopen(outfile, "w"); if (outptr == NULL) { fclose(inptr); fprintf(stderr, "Could not create %s.\n", outfile); return 3; } // read infile's BITMAPFILEHEADER BITMAPFILEHEADER bf; fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr); // read infile's BITMAPINFOHEADER BITMAPINFOHEADER bi; fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr); // ensure infile is (likely) a 24-bit uncompressed BMP 4.0 if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || bi.biBitCount != 24 || bi.biCompression != 0) { fclose(outptr); fclose(inptr); fprintf(stderr, "Unsupported file format.\n"); return 4; } //plein de variables int largeur, hauteur, newlargeur, newhauteur, pad, newpad, tailleimage, taillefichier, repere; //calculs des nouveaux elements: hauteur, largeur et padding largeur = abs(bi.biWidth); hauteur = abs(bi.biHeight); pad = (4 - (largeur*sizeof(RGBTRIPLE))%4)%4; newlargeur = largeur * multi; newhauteur = hauteur * multi; newpad = (4 - (newlargeur*sizeof(RGBTRIPLE))%4)%4; bi.biWidth = newlargeur; bi.biHeight = newhauteur; //taille de la nouvelle image + du fichier tailleimage = abs(newhauteur) * (newlargeur * sizeof(RGBTRIPLE) + newpad); taillefichier = tailleimage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //on remet les valeurs à leur place bf.bfSize = taillefichier; bi.biSizeImage = tailleimage; //on pose l'unité de stockage de la ligne RGBTRIPLE scancolor[newlargeur]; // write outfile's BITMAPFILEHEADER fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr); // write outfile's BITMAPINFOHEADER fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr); printf("\nlargeur:%d\nhauteur:%d\n\nnewlargeur:%d\nnewhauteur:%d\n\npad:%d\nnewpad:%d\n\ntailleimage:%d\ntaillefichier:%d\n\nbfSize:%d\nbiSizeimage:%d\n\n",largeur, hauteur,newlargeur, newhauteur,pad, newpad, tailleimage, taillefichier,bf.bfSize,bi.biSizeImage); // iterate over infile's scanlines for (int i = 0, r = hauteur; i < r; i++) { repere = 0; // iterate over pixels in scanline for (int j = 0, v = largeur; j < v; j++) { // temporary storage RGBTRIPLE tempcolor; // read RGB triple from infile (entire line) fread(&tempcolor, sizeof(RGBTRIPLE), 1, inptr); for (int l = 0; l < multi; l++) { scancolor[repere].rgbtBlue = tempcolor.rgbtBlue; scancolor[repere].rgbtGreen = tempcolor.rgbtGreen; scancolor[repere].rgbtRed = tempcolor.rgbtRed; repere++; } } //on itère la réécriture de la ligne for (int m = 0; m < multi; m++) { for (repere = 0; repere < multi; repere++) { fwrite(&scancolor[repere], sizeof (RGBTRIPLE), 1, outptr); } for (int u = 0; u < newpad; u++) { fputc(0x00, outptr); } } // skip over padding, if any fseek(inptr, pad, SEEK_CUR); } // close infile fclose(inptr); // close outfile fclose(outptr); // that's all folks return 0; Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 4 octobre 2014 Partager Posté(e) le 4 octobre 2014 Tu l'as eu où ton source "bmp.h" Et c'est quoi ton erreur: cela te génère une image avec Évelyne Dhéliat nue un carré de pixels dont la taille est (pixel*A) De côté A, mais de taille (A*A) Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 4 octobre 2014 Auteur Partager Posté(e) le 4 octobre 2014 l'image de base est celle la (3x3 pixels du vert autour un blanc au milieu): http://meinu.fr/small.bmp en la multipliant par 3 je devrait tomber sur ca (9X9 avec un carré de 3x3 pixels blancs au milieu http://meinu.fr/large.bmp Mais sur le principe ca doit marcher avec n'importe quelle image. Mon soucis est que j'obtiens ca: http://meinu.fr/resize.bmp La taille de l'image est bonne (ca c'est la partie facile) mais j'ai un soucis avec le contenu... Désolé je n'ai pas pu mettre les images en photo apparemment les BMP sont interdits ! Merci de ton interet! Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 5 octobre 2014 Partager Posté(e) le 5 octobre 2014 Il faut savoir un truc: le format bmp est un format totalement merdik :devil: Regarde Wiki, mais les trucs qu'il faut tenir compte: Les lignes sont des multiples de 4 L'image est sauvegardée "upside-down" à l'envers de haut en bas, mais de gauche à droite Il y a éventuellement une palette Tout cela pour te dire que ton algo est voué à l'échec Message hors-propos, parce que codé avec GDI+, en C++ avec la classe Bitmap (ou Image) Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 5 octobre 2014 Auteur Partager Posté(e) le 5 octobre 2014 Je ne pense pas que mon code soit voué à l’échec parce que la base du code (qui fonctionne, elle) a pour fonction de copier bit par bit le fichier. En outre il faut que je reste en C c'est imposé par l’exercice. Mais merci pour ton input Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 5 octobre 2014 Partager Posté(e) le 5 octobre 2014 Ne fonctionne pas avec tous les bmp Il faut ouvrir les fichiers en binaire // XXX CHANGE - include: Need structs RGBTRIPLE, BITMAPFILEHEADER & BITMAPINFOHEADER #include<Windows.h> #include<stdlib.h> #include<stdio.h> int main(int argc, char* argv[]) { // Ensure proper usage if ((argc != 4) && (argc != 5)) { printf("Usage: %s multiplicator infile outfile [version: 1 or 2]\n", argv[0]); return 1; } unsigned short multiplier = atoi( argv[1] ); if (multiplier == 0) { fprintf(stderr, "%s - Error: multiplier must be at least equal to 1\n", argv[0]); return 2; } // Open input file FILE* image = fopen(argv[2], "rb"); if (image == NULL) { fprintf(stderr, "%s - Error: Could not open %s\n", argv[0], argv[2]); return 3; } // Open output file FILE* new_image = fopen(argv[3], "wb"); if (new_image == NULL) { fclose(image); fprintf(stderr, "%s - Error: Could not create %s\n", argv[0], argv[3]); return 4; } // Read infile's BITMAPFILEHEADER & BITMAPINFOHEADER BITMAPFILEHEADER bf; BITMAPINFOHEADER bi; printf("image start: %d\n", fseek(image, 0, SEEK_SET)); // Useless??? fread(&bf, sizeof(BITMAPFILEHEADER), 1, image); fread(&bi, sizeof(BITMAPINFOHEADER), 1, image); // Ensure infile is (likely) a 24-bit uncompressed BMP 4.0 if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 || bi.biBitCount != 24 || bi.biCompression != 0) { fclose(new_image); fclose(image); fprintf(stderr, "%s - Error: Unsupported file format.\n", argv[0]); return 5; } unsigned long width = abs(bi.biWidth), height = abs(bi.biHeight); // Avoid casting unsigned char version = 1, size_RGB = sizeof(RGBTRIPLE); if (argc == 5) { version = atoi( argv[4] ); if ((version != 1) && (version != 2)) { version = 1; } } if ((width == 0) || (height == 0)) { fclose(new_image); fclose(image); fprintf(stderr, "%s - Error: size 0\n", argv[0]); return 6; } // Skip over headers printf("image start1: %d\n", fseek(image, bf.bfOffBits, SEEK_SET)); // Useless??? bi.biWidth *= multiplier; bi.biHeight *= multiplier; unsigned char padding = ((4 - (width * size_RGB) % 4) % 4), new_padding = ((4 - (bi.biWidth * size_RGB) % 4) % 4); // unsigned char padding = 0, new_padding = 0; // while(((width * size_RGB + padding) % 4) != 0) { padding++; } // while(((bi.biWidth * size_RGB + new_padding) % 4) != 0) { new_padding++; } printf("%ux%u (Pad: %u, Offset: %lu) -- *%u --> %ux%u (Pad: %u) (Ver: %d)\n", width, height, padding, bf.bfOffBits, multiplier, bi.biWidth, bi.biHeight, new_padding, version); bi.biSizeImage = (bi.biHeight * (bi.biWidth * size_RGB + new_padding)); bf.bfOffBits = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); bf.bfSize = (bi.biSizeImage + bf.bfOffBits); // Maybe should clean other attributes // Write outfile's BITMAPFILEHEADER & BITMAPINFOHEADER printf("new_image start: %d\n", fseek(new_image, 0, SEEK_SET)); // Useless??? fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, new_image); fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, new_image); RGBTRIPLE* one_row = NULL; if (version == 1) { // Version 1: Write the output bitmap line (with the padding) by line (with the padding) unsigned int output_w_size = (bi.biWidth * size_RGB + new_padding); // Avoid casting unsigned short pos_w = 0, pos_h = 0, tmp = 0; one_row = (RGBTRIPLE*) malloc(output_w_size); memset(one_row, 0, output_w_size); for(; pos_h < height; ++pos_h) { for(pos_w = 0; pos_w < (width * multiplier); pos_w += multiplier) { fread((one_row + pos_w), size_RGB, 1, image); for(tmp = 1; tmp < multiplier; ++tmp) { one_row[pos_w + tmp] = one_row[pos_w]; } // printf("%u %u: (%u, %u, %u)\n", (height - pos_h), (pos_w + 1), one_row[pos_w].rgbtRed, one_row[pos_w].rgbtGreen, one_row[pos_w].rgbtBlue); } for(tmp = 0; tmp < multiplier; ++tmp) { fwrite(one_row, sizeof(char), output_w_size, new_image); } // Skip over padding, if any fseek(image, padding, SEEK_CUR); } } else if (version == 2) { // Version 2: Write the output bitmap color by color unsigned short pos_w = 0, pos_h = 0, mul_h = 0; unsigned int tmp = 0; // /!\: Use to write the padding one_row = (RGBTRIPLE*) malloc(width * size_RGB); memset(one_row, 0, (width * size_RGB)); for(; pos_h < height; ++pos_h) { for(pos_w = 0; pos_w < width; ++pos_w) { fread((one_row + pos_w), size_RGB, 1, image); // printf("%u %u: (%u, %u, %u)\n", (height - pos_h), (pos_w + 1), one_row[pos_w].rgbtRed, one_row[pos_w].rgbtGreen, one_row[pos_w].rgbtBlue); } for(mul_h = 0; mul_h < multiplier; ++mul_h) { for(pos_w = 0; pos_w < width; ++pos_w) { for(tmp = multiplier; tmp > 0; --tmp) { fwrite((one_row + pos_w), size_RGB, 1, new_image); } } // Write padding, if any. tmp is equal to 0 here in order to use it // to write the padding. The padding is not more than 3 bytes fwrite(&tmp, sizeof(char), new_padding, new_image); } // Skip over padding, if any fseek(image, padding, SEEK_CUR); } } if (one_row != NULL) { free(one_row); } // Close infile & outfile fclose(image); fclose(new_image); return EXIT_SUCCESS; } Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 5 octobre 2014 Partager Posté(e) le 5 octobre 2014 Édition de mon code Édition de mon code (2 jours plus tard ) pour proposer 2 approches (suite à mes messages ci-dessous) et un paramètre/ une bascule "version" qui permet de choisir: version == 1 -> On va écrire l'image résultat ligne par ligne en incluant le padding version == 2 -> On va écrire l'image résultat couleur par couleur Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 6 octobre 2014 Auteur Partager Posté(e) le 6 octobre 2014 Merci beaucoup pour ton aide foetus, Le soucis c'est que je dois faire un programme en C et que je n'arrive pas ce qui m'aiderait c'est de savoir ce qui ne marche pas dans mon code. Quelqu'un voit le soucis? '-_- Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 6 octobre 2014 Partager Posté(e) le 6 octobre 2014 Le soucis c'est que je dois faire un programme en C et que je n'arrive pas ce qui m'aiderait c'est de savoir ce qui ne marche pas dans mon code. Jusqu'à preuve du contraire mon code est en C99 comme le tien D'ailleurs ce bout code n'est pas valide "RGBTRIPLE scancolor[newlargeur];" Pourquoi tu dis qu'il est en C++? Je peux le faire en pure C, mais cela ne va servir à rien Quelqu'un voit le soucis? '-_- Tu as un double problème de logique avec cette boucle "for (repere = 0; repere < multi; repere++)" Cela t'apprendras à avoir une bonne indentation, à ne pas avoir de variables qui se trimballent n'importe où (pourquoi la variable repere (initialisation/ ++/ ...) n'est pas dans les boucles), à déclarer des variables temporaires au milieu de tes boucles ... et avoir trop de variables redondantes (les variables r et v) Sans parler de 2-3 détails (peut-être inutiles) corrigés dans mon code qui lui fonctionne (et quasi identique au tien, mais avec moins de variables, moins de mémoire utilisée, moins de recopie, 1-2 tests défensifs en plus ...) Édit: Le problème du code original, c'est qu'il écrit les multi premières couleurs enregistrées dans le tableau scancolor, au lieu d'écrire la ligne en entier (c'est à dire multi * width couleurs) Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 6 octobre 2014 Auteur Partager Posté(e) le 6 octobre 2014 Bonjour Foetus! Merci pour ton soutien! En fait l'inclusion de window.h m'a fait penser que c'était pas du C mais ptet du C + quelque chose . Le developpement étant fait sous fedorah l'inclusion de windows.h n'est pas tellement envisageable Sinon, je ne vois pas la soucis de logique avec la boucle: dans la partie précédent cette boucle j'ai attribué à scancolor[repere] les couleurs qui sont sur l'image d'origine, et avec cette boucle je Je suis trop bête le soucis était effectivement là maintenant ca marche!!! Merci t'es un génie! :) Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 6 octobre 2014 Partager Posté(e) le 6 octobre 2014 Le windows.h c'est pour avoir accès aux structures RGBTRIPLE, BITMAPFILEHEADER et BITMAPINFOHEADER. J'ai mis un commentaire Parce que tu n'avais pas répondu à ma première question "Tu l'as eu où ton source "bmp.h"" Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 6 octobre 2014 Auteur Partager Posté(e) le 6 octobre 2014 Salut! Désolé j'ai les yeux carrés à force de regarder le code ^^... alors le bmp.h vient dans la machine virtuelle pré-préparée avec laquelle il faut faire les exercixes donc je ne sais pas trop d'ou il vient ! Merci en tout cas c'est super :) je bute toujours sur des détails débiles comme ca! et sans conteste ton code est beauuuucoup plus joli que le mien. Mais je dois rendre mon code et pas celui de quelqu'un d'autre honneteté académique tout ca :).. Merci en tout cas et forcément a bientot pour de nouvelles aventures.... en C! Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 7 octobre 2014 Partager Posté(e) le 7 octobre 2014 Je reviens pour te faire remarquer que, dans ton code, tu peux totalement supprimer la boucle fautive et laisser le travail à fwrite (*) // for (repere = 0; repere < newlargeur; repere++) // { // fwrite(&scancolor[repere], sizeof(RGBTRIPLE), 1, outptr); // } fwrite(scancolor, sizeof(RGBTRIPLE), newlargeur, outptr); Et 2-3 détails que j'ai mis dans mon code C (le 2ième code) qui me semble bon de prendre en compte, même si tu veux "plus il est dirty plus c'est le mien " Ouvre tes fichiers en binaire. C'est le b dans le mode d'accès de fopen "rb", "wb". Cela évite que tes données soient modifiées. Teste si ton fichier en entrée à soit une largeur égale à 0 soit une hauteur égale à 0 (soit les 2). Cela évite de générer une image résultat vide, ce qui peut être confusant: est-ce une erreur? est-ce un résultat normal? Et pour plus tard. scancolor est un tableau. Donc scancolor est un pointeur sur l'adresse de la première case. Parce que &(scancolor[m]), au lieu de (scancolor + m), c'est moche Et en plus tu pourras t'amuser avec l'arithmétique des pointeurs Édit: (*) -> C'est intéressant parce que si fwrite écrit une ligne en entier (sans faire de boucle, quoique pour l'écriture d'un fichier il me semble que les fonctions ne peuvent pas écrire plus d'1 bloc de X (512? 1024?) octects à la fois) c'est une bonne optimisation CPU, parce que tu ne feras que newHauteur appels à fwrite. Par contre niveau mémoire cela se discute Parce que si multi est assez grand ainsi que la largeur de ton image en entrée, scancolor va être assez volumineux. Lien vers le commentaire Partager sur d’autres sites More sharing options...
beankylla Posté(e) le 7 octobre 2014 Auteur Partager Posté(e) le 7 octobre 2014 J'avoue que je suis un peu largué! mais petite note comme ca: si tu mets juste fwrite va-t-il bien écrire le fichier bit par bit comme on l'avait fait avant? (je ne suis pas le plus au point sur les pointeurs, etc, j'avoue ... ^ ^ pour être franc j'ai un code qui marche et je ne compte plus y toucher. Par contre j'ai encore d'autre exercixes et maintenant que j'ai trouvé le maitre du C je vais venir ici directement au lieu de galérer dans mon coin! (du coup je continuerais ce thread je ne le cloture pas :)) Merci beaucoup Foetus! Lien vers le commentaire Partager sur d’autres sites More sharing options...
foetus Posté(e) le 7 octobre 2014 Partager Posté(e) le 7 octobre 2014 J'avoue que je suis un peu largué! C'est juste une remarque pense-y à tête réposée. J'ai édité mon code, avec un nouveau paramètre optionnel ou si tu mets juste fwrite va-t-il bien écrire le fichier bit par bit comme on l'avait fait avant? (je ne suis pas le plus au point sur les pointeurs, etc, j'avoue ... ^ ^ Non regarde la documentation de fwrite: le troisième paramètre c'est le nombre d'éléments que tu veux écrire Donc au lieu de faire une boucle et d'écrire couleurs par couleurs, tu peux dire à fwrite d'écrire newLargeur couleurs. Parce que dans ton code, tu calcules une ligne de ton image de sortie. Et tu peux même aller plus loin, et rajouter le padding à la fin de scancolor, pour dire à fwrite d'écrire (newLargeur couleurs + newPad). Ansi supprimer également la boucle qui ecrit les zéros à la fin de chaque ligne de ton image de sortie. Après que va faire fwrite si on lui demande d'écrire X éléments? Je pense que cela va dépendre de la taille du buffer d'écriture en mémoire (comme je l'ai dit avant à la fin de mon message), mais on ne s'attend pas qu'il écrive élément par élément Lien vers le commentaire Partager sur d’autres sites More sharing options...
Messages recommandés
Archivé
Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.