Created
July 17, 2020 15:37
-
-
Save tearfulDalvik/ca8b21285aa11c71720a3cbdf50feb9b to your computer and use it in GitHub Desktop.
This file contains hidden or 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 <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