Skip to content

Instantly share code, notes, and snippets.

@tearfulDalvik
Created July 17, 2020 15:37
Show Gist options
  • Save tearfulDalvik/ca8b21285aa11c71720a3cbdf50feb9b to your computer and use it in GitHub Desktop.
Save tearfulDalvik/ca8b21285aa11c71720a3cbdf50feb9b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <windows.h>
#include <vector>
typedef struct COLOR {
BYTE rgbaBlue;
BYTE rgbaGreen;
BYTE rgbaRed;
BYTE rgbaAlpha;
} *PCOLOR;
class Bitmap {
public:
PBITMAPFILEHEADER fileHeader;
PBITMAPINFOHEADER infoHeader;
Bitmap(const char*);
// Contains padding as well
std::vector<uint8_t> read_bmpImageData();
std::vector<uint8_t> image_black();
std::vector<uint8_t> image_shift(int, int);
static void write(int, int, std::vector<uint8_t>);
private:
FILE* fp;
const char* path;
};
int main(void)
{
Bitmap* b = new Bitmap("D:\\1.bmp");
std::vector<uint8_t> imageData = b->read_bmpImageData();
b->write(b->infoHeader->biWidth, b->infoHeader->biHeight, b->image_shift(-50, 70));
return 0;
}
Bitmap::Bitmap(const char* path) {
errno_t err;
if ((err = fopen_s(&fp, path, "rb")) != NULL)
{
throw "can't open the bmp imgae.";
}
this->path = path;
fileHeader = new BITMAPFILEHEADER;
fread(fileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
infoHeader = new BITMAPINFOHEADER;
fread(infoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
if (infoHeader->biSize != 40) {
throw "bit marks not supported";
}
if (infoHeader->biBitCount != 8) {
throw "8 bit(grey scale) images only";
}
if (infoHeader->biCompression != 0) {
throw "compression not supported";
}
printf("类型为\t%c%c\n", (char)fileHeader->bfType, (char)(fileHeader->bfType >> 8));
printf("大小\t%d\n", fileHeader->bfSize);
printf("高度\t%d\n", infoHeader->biHeight);
printf("宽度\t%d\n", infoHeader->biWidth);
}
std::vector<uint8_t> Bitmap::read_bmpImageData() {
if (fseek(fp, fileHeader->bfOffBits, SEEK_SET) != 0) {
throw "cannot locate color bits";
}
std::vector<uint8_t> data;
data.resize(infoHeader->biWidth * infoHeader->biHeight);
fread(data.data(), data.size(), 1, fp);
return data;
}
std::vector<uint8_t> Bitmap::image_black() {
std::vector<uint8_t> image = read_bmpImageData();
int width = infoHeader->biWidth;
int height = infoHeader->biHeight;
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 50; j++) {
image[i * width + j] = 1;
image[(height - i - 1) * width + j] = 1;
image[i * width + (width - j - 1)] = 1;
image[(height - i - 1) * width + (width - j - 1)] = 1;
}
}
return image;
}
std::vector<uint8_t> Bitmap::image_shift(int l2r, int t2b) {
int width = infoHeader->biWidth;
int height = infoHeader->biHeight;
std::vector<uint8_t> original = read_bmpImageData();
std::vector<uint8_t> image = read_bmpImageData();
image.resize(height * width);
// i is row while j is column
if (l2r != 0) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if ((l2r < 0 && j >= width + l2r) || (l2r > 0 && j <= l2r)) {
image[i * width + j] = 0;
continue;
}
image[i * width + j] = original[i * width + j - l2r];
}
}
}
original = image;
if (t2b != 0) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if ((t2b > 0 && i >= height - t2b) || (t2b < 0 && i <= -t2b)) {
image[i * width + j] = 0;
continue;
}
image[i * width + j] = original[(i + t2b) * width + j];
}
}
}
return image;
}
void Bitmap::write(int width, int height, std::vector<uint8_t> data) {
if (data.size() != width * height) {
throw "size not equal";
}
errno_t err;
FILE* fp;
if ((err = fopen_s(&fp, "D:\\rewriten.bmp", "wb")) != NULL)
{
throw "can't open the bmp imgae.";
}
BITMAPFILEHEADER fh = {};
BITMAPINFOHEADER ih = {};
std::vector<COLOR> colors = {};
for (uint8_t i = 0; i < (2 << 7) - 1; i++) {
colors.push_back(COLOR{i,i,i,0});
}
colors.push_back(COLOR{ 0xff,0xff,0xff,0 });
COLOR* colorTable = colors.data();
fh.bfType = 0x4d42;
fh.bfSize = sizeof(fh) + sizeof(ih) + data.size() + (2 << 7) * sizeof(DWORD);
fh.bfOffBits = sizeof(fh) + sizeof(ih) + (2 << 7) * sizeof(DWORD);
ih.biSize = sizeof(ih);
ih.biWidth = width;
ih.biHeight = height;
ih.biBitCount = 8;
ih.biCompression = 0;
ih.biPlanes = 1;
ih.biSizeImage = data.size();
ih.biClrUsed = 2 << 7;
ih.biClrImportant = 2 << 7;
fwrite(&fh, sizeof(fh), 1, fp);
fwrite(&ih, sizeof(ih), 1, fp);
fwrite(colorTable, (2 << 7) * sizeof(COLOR), 1, fp);
fwrite(data.data(), data.size(), 1, fp);
ShellExecute(NULL, NULL, L"D:\\rewriten.bmp", NULL, NULL, SW_SHOW);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment