299 lines
11 KiB
C
299 lines
11 KiB
C
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <inttypes.h>
|
||
#include <math.h>
|
||
typedef unsigned char uch;
|
||
|
||
|
||
// 妾旀绲愭
|
||
#pragma pack(2)
|
||
struct BmpFileHeader {
|
||
uint16_t bfTybe;
|
||
uint32_t bfSize;
|
||
uint16_t bfReserved1;
|
||
uint16_t bfReserved2;
|
||
uint32_t bfOffBits;
|
||
};
|
||
struct BmpInfoHeader {
|
||
uint32_t biSize;
|
||
uint32_t biWidth;
|
||
uint32_t biHeight;
|
||
uint16_t biPlanes; // 1=defeaul, 0=custom
|
||
uint16_t biBitCount;
|
||
uint32_t biCompression;
|
||
uint32_t biSizeImage;
|
||
uint32_t biXPelsPerMeter; // 72dpi=2835, 96dpi=3780
|
||
uint32_t biYPelsPerMeter; // 120dpi=4724, 300dpi=11811
|
||
uint32_t biClrUsed;
|
||
uint32_t biClrImportant;
|
||
};
|
||
#pragma pack()
|
||
|
||
//杈呭姪璁$畻鍑芥暟
|
||
float linear_single(float x, float x1, float x2, float f1, float f2){
|
||
return floor(f1 * (x2 - x) / (x2 - x1) + f2 * (x - x1) / (x2 - x1));
|
||
}
|
||
|
||
// 鍙岀嚎鎬ф彃鍊煎嚱鏁<E59AB1>
|
||
// 鍙傝€<E5829D> https://zh.wikipedia.org/wiki/%E5%8F%8C%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC
|
||
char** linear_insert(uch** old_pixels, uint32_t row, uint32_t col, uint32_t old_width, uint32_t old_height, float radio_w, float radio_h){
|
||
float x = row / radio_h;
|
||
float y = col / radio_w;
|
||
// 濡傛灉鏁存暟鏍肩偣灏辩洿鎺ヨ繑鍥<E7B991>
|
||
int x1 = floor(x);
|
||
int x2 = ceil(x);
|
||
int y1 = floor(y);
|
||
int y2 = ceil(y);
|
||
if (x2 >= old_height){x2 = x1;}
|
||
|
||
if (y2 >= old_width){y2 = y1;}
|
||
if (x1 == x2 && y1 == y2){
|
||
uint32_t idx = x1*old_width+y1;
|
||
return old_pixels[idx + 0], old_pixels[idx + 1], old_pixels[idx + 2];}
|
||
if (x1 == x2){
|
||
int x = x1;
|
||
uint32_t idx1 = x*old_width+y;
|
||
uint32_t idx2 = x*old_width+y;
|
||
float r = linear_single(y, y1, y2, old_pixels[x][idx1 + 0], old_pixels[x][idx2 + 0]);
|
||
float g = linear_single(y, y1, y2, old_pixels[x][idx1 + 1], old_pixels[x][idx2 + 1]);
|
||
float b = linear_single(y, y1, y2, old_pixels[x][idx1 + 2], old_pixels[x][idx2 + 2]);
|
||
return (char)r, (char)g, (char)b;
|
||
}
|
||
if (y1 == y2){
|
||
int y = y1;
|
||
uint32_t idx = x*old_width+y;
|
||
float r = linear_single(x, x1, x2, old_pixels[x1][idx + 0], old_pixels[x2][idx + 0]);
|
||
float g = linear_single(x, x1, x2, old_pixels[x1][idx + 1], old_pixels[x2][idx + 1]);
|
||
float b = linear_single(x, x1, x2, old_pixels[x1][idx + 2], old_pixels[x2][idx + 2]);
|
||
return (char)r, (char)g, (char)b;
|
||
}
|
||
uint32_t idx1 = x*old_width+y;
|
||
uint32_t idx2 = x*old_width+y;
|
||
float fy1_r = linear_single(x, x1, x2, old_pixels[x1][idx1 + 0], old_pixels[x2][idx1 + 0]);
|
||
float fy1_g = linear_single(x, x1, x2, old_pixels[x1][idx1 + 1], old_pixels[x2][idx1 + 1]);
|
||
float fy1_b = linear_single(x, x1, x2, old_pixels[x1][idx1 + 2], old_pixels[x2][idx1 + 2]);
|
||
float fy2_r = linear_single(x, x1, x2, old_pixels[x1][idx2 + 0], old_pixels[x2][idx2 + 0]);
|
||
float fy2_g = linear_single(x, x1, x2, old_pixels[x1][idx2 + 1], old_pixels[x2][idx2 + 1]);
|
||
float fy2_b = linear_single(x, x1, x2, old_pixels[x1][idx2 + 2], old_pixels[x2][idx2 + 2]);
|
||
float r = linear_single(y, y1, y2, fy1_r, fy2_r);
|
||
float g = linear_single(y, y1, y2, fy1_g, fy2_g);
|
||
float b = linear_single(y, y1, y2, fy1_b, fy2_b);
|
||
return (char)r, (char)g, (char)b;
|
||
}
|
||
|
||
void bmpWrite(const char* name, const uch* raw_img, uint32_t width, uint32_t height, uint32_t bits, float radio_w, float radio_h){
|
||
if(!(name && raw_img)){
|
||
perror("Error bmpWrite.");
|
||
return;
|
||
}
|
||
// 妾旀璩囪▕
|
||
struct BmpFileHeader file_h = {
|
||
.bfTybe=0x4d42,
|
||
.bfReserved1=0,
|
||
.bfReserved2=0,
|
||
.bfOffBits=54,
|
||
};
|
||
|
||
uint32_t new_width = floor(width*radio_w);
|
||
uint32_t new_height = floor(height*radio_h);
|
||
file_h.bfSize = file_h.bfOffBits + new_width*new_height * bits/8;
|
||
if(bits==8) {file_h.bfSize+= 1024, file_h.bfOffBits+= 1024;}
|
||
|
||
|
||
// 鍦栫墖璩囪▕
|
||
struct BmpInfoHeader info_h = {
|
||
.biSize=40,
|
||
.biPlanes=1,
|
||
.biCompression=0,
|
||
.biXPelsPerMeter=0,
|
||
.biYPelsPerMeter=0,
|
||
.biClrUsed=0,
|
||
.biClrImportant=0,
|
||
};
|
||
info_h.biWidth = new_width;
|
||
info_h.biHeight = new_height;
|
||
info_h.biBitCount = bits;// 澶氬皯浣嶇殑鍦<E6AE91>
|
||
info_h.biSizeImage = new_width*new_height * bits/8;
|
||
if(bits == 8) {info_h.biClrUsed=256;}
|
||
// 瀵叆妾旈牠
|
||
FILE *pFile = NULL;
|
||
// pFile = fopen(name,"wb+");
|
||
fopen_s(&pFile, name,"wb+");
|
||
if(!pFile) {
|
||
perror("Error opening file.");
|
||
return;
|
||
}
|
||
fwrite((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
|
||
fwrite((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
|
||
// 瀵鑹茬洡
|
||
if(bits == 8) {
|
||
for(unsigned i = 0; i < 256; ++i) {
|
||
uch c = i;
|
||
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
|
||
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
|
||
fwrite((char*)&c, sizeof(char), sizeof(uch), pFile);
|
||
fwrite("", sizeof(char), sizeof(uch), pFile);
|
||
}
|
||
}
|
||
|
||
// char newpixels[new_width*new_height];
|
||
unsigned char **newpixels=(unsigned char**)malloc(new_width*new_height*3);// 娌掔敤鍒<E695A4>
|
||
|
||
// 瀵叆鍦栫墖璩囪▕
|
||
size_t alig = ((new_width*bits/8)*3) % 4;
|
||
for(int j = new_height-1; j >= 0; --j) {
|
||
for(unsigned i = 0; i < new_width; ++i) {
|
||
uint32_t idx = j*new_width +i;
|
||
if(bits == 24) { // RGB鍦栫墖
|
||
fwrite((char*)&raw_img[idx*3 +2], sizeof(char), sizeof(uch), pFile);
|
||
fwrite((char*)&raw_img[idx*3 +1], sizeof(char), sizeof(uch), pFile);
|
||
fwrite((char*)&raw_img[idx*3 +0], sizeof(char), sizeof(uch), pFile);
|
||
// printf("%x",(raw_img)[idx*3 +2]);
|
||
// printf("%x",(raw_img)[idx*3 +1]);
|
||
// printf("%x",(raw_img)[idx*3 +0]);
|
||
// printf(" ");
|
||
}
|
||
else if(bits == 8) { // 鐏伴殠鍦<E6AEA0>
|
||
fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
|
||
}
|
||
// printf("\n");
|
||
}
|
||
|
||
|
||
// for(int j = new_height-1; j >= 0; --j) {
|
||
// for(unsigned i = 0; i < new_width; ++i) {
|
||
// uint32_t idx = j*new_width +i;
|
||
// if(bits == 24) { // RGB鍦栫墖
|
||
// char** r, g, b = linear_insert(&(raw_img), j, i, width, height, radio_w, radio_h);
|
||
// fwrite(b, sizeof(char), sizeof(uch), pFile);
|
||
// fwrite(g, sizeof(char), sizeof(uch), pFile);
|
||
// fwrite(r, sizeof(char), sizeof(uch), pFile);
|
||
// } else if(bits == 8) { // 鐏伴殠鍦<E6AEA0>
|
||
// fwrite((char*)&raw_img[idx], sizeof(char), sizeof(uch), pFile);
|
||
// }
|
||
// }
|
||
//# 璁$畻鏂板儚绱<E5849A>
|
||
// 灏嶉綂4byte
|
||
for(size_t i = 0; i < alig; ++i) {
|
||
fwrite("", sizeof(char), sizeof(uch), pFile);
|
||
}
|
||
}
|
||
fclose(pFile);
|
||
|
||
free(newpixels); //瑷樺緱閲嬫斁绌洪枔
|
||
}
|
||
void bmpRead(const char* name, uch** oldpixels, uint32_t* width, uint32_t* height, uint16_t* bits)
|
||
{
|
||
if(!(name && oldpixels && width && height && bits)) {
|
||
perror("Error bmpRead.");
|
||
return;
|
||
}
|
||
// 妾旀璩囪▕
|
||
struct BmpFileHeader file_h;
|
||
// 鍦栫墖璩囪▕
|
||
struct BmpInfoHeader info_h;
|
||
// 璁€鍙栨獢闋<E78DA2>
|
||
FILE *pFile = NULL;
|
||
// pFile = fopen(name, "rb+");
|
||
fopen_s(&pFile, name, "rb+");
|
||
if(!pFile) {
|
||
perror("Error opening file.");
|
||
return;
|
||
}
|
||
fread((char*)&file_h, sizeof(char), sizeof(file_h), pFile);
|
||
fread((char*)&info_h, sizeof(char), sizeof(info_h), pFile);
|
||
// 璁€鍙栭暦瀵<E69AA6>
|
||
*width = info_h.biWidth;
|
||
*height = info_h.biHeight;
|
||
*bits = info_h.biBitCount;
|
||
// **oldpixels=(unsigned char**)malloc((*width)*(*height)*3);
|
||
|
||
size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
|
||
*oldpixels = (uch*)calloc(ImgSize, sizeof(uch));
|
||
// 璁€鍙栬畝鐗囪硣瑷婅綁RAW妾旇硣瑷<E7A1A3>
|
||
fseek(pFile, file_h.bfOffBits, SEEK_SET);
|
||
size_t alig = ((info_h.biWidth*info_h.biBitCount/8)*3) % 4;
|
||
for(int j = *height-1; j >= 0; --j) {
|
||
for(unsigned i = 0; i < *width; ++i) {
|
||
uint32_t idx = j*(*width)+i;
|
||
if(*bits == 24) { // RGB鍦栫墖
|
||
fread((char*)&(*oldpixels)[idx*3 +2], sizeof(char), sizeof(uch), pFile);
|
||
fread((char*)&(*oldpixels)[idx*3 +1], sizeof(char), sizeof(uch), pFile);
|
||
fread((char*)&(*oldpixels)[idx*3 +0], sizeof(char), sizeof(uch), pFile);
|
||
} else if(*bits == 8) { // 鐏伴殠鍦<E6AEA0>
|
||
fread((char*)&(*oldpixels)[idx], sizeof(char), sizeof(uch), pFile);
|
||
}
|
||
}
|
||
fseek(pFile , (long)alig , SEEK_CUR);
|
||
}
|
||
fclose(pFile);
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
// size_t ImgSize = ((size_t)*width) * ((size_t)*height) * 3;
|
||
// *raw_img = (uch*)calloc(ImgSize, sizeof(uch));
|
||
// // 璁€鍙栬畝鐗囪硣瑷婅綁RAW妾旇硣瑷<E7A1A3>
|
||
// fseek(pFile, file_h.bfOffBits, SEEK_SET);
|
||
// size_t alig = ((info_h.biWidth*info_h.biBitCount/8)*3) % 4;
|
||
// for(int j = *height-1; j >= 0; --j) {
|
||
// for(unsigned i = 0; i < *width; ++i) {
|
||
// uint32_t idx = j*(*width)+i;
|
||
// if(*bits == 24) { // RGB鍦栫墖
|
||
// fread((char*)&(*raw_img)[idx*3 +2], sizeof(char), sizeof(uch), pFile);
|
||
// fread((char*)&(*raw_img)[idx*3 +1], sizeof(char), sizeof(uch), pFile);
|
||
// fread((char*)&(*raw_img)[idx*3 +0], sizeof(char), sizeof(uch), pFile);
|
||
// } else if(*bits == 8) { // 鐏伴殠鍦<E6AEA0>
|
||
// fread((char*)&(*raw_img)[idx], sizeof(char), sizeof(uch), pFile);
|
||
// }
|
||
// }
|
||
// fseek(pFile , (long)alig , SEEK_CUR);
|
||
// }
|
||
// fclose(pFile);
|
||
//----------------------------------------------------------------------------
|
||
|
||
for(int j = *height-1; j >= 0; --j) {
|
||
for(unsigned i = 0; i < *width; ++i) {
|
||
uint32_t idx = j*(*width)+i;
|
||
for(int k = 0; k < 3; k++){
|
||
printf("%x",(*oldpixels)[idx*3 +k]);
|
||
printf(" ");
|
||
}
|
||
printf("\t");
|
||
}
|
||
printf("\n");
|
||
}
|
||
printf("done \n");
|
||
}
|
||
|
||
// 鍦栧儚绲愭
|
||
typedef struct Imgraw {
|
||
uint32_t width, height;
|
||
uint16_t bits;
|
||
uch* data;
|
||
} Imgraw;
|
||
|
||
void Imgraw_Read(const Imgraw* _this, const char* name) {
|
||
const Imgraw* p = _this;
|
||
bmpRead(name, &p->data, &p->width, &p->height, &p->bits);
|
||
}
|
||
void Imgraw_Writ(const Imgraw* _this, const char* name, float radio_w, float radio_h) {
|
||
const Imgraw* p = _this;
|
||
bmpWrite(name, p->data, p->width, p->height, p->bits, radio_w, radio_h);
|
||
}
|
||
/*==============================================================*/
|
||
int main(int argc, char const *argv[]) {
|
||
float radio_w, radio_h;
|
||
printf("Enter a radio of width :") ;
|
||
scanf("%f", &radio_w);
|
||
printf("Enter a radio of height :") ;
|
||
scanf("%f", &radio_h);
|
||
printf("\n");
|
||
// 寤烘
|
||
Imgraw img = {0, 0, 0, NULL};
|
||
// 璁€鍦<E282AC>
|
||
Imgraw_Read(&img, "./input/bw2x1.bmp");
|
||
// 瀵湒
|
||
Imgraw_Writ(&img, "./output/bw2x1(output).bmp", radio_w, radio_h);
|
||
return 0;
|
||
}
|
||
/*==============================================================*/ |