Last active
May 25, 2016 17:46
-
-
Save sysint64/9c0a0a68acfb84bf6ec3bc90770247b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <vector> | |
#include <string> | |
#include <array> | |
#include <math.h> | |
// Палитры цветов | |
#include "palettes.h" | |
class Bitmap { | |
public: | |
uint32_t width, height; | |
uint16_t bitsPerPixel; | |
std::vector<uint8_t> pixels; | |
std::vector<uint8_t> fileInfo; | |
Bitmap() {} | |
Bitmap (const std::string &fileName) { | |
loadFromFile(fileName); | |
} | |
void loadFromFile (const std::string &fileName); | |
void saveToFile (const std::string &fileName); | |
void changePalette (uint8_t palette[][3], size_t size); | |
}; | |
void Bitmap::loadFromFile (const std::string &fileName) { | |
std::fstream hFile (fileName, std::ios::in | std::ios::binary); | |
if (!hFile.is_open()) | |
throw std::invalid_argument ("Error: File Not Found."); | |
hFile.seekg (0, std::ios::end); | |
size_t length = hFile.tellg(); | |
hFile.seekg (0, std::ios::beg); | |
fileInfo.resize (length); | |
hFile.read (reinterpret_cast<char*>(fileInfo.data()), 54); | |
if (fileInfo[0] != 'B' && fileInfo[1] != 'M') { | |
hFile.close(); | |
throw std::invalid_argument("Error: Invalid File Format. Bitmap Required."); | |
} | |
bitsPerPixel = fileInfo[28]; | |
width = fileInfo[18] + (fileInfo[19] << 8); | |
height = fileInfo[22] + (fileInfo[23] << 8); | |
uint32_t pixelsOffset = fileInfo[10] + (fileInfo[11] << 8); | |
uint32_t size = ((width * bitsPerPixel + 31) / 32) * 4 * height; | |
pixels.resize (size); | |
hFile.seekg (pixelsOffset, std::ios::beg); | |
hFile.read (reinterpret_cast<char*>(pixels.data()), size); | |
hFile.close (); | |
} | |
void Bitmap::saveToFile (const std::string &fileName) { | |
std::fstream hFile (fileName, std::ios::out | std::ios::binary); | |
fileInfo[28] = bitsPerPixel; | |
uint32_t pixelsOffset = fileInfo[10] + (fileInfo[11] << 8); | |
hFile.write (reinterpret_cast<char*>(fileInfo.data()), pixelsOffset); | |
hFile.write (reinterpret_cast<char*>(pixels .data()), pixels .size()); | |
hFile.close (); | |
} | |
inline double sqr (double x) { return x*x; } | |
uint8_t getColor (uint8_t* color, uint8_t palette[][3], size_t size) { | |
double minDeltaE = 999.0; | |
int target = 0; | |
for (int i = 0; i < size; ++i) { | |
auto cpDeltaE = sqrt(sqr(palette[i][0]-color[0]) + | |
sqr(palette[i][1]-color[1]) + | |
sqr(palette[i][2]-color[2])); | |
if (minDeltaE > cpDeltaE) { | |
minDeltaE = cpDeltaE; | |
target = i; | |
} | |
} | |
return target; | |
} | |
void Bitmap::changePalette (uint8_t palette[][3], size_t size) { | |
std::vector<uint8_t> newPixels; | |
uint8_t byte = 0; | |
uint8_t c = 0; | |
uint8_t c1 = 0; | |
uint8_t c2 = 0; | |
for (int i = 0; i < pixels.size(); i += 3) { | |
int paletteIdx = getColor (&pixels[i], palette, size); | |
newPixels.push_back (palette[paletteIdx][0]); | |
newPixels.push_back (palette[paletteIdx][1]); | |
newPixels.push_back (palette[paletteIdx][2]); | |
} | |
std::cout << std::endl; | |
pixels = newPixels; | |
} | |
int main() { | |
Bitmap bmp ("turtles.bmp"); | |
bmp.changePalette (RGB4_Palette, 16); // 4 битная палтира | |
// bmp.changePalette (RGB8_Palette, 256); // 8 битная палитра | |
bmp.saveToFile ("test.bmp"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment