使用C ++将bmp照片旋转90度 [英] stuck in rotating a bmp photo 90 degrees using C++
问题描述
这是我的代码,它破坏了照片我不知道为什么!
**它是一个24位的位图**
< pre lang =c ++> #include < < span class =code-leadattribute> iostream >
#include < fstream >
使用 命名空间 std ;
int main()
{
fstream flower( < span class =code-string> flower.bmp,ios :: in | ios :: out | ios :: binary);
// 声明一个包含数据字节的数组属于800 * 686像素:
char temp [ 686 * 800 * 3 ]; // * 3因为每个像素包含3个字节。
flower.seekg ( 54 ,ios :: beg); // 花的第54个字节(bmp文件)属于标题,像素数据在此之后开始)
flower.read(temp, 686 * 3 * 800 ); // 将像素字节分配给数组:
// 交换位图文件的宽度和高度:
flower.seekg( 18 ,ios :: beg); // 19,20,21 ,22个字节定义bmp文件的宽度,它是一个整数,接下来的4个字节属于高度。
char read1 [ 4 跨度>];
char read2 [ 4 ];
flower.read(read1, 4 );
flower.read(read2, 4 );
flower.seekg( 22 ,ios :: beg);
flower.write(read1, 4 );
flower.seekg( 18 ,ios :: beg);
flower.write(read2, 4 );
// 用高度字节交换宽度字节。
flower.seekg(< span class =code-digit> 54 ,ios :: beg);
int k = 0 ;
int l = 0 ;
for ( int i = 1 ; i< = 686 ; i ++)
{
flower.seekg(54 + k,ios :: beg);
for ( int j = 1 ; j< = 800 ; j ++)
{
flower.put(temp [l]);
flower.seekg( 1 );
flower.put(temp [++ l]);
flower.seekg( 1 );
flower.put(temp [++ l]);
l ++;
flower.seekg( 685 * 3 );
}
k + = 3 ;
}
flower.close();
}
你必须考虑到位图在32 32
位(即四个字节)边界(填充)。宽度800
的原始位图不需要填充(因此大小正好是1646454
字节)图像需要它(686%4
非零),即你需要为每个添加2
填充字节行(因此文件大小1648054
,即800x2
比原始文件长)。
以下代码旋转原始图像,将结果写入'rflower.bmp
'文件。
#include < iostream >
#include < fstream >
#include < stdint.h >
使用 命名空间标准;
int main()
{
const int BFHS = 14 ; // 位图文件标题大小
const int BIHS = 40 ; // 位图信息标题大小
const int W = 800 ;
const int H = 686 ;
ifstream bmp( flower.bmp,ios :: binary) ;
ofstream rbm( rflower.bmp,ios :: binary);
char head [BFHS + BIHS];
char rgb [ 3 * W * H];
// 复制标题
bmp.read(head ,BFHS + BIHS);
// 交换宽度与高度
uint32_t temp = *(uint32_t *) &安培;头[BFHS + 4];
*(uint32_t *)& head [BFHS + 4] = *(uint32_t *)& head [BFHS + 8];
*(uint32_t *)& head [BFHS + 8] = temp;
rbm.write(head,BFHS + BIHS);
// 读取像素值
bmp.read(rgb, 3 跨度> * W * H);
char 零[ 3 ] = { 0 跨度>};
for ( int y = 0 ; y< W; ++ y)
{
for ( int x = 0 ; x< H; ++ x)
{
// rbm(x,y)是原始bmp(y,H-1-x)
rbm.write(& rgb [ (H - x - 1 )* W * 3 + y * 3 ], 3 );
}
rbm.write(零, 2 ); // 32位边界对齐
}
}
通过以下基于零的索引转换完成将矩阵旋转90度:A = N x M原始矩阵
B = M×N变换矩阵(即旋转+90度)
A [i,j] - > B [M-j-1,i]因此,您将数据读入内存中的原始矩阵,在内存中创建转换矩阵,并将原始单元转换为转换后的矩阵。最后,将数据从内存写入文件(带有相应的标题和填充字节)。
干杯
Andi
PS:请注意,位图文件中的每一行都填充为4个字节的倍数!
如果您正在编写Windows代码您可以使用.Net库来帮助您:
旋转图像 [ ^ ]然后它适用于任何图片。
如前所述,使用硬编码值并不好,它们应该是您方法的参数。
同样使用十六进制编辑器可以帮助您查看文件的真实外观。
here's my code, it corrupts the photo i donno why!
** its a 24-bit bitmap **
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
fstream flower("flower.bmp", ios::in | ios::out | ios::binary);
//declaring an array which holds data bytes belong to 800*686 pixels:
char temp[686*800*3]; // *3 because each pixel contains 3 bytes.
flower.seekg(54,ios::beg); //first 54 bytes of flower (bmp file) belong to the headers, pixels data start after that)
flower.read(temp,686*3*800);//assigning pixel bytes to the array:
//swapping width and height of the bitmap file:
flower.seekg(18,ios::beg);//19,20,21,22 bytes defines the width of bmp file which is an integer and next 4 bytes belong to the height.
char read1[4];
char read2[4];
flower.read(read1,4);
flower.read(read2,4);
flower.seekg(22,ios::beg);
flower.write(read1,4);
flower.seekg(18,ios::beg);
flower.write(read2,4);
//swapping width bytes with height bytes.
flower.seekg(54,ios::beg);
int k=0;
int l=0;
for(int i=1;i<=686;i++)
{
flower.seekg(54+k,ios::beg);
for(int j=1;j<=800;j++)
{
flower.put(temp[l]);
flower.seekg(1);
flower.put(temp[++l]);
flower.seekg(1);
flower.put(temp[++l]);
l++;
flower.seekg(685*3);
}
k+=3;
}
flower.close();
}
You have to take into account that bitmaps have rows aligned on32
bits (i.e four bytes) boundaries (they are padded). The original bitmap, having width800
doesn't need padding (hence is size is exactly1646454
bytes) while the rotated image needs it (686 % 4
is non-zero), that is you need to add2
padding bytes per each row (hence the file size is1648054
, that is800x2
longer than the original one).
The following code rotates the original image, writing the resulting one to the 'rflower.bmp
' file.
#include<iostream> #include<fstream> #include <stdint.h> using namespace std; int main() { const int BFHS = 14; // bitmap file header size const int BIHS = 40; // bitmap info header size const int W = 800; const int H = 686; ifstream bmp("flower.bmp", ios::binary); ofstream rbm("rflower.bmp", ios::binary); char head[BFHS+BIHS]; char rgb[3*W*H]; // copy the header bmp.read(head, BFHS+BIHS); // swap width with height uint32_t temp = *(uint32_t*)&head[BFHS+4]; *(uint32_t*)&head[BFHS+4] = *(uint32_t*)&head[BFHS+8]; *(uint32_t*)&head[BFHS+8]= temp; rbm.write(head, BFHS+BIHS); // read pixel values bmp.read(rgb, 3*W*H); char zero[3] = {0}; for (int y=0; y<W; ++y) { for (int x=0; x<H; ++x) { // rbm (x,y) is original bmp (y,H-1-x) rbm.write(&rgb[(H - x - 1) * W * 3 + y * 3], 3); } rbm.write(zero,2); // align on 32 bit boundary } }
Rotating a matrix by 90 degree is done by the following transformation of zero-based indices:A = N x M original matrix B = M x N transformed matrix (i.e. rotated by +90 degree) A[i,j] -> B[M-j-1,i]So, you read the data into the original matrix in memory, create a transformation matrix in memory, and do transform the original cells into the transformed matrix. Finally, write the data from memory to the file (with the appropriate header and padding bytes).
Cheers
Andi
PS: Note that each row in the bit map file is padded to a multiple of 4 bytes!
If you are writing code for windows you can use .Net library to help you:
Rotate image[^] then it will work for any image.
As already mentioned it is not good to use hard-coded values, they should be parameters to your method.
Also using a Hex Editor can help you see what the file really looks like.
这篇关于使用C ++将bmp照片旋转90度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!