285 lines
9.1 KiB
C++
285 lines
9.1 KiB
C++
#include <iostream>
|
||
#include <fstream>
|
||
#include <windows.h>
|
||
#include <stdio.h>
|
||
#include <string>
|
||
#include <math.h>
|
||
#include <algorithm>
|
||
using namespace std;
|
||
|
||
typedef unsigned char uch;
|
||
|
||
void error(int x){
|
||
switch (x)
|
||
{
|
||
case 1:
|
||
fprintf(stderr, "Usage: ./transform.exe infile outfile width*height!\n");
|
||
break;
|
||
|
||
case 2:
|
||
fprintf(stderr, "Format of infile is wrong, pleace check it and try again!\n");
|
||
break;
|
||
|
||
case 3:
|
||
fprintf(stderr, "Format of outfile is wrong, pleace check it and try again!\n");
|
||
break;
|
||
|
||
case 4:
|
||
fprintf(stderr, "Please use width*height or angle format at the end!\n");
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
bool isNumber(const string& str)
|
||
{
|
||
return !str.empty() &&
|
||
std::find_if(str.begin(), str.end(),
|
||
[](unsigned char c) { return !std::isdigit(c); }) == str.end();
|
||
}
|
||
|
||
char* input_file = new char[100];
|
||
char* output_file = new char[100];
|
||
uint32_t old_width, old_height, bit;
|
||
uint32_t new_width, new_height;
|
||
int situation = 0;
|
||
int angle = 0;
|
||
|
||
int main(int argc, char* argv[]){
|
||
BITMAPFILEHEADER old_head;
|
||
BITMAPINFOHEADER old_info;
|
||
ifstream infile;
|
||
|
||
if(argc != 4){
|
||
error(1);
|
||
return 0;
|
||
}
|
||
else{
|
||
input_file = argv[1];
|
||
output_file = argv[2];
|
||
string funtion = argv[3];
|
||
string special_symbol = "*";
|
||
string special_words = ".bmp";
|
||
|
||
string::size_type check_in, check_out, func;
|
||
check_in = ((string)input_file).find(special_words);
|
||
check_out = ((string)output_file).find(special_words);
|
||
func = funtion.find(special_symbol);
|
||
|
||
infile.open(input_file, ios::in | ios::binary);
|
||
infile.read((char*)&old_head, sizeof(BITMAPFILEHEADER));
|
||
infile.read((char*)&old_info, sizeof(BITMAPINFOHEADER));
|
||
uint32_t old_width = old_info.biWidth;
|
||
uint32_t old_height = old_info.biHeight;
|
||
uint16_t bit = old_info.biBitCount;
|
||
|
||
if(check_in == string::npos){//²»´æ??
|
||
error(2);
|
||
return 0;
|
||
}
|
||
else if(check_out == string::npos){//²»´æ??
|
||
error(3);
|
||
return 0;
|
||
}
|
||
if(func == string::npos){//²»´æÔÚ£¬ÓпÉÄÜÊÇÐýÞD
|
||
if(isNumber(funtion)){
|
||
new_width = old_width;
|
||
new_height = old_height;
|
||
angle = stoi(funtion);
|
||
if(angle == 90){
|
||
situation = 1;
|
||
new_width = old_height;
|
||
new_height = old_width;
|
||
}
|
||
else if(angle == 180){
|
||
situation = 2;
|
||
new_width = old_width;
|
||
new_height = old_height;
|
||
}
|
||
else if(angle == 270){
|
||
situation = 3;
|
||
new_width = old_height;
|
||
new_height = old_width;
|
||
}
|
||
else{error(4);return 0;}
|
||
}
|
||
else{error(4);return 0;}
|
||
}
|
||
else{
|
||
situation = 0;
|
||
int current = 0;
|
||
int pos = funtion.find_first_of(special_symbol, current);
|
||
new_width = atoi((funtion.substr(0, funtion.find(special_symbol))).c_str());
|
||
new_height = atoi((funtion.substr(funtion.find(special_symbol) + 1, funtion.length())).c_str());
|
||
}
|
||
}
|
||
|
||
cout << situation << endl;
|
||
if(old_head.bfType != 0x4d42){
|
||
cout << "error" << endl;
|
||
infile.close();
|
||
return 0;
|
||
}
|
||
|
||
unsigned char raw[old_height][old_width][3] = {};
|
||
// cout << old_info. << endl;
|
||
|
||
int padding = (4 - (old_width * 3) % 4) % 4;
|
||
|
||
for(int y = old_height-1; y >= 0; --y) {
|
||
for(int x = 0; x < old_width; ++x) {
|
||
if(bit == 24) {
|
||
unsigned char colour[3];
|
||
|
||
infile.read((char*)raw[y][x], 3);
|
||
}
|
||
}
|
||
infile.ignore(padding);
|
||
}
|
||
infile.close();
|
||
|
||
//--------------éL¡¢Œ’??-----------------
|
||
// float radio_w, radio_h;
|
||
// printf("±¶”µ(w)??");
|
||
// cin >> radio_w;
|
||
// printf("±¶”µ(h)??");
|
||
// cin >> radio_h;
|
||
// uint32_t new_width = (uint32_t)floor(radio_w*old_width);
|
||
// uint32_t new_height = (uint32_t)floor(radio_h*old_height);
|
||
|
||
//--------------ÌØ¶¨éL¡¢Œ’-----------------
|
||
// uint32_t new_width, new_height;
|
||
// printf("±¶”µ(w)??");
|
||
// scanf("%d", &new_width);
|
||
// printf("±¶”µ(h)??");
|
||
// scanf("%d", &new_height);
|
||
float radio_w = (float)new_width/old_width;
|
||
float radio_h = (float)new_height/old_height;
|
||
|
||
|
||
ofstream outfile;
|
||
outfile.open(output_file, ios::out | ios::binary);
|
||
|
||
BITMAPFILEHEADER new_head;
|
||
BITMAPINFOHEADER new_info;
|
||
new_head.bfType = 0x4d42;
|
||
new_head.bfReserved1 = 0;
|
||
new_head.bfReserved2 = 0;
|
||
new_head.bfOffBits = 54;
|
||
new_head.bfSize = new_head.bfOffBits + new_width*new_height * bit/8;
|
||
if(bit==8){new_head.bfSize += 1024, new_head.bfOffBits += 1024;}
|
||
|
||
new_info.biSize = 40;
|
||
new_info.biPlanes = 1;
|
||
new_info.biCompression = 0;
|
||
new_info.biXPelsPerMeter = 0;
|
||
new_info.biYPelsPerMeter = 0;
|
||
new_info.biClrUsed = 0;
|
||
new_info.biClrImportant = 0;
|
||
|
||
new_info.biWidth = new_width;
|
||
new_info.biHeight = new_height;
|
||
new_info.biBitCount = bit;
|
||
new_info.biSizeImage = new_width*new_height*bit/8;
|
||
|
||
|
||
outfile.write((char*)&new_head, sizeof(new_head));
|
||
outfile.write((char*)&new_info, sizeof(new_info));
|
||
|
||
// cout << "\nnew_width : " << new_width << endl;
|
||
// cout << "new_height : " << new_height << endl;
|
||
|
||
padding = (4 - (new_width * 3) % 4) % 4;
|
||
unsigned char bmpPad[3] = {0, 0, 0};
|
||
switch (situation)
|
||
{
|
||
case 0:
|
||
//---------------------------resize-------------------------
|
||
for(int y = new_height-1; y >= 0; --y){
|
||
for(int x = 0; x < new_width; ++x){
|
||
if(bit == 24) {
|
||
unsigned char b = raw[(int)(y/radio_h)][(int)(x/radio_w)][2];
|
||
unsigned char g = raw[(int)(y/radio_h)][(int)(x/radio_w)][1];
|
||
unsigned char r = raw[(int)(y/radio_h)][(int)(x/radio_w)][0];
|
||
unsigned char color[] = {r, g, b};
|
||
outfile.write((char*)color, 3);
|
||
}
|
||
// else if(bit == 8){
|
||
// outfile.write((char*)&raw[i][j], sizeof(char*));
|
||
// }
|
||
}
|
||
outfile.write((char*)bmpPad, padding);
|
||
}
|
||
break;
|
||
|
||
case 1:
|
||
//---------------------------turn 90-------------------------
|
||
for(int x = 0; x < new_width; ++x){
|
||
for(int y = 0; y < new_height; ++y){
|
||
if(bit == 24) {
|
||
unsigned char b = raw[(int)(y/radio_h)][(int)(x/radio_w)][2];
|
||
unsigned char g = raw[(int)(y/radio_h)][(int)(x/radio_w)][1];
|
||
unsigned char r = raw[(int)(y/radio_h)][(int)(x/radio_w)][0];
|
||
unsigned char color[] = {r, g, b};
|
||
outfile.write((char*)color, 3);
|
||
}
|
||
// else if(bit == 8){
|
||
// outfile.write((char*)&raw[i][j], sizeof(char*));
|
||
// }
|
||
}
|
||
outfile.write((char*)bmpPad, padding);
|
||
}
|
||
outfile.close();
|
||
return 0;
|
||
break;
|
||
|
||
case 2:
|
||
//---------------------------turn 180-------------------------
|
||
for(int y = 0; y < new_height; ++y){
|
||
for(int x = new_width-1; x >= 0; --x){
|
||
if(bit == 24) {
|
||
unsigned char b = raw[(int)(y/radio_h)][(int)(x/radio_w)][2];
|
||
unsigned char g = raw[(int)(y/radio_h)][(int)(x/radio_w)][1];
|
||
unsigned char r = raw[(int)(y/radio_h)][(int)(x/radio_w)][0];
|
||
unsigned char color[] = {r, g, b};
|
||
outfile.write((char*)color, 3);
|
||
}
|
||
// else if(bit == 8){
|
||
// outfile.write((char*)&raw[i][j], sizeof(char*));
|
||
// }
|
||
}
|
||
outfile.write((char*)bmpPad, padding);
|
||
}
|
||
outfile.close();
|
||
return 0;
|
||
break;
|
||
|
||
case 3:
|
||
//---------------------------turn 270-------------------------
|
||
for(int x = new_width - 1; x >= 0; --x){
|
||
for(int y = new_height-1; y >= 0; --y){
|
||
if(bit == 24) {
|
||
unsigned char b = raw[(int)(y/radio_h)][(int)(x/radio_w)][2];
|
||
unsigned char g = raw[(int)(y/radio_h)][(int)(x/radio_w)][1];
|
||
unsigned char r = raw[(int)(y/radio_h)][(int)(x/radio_w)][0];
|
||
unsigned char color[] = {r, g, b};
|
||
outfile.write((char*)color, 3);
|
||
}
|
||
// else if(bit == 8){
|
||
// outfile.write((char*)&raw[i][j], sizeof(char*));
|
||
// }
|
||
}
|
||
outfile.write((char*)bmpPad, padding);
|
||
}
|
||
outfile.close();
|
||
return 0;
|
||
break;
|
||
default:
|
||
return 0;
|
||
break;
|
||
}
|
||
//-----------------------------------------------------------------------------
|
||
outfile.close();
|
||
return 0;
|
||
} |