Skip to content

Instantly share code, notes, and snippets.

@sysint64
Last active May 25, 2016 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sysint64/9c0a0a68acfb84bf6ec3bc90770247b0 to your computer and use it in GitHub Desktop.
Save sysint64/9c0a0a68acfb84bf6ec3bc90770247b0 to your computer and use it in GitHub Desktop.
#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