Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #define palette_size 1024
- #define header_size 54
- using namespace std;
- enum CODE
- {
- WORD,
- DWORD
- };
- int32_t pow(int32_t x)
- {
- return x*x;
- }
- void BMP_code(uint8_t * source, uint8_t * dest, CODE type) /// Odczytuje kod w odwrotnej kolejnosci bajtow dla 2 bajtow i 4 bajtow
- {
- if(type == WORD)
- {
- dest[0] = source[0];
- dest[1] = source[1];
- }
- else if(type == DWORD)
- {
- dest[0] = source[0];
- dest[1] = source[1];
- dest[2] = source[2];
- dest[3] = source[3];
- }
- }
- /// Moj wlasny algorytm na indeksowanie kolorow
- /// Polega on na obliczeniu roznicy szukanego koloru z kolorem palety i podniesieniu go do kwadratu
- /// Po obliczeniu 3 kolorow jest ono sumowane
- /// Dzieki temu preferowane jest wyszukiwanie blizszego koloru w odpowiedniku 8 bitowym
- /// Np. mamy 2 podobne kolory 1.(125,125,125) i 2.(120,120,120) w palecie
- /// i kolor (123,117,130), wyliczamy roznice dla obydwu wariantow
- /// 1: (125-123)^2+(125-117)^2+(130-125)^2=4+64+25=93
- /// 2: (123-120)^2+(120-117)^2+(130-120)^2=9+9+100=118
- /// To są wariancje teraz liczymy zwykla sume roznic
- /// 1: (125-123)+(125-117)+(130-125)=2+8+5=15
- /// 2: (123-120)+(120-117)+(130-120)=16
- /// Roznica sumy roznica jest duzo mniejsza od wariancji
- /// Wyliczenie na podstawie wariancji gwarantuje nam dobranie bardziej odpowiedniego koloru
- /// Tym samym ten algorytm jest ok
- int32_t GetColorIndex(int32_t r, int32_t g, int32_t b, uint8_t * palette)
- {
- int32_t temprange;
- int32_t range = pow(r-int32_t(palette[0]))+pow(g-int32_t(palette[1]))+pow(b-int32_t(palette[2]));
- int32_t index = 0;
- for(int32_t a = 4; a<palette_size; a++)
- {
- temprange = pow(r-int32_t(palette[a]))+pow(g-int32_t(palette[a+1]))+pow(b-int32_t(palette[a+2]));
- if(temprange < range)
- {
- range = temprange;
- index = a/4;
- }
- }
- return index;
- }
- int main()
- {
- /// Nazwa pliku
- string filename;
- /// Zmienne zawierajace cechy bitmapy
- uint8_t header[header_size]; /// Naglowek bitmapy
- uint8_t palette[palette_size]; /// Paleta kolorow dla bitmapy 8 bitowej
- uint8_t * sourcedata; /// Piksele
- uint8_t * destdata;
- uint32_t sourcefilesize;
- uint32_t sourcepadding; /// Wartosc potrzebna do zaokraglenia do wielokrotnosci 4
- uint32_t sourcedatasize;
- uint32_t width, height;
- uint32_t destdatasize;
- uint32_t destdatapadding;
- /// Klasy potrzebne do odczytu lub zapisu pliku
- ifstream szablon_palety; /// Wczytuje domyslna palete kolorow
- ifstream BMP24; /// Źródło
- ofstream BMP8; /// Wynik
- /// Program
- cout << "Nazwa pliku wraz z formatem:"; cin >> filename; cout << endl;
- cout << "Nastepuje otwieranie." << endl << endl;
- BMP24.open(filename.c_str(), ifstream::in | ifstream::binary);
- if(!BMP24.is_open()) /// Zabezpieczenie przed otwarciem nieistniejącego pliku
- {
- cout << "Blad. Pliku zrodlowego nie udalo sie otworzyc." << endl;
- system("pause");
- exit(0);
- }
- cout << "Plik zrodlowy jest otwarty." << endl << endl;
- cout << "Nastepuje odczytywanie naglowka." << endl << endl;
- BMP24.read((char*)header, header_size); /// Odczytanie nagłówka
- if(header[0] != 'B' || header[1] != 'M') /// Potwierdza autentycznosc bitmapy
- {
- cout << "Blad. Plik zrodlowy nie jest bitmapa." << endl;
- system("pause");
- exit(0);
- }
- if(header[28] != 24)
- {
- cout << "Blad. Bitmapa nie ma formatu 24 bitowego." << endl;
- system("pause");
- exit(0);
- }
- cout << "Dane naglowka zostaly pobrane." << endl << endl;
- cout << "Nastepuje pobieranie cech bitmapy." << endl << endl; /// Pobiera cechy bitmapy
- BMP_code(header+34, (uint8_t*)&sourcefilesize, DWORD);
- BMP_code(header+18, (uint8_t*)&width, DWORD);
- BMP_code(header+22, (uint8_t*)&height, DWORD);
- sourcedatasize = width*height*3;
- sourcepadding = (sourcefilesize-sourcedatasize)/height;
- cout << "Nastepuje pobieranie pikseli bitmapy." << endl << endl;
- sourcedata = new uint8_t[sourcedatasize];
- for(uint32_t a = 0; a<height; a++) /// Wczytuje piksele pomijajac jednoczesnie wypelnienie do wielokrotnosci 4
- {
- BMP24.read((char*)(sourcedata+a*width*3), width*3);
- BMP24.seekg(sourcepadding, BMP24.cur);
- }
- BMP24.close();
- cout << "Dane pikselow bitmapy zostaly pobrane." << endl << endl;
- destdatasize = sourcedatasize/3;
- destdata = new uint8_t[destdatasize];
- cout << "Nastepuje pobranie danych palety kolorow." << endl << endl;
- szablon_palety.open("template.plt", ifstream::in | ifstream::binary); /// Gotowa paleta jest otwierana z pliku
- if(!szablon_palety.is_open())
- {
- cout << "Blad. Brak pliku zawierającego domyslna palete." << endl;
- delete [] sourcedata;
- system("pause");
- exit(0);
- }
- cout << "Paleta kolorow zostala wczytana." << endl << endl;
- szablon_palety.read((char*)palette, palette_size);
- szablon_palety.close();
- cout << "Uwaga. Nastepuje konwersja pikseli z 24 bitow do 8 bitow." << endl << endl;
- for(uint32_t a = 0; a<destdatasize; a++) destdata[a] = uint8_t(GetColorIndex(sourcedata[a*3],sourcedata[a*3+1],sourcedata[a*3+2], palette)); /// Klucz programu, konwersja
- cout << "Piksele bitmapy 24 bitowej zostaly przekonwertowane na format 8 bitowy." << endl << endl;
- destdatapadding = 4-(width%4);
- if(destdatapadding == 4) destdatapadding = 0; /// Oblicza wypelnienie dla 8 bitow
- uint32_t dword;
- uint16_t word;
- /// Uzupelnianie naglowka
- cout << "Ustawianie naglowka dla formatu 8 bitowego." << endl << endl;
- dword = (width+destdatapadding)*height+54+1024;
- BMP_code((uint8_t*)&dword, header+2, DWORD);
- dword = 1024+54;
- BMP_code((uint8_t*)&dword, header+10, DWORD);
- word = 8;
- BMP_code((uint8_t*)&word, header+28, WORD);
- dword = (width+destdatapadding)*height;
- BMP_code((uint8_t*)&dword, header+34, DWORD);
- cout << "Tworzenie pliku koncowego pod nazwa outcome.bmp" << endl << endl;
- BMP8.open("outcome.bmp", ofstream::out | ofstream::binary);
- if(!BMP8.is_open())
- {
- cout << "Blad. Nie udalo sie utworzyc pliku koncowego." << endl;
- delete [] sourcedata;
- delete [] destdata;
- system("pause");
- exit(0);
- }
- cout << "Tworzenie powiodlo sie. Nastepuje zapisywanie danych." << endl << endl;
- BMP8.write((char*)header, header_size);
- BMP8.write((char*)palette, palette_size);
- for(uint32_t a = 0; a<height; a++) /// Wypelnia piksele
- {
- BMP8.write((char*)(destdata+a*width), width); /// Piksele
- for(uint32_t b = 0; b<destdatapadding; b++) BMP8 << '\0'; /// Wypelnienie
- }
- BMP8.close();
- delete [] sourcedata;
- delete [] destdata;
- cout << "Konwersja ukonczona." << endl << endl;
- system("pause");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement