Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // tp2.cpp
- // Exemple de convolution d'image avec lodepng
- //
- // Créé par Julien-Charles Lévesque
- // Copyright 2015 Université Laval. Tous droits réservés.
- //
- #include "lodepng.h"
- #include <iostream>
- #include <stdlib.h>
- #include <fstream>
- #include <thread>
- #include <omp.h>
- #include <cstring>
- #include <cmath>
- #include "Chrono.hpp"
- #include "PACC/Tokenizer.hpp"
- using namespace std;
- //Aide pour le programme
- void usage(char* inName) {
- cout << endl << "Utilisation> " << inName << " fichier_image fichier_noyau [fichier_sortie=output.png]" << endl;
- exit(1);
- }
- //Décoder à partir du disque dans un vecteur de pixels bruts en un seul appel de fonction
- void decode(const char* inFilename, vector<unsigned char>& outImage, unsigned int& outWidth, unsigned int& outHeight)
- {
- //Décoder
- unsigned int lError = lodepng::decode(outImage, outWidth, outHeight, inFilename);
- //Montrer l'erreur s'il y en a une.
- if(lError)
- cout << "Erreur de décodage " << lError << ": " << lodepng_error_text(lError) << endl;
- //Les pixels sont maintenant dans le vecteur outImage, 4 octets par pixel, organisés RGBARGBA...
- }
- //Encoder à partir de pixels bruts sur le disque en un seul appel de fonction
- //L'argument inImage contient inWidth * inHeight pixels RGBA ou inWidth * inHeight * 4 octets
- void encode(const char* inFilename, vector<unsigned char>& inImage, unsigned int inWidth, unsigned int inHeight)
- {
- //Encoder l'image
- unsigned lError = lodepng::encode(inFilename, inImage, inWidth, inHeight);
- //Montrer l'erreur s'il y en a une.
- if(lError)
- cout << "Erreur d'encodage " << lError << ": "<< lodepng_error_text(lError) << endl;
- }
- int main(int inArgc, char *inArgv[])
- {
- if(inArgc < 3 or inArgc > 4) usage(inArgv[0]);
- string lFilename = inArgv[1];
- string lOutFilename;
- if (inArgc == 4)
- lOutFilename = inArgv[3];
- else
- lOutFilename = "output.png";
- // Lire le noyau.
- ifstream lConfig;
- lConfig.open(inArgv[2]);
- if (!lConfig.is_open()) {
- cerr << "Le fichier noyau fourni (" << inArgv[2] << ") est invalide." << endl;
- exit(1);
- }
- PACC::Tokenizer lTok(lConfig);
- lTok.setDelimiters(" \n","");
- string lToken;
- lTok.getNextToken(lToken);
- int lK = atoi(lToken.c_str());
- int lHalfK = lK/2;
- cout << "Taille du noyau: " << lK << endl;
- //Lecture du filtre
- double* lFilter = new double[lK*lK];
- for (int i = 0; i < lK; i++) {
- for (int j = 0; j < lK; j++) {
- lTok.getNextToken(lToken);
- lFilter[i*lK+j] = atof(lToken.c_str());
- }
- }
- //Lecture de l'image
- //Variables à remplir
- unsigned int lWidth, lHeight;
- vector<unsigned char> lImage; //Les pixels bruts
- //Appeler lodepng
- decode(lFilename.c_str(), lImage, lWidth, lHeight);
- // Démarrer le chronomètre
- Chrono lChrono(true);
- //Variables contenant des indices
- //Variables temporaires pour les canaux de l'image
- vector<unsigned char> oImage(lImage);
- int numberOfProcessor = std::thread::hardware_concurrency();
- if (numberOfProcessor == 0){
- printf("No processor detected!");
- numberOfProcessor = 2;
- }
- int workingSize = lHeight - lK + 1;
- #pragma omp parallel for
- for (int iteration = 0; iteration < numberOfProcessor; ++iteration)
- {
- const size_t startIndex = lHalfK*4 + (iteration * ceil(workingSize / numberOfProcessor) + lHalfK) * lWidth * 4;
- vector<unsigned char> oCopyImage(lImage.cbegin() + startIndex,
- lImage.cbegin() + ((iteration + 1) * ceil(workingSize / numberOfProcessor) + lHalfK) * lWidth * 4);
- for(int y = iteration * ceil(workingSize / numberOfProcessor) + lHalfK; y < (iteration + 1) * ceil(workingSize / numberOfProcessor) + lHalfK && y < workingSize + lHalfK; y++)
- {
- for (int x = lHalfK; x < (int)lWidth - lHalfK; x++)
- {
- double lR, lG, lB;
- lR = 0.;
- lG = 0.;
- lB = 0.;
- for (int j = -lHalfK; j <= lHalfK; j++) {
- int fy, fx;
- fy = j + lHalfK;
- for (int i = -lHalfK; i <= lHalfK; i++) {
- fx = i + lHalfK;
- lR += double(lImage[(y + j)*lWidth*4 + (x + i)*4]) * lFilter[fx + fy*lK];
- lG += double(lImage[(y + j)*lWidth*4 + (x + i)*4 + 1]) * lFilter[fx + fy*lK];
- lB += double(lImage[(y + j)*lWidth*4 + (x + i)*4 + 2]) * lFilter[fx + fy*lK];
- }
- }
- //Placer le résultat dans l'image.
- oCopyImage[y*lWidth*4 + x*4 - startIndex] = (unsigned char)lR;
- oCopyImage[y*lWidth*4 + x*4 + 1 - startIndex] = (unsigned char)lG;
- oCopyImage[y*lWidth*4 + x*4 + 2 - startIndex] = (unsigned char)lB;
- }
- }
- #pragma omp critical // Whatch out, all unnamed critical sections have the same lock
- memcpy(&oImage[startIndex], &oCopyImage[0], oCopyImage.size() * sizeof(unsigned char));
- }
- // Arrêter le chronomètre
- lChrono.pause();
- // Afficher le temps d'exécution dans le stderr
- fprintf(stderr, "Temps d'execution = %f sec\n", lChrono.get());
- //Sauvegarde de l'image dans un fichier sortie
- encode(lOutFilename.c_str(), oImage, lWidth, lHeight);
- cout << "L'image a été filtrée et enregistrée dans " << lOutFilename << " avec succès!" << endl;
- delete lFilter;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement