BMP图像文件旋转作业

合集下载

电脑旋转图像怎么操作方法

电脑旋转图像怎么操作方法

电脑旋转图像怎么操作方法
电脑上旋转图像的操作方法有多种,具体操作方法如下:
1. 使用Windows自带的照片查看器:
- 打开要旋转的图像文件。

- 在照片查看器中,点击“编辑”按钮。

- 在下拉菜单中选择“旋转向左”或“旋转向右”选项,旋转图像到所需的方向。

- 如果需要,点击“另存为”按钮保存旋转后的图像。

2. 使用图像编辑软件:
- 打开图像编辑软件,如Adobe Photoshop、GIMP等。

- 导入要旋转的图像文件。

- 在软件的菜单或工具栏中,找到“旋转”或“转换”选项。

- 选择旋转的方向和角度,点击应用或确认按钮。

- 如果需要,保存旋转后的图像。

3. 使用在线图像编辑工具:
- 打开一个在线图像编辑网站,如Fotor、Pixlr等。

- 上传要旋转的图像文件或直接将图像拖放到编辑界面。

- 在工具栏中找到“旋转”选项。

- 选择旋转的方向和角度,点击应用或确认按钮。

- 如果需要,保存旋转后的图像到本地。

无论使用哪种方法,记得在旋转图像前,最好先备份原始图像,以防意外情况发生。

图像旋转与翻转的技巧与应用

图像旋转与翻转的技巧与应用

图像旋转与翻转的技巧与应用图像旋转和翻转是PhotoShop软件中常用的功能之一,它可以对图像进行各种角度的旋转和翻转处理,从而达到不同的效果和表达方式。

在本篇文章中,我将向大家介绍一些图像旋转和翻转的技巧和应用。

首先,我们先来了解一下图像旋转的基本操作。

在打开PhotoShop软件后,选择需要处理的图像,然后在菜单栏中选择"编辑"-"转换"-"旋转",或者使用快捷键Ctrl+T来调出图像旋转工具。

调出工具后,可以看到图像上出现一个矩形框,矩形框的边缘上有一些小方块,分别代表矩形框的四个角和中心点。

要旋转图像,只需将鼠标移至矩形框外围的小方块上,鼠标变成一个弯曲的双向箭头后,点击并拖动即可实现图像的旋转。

如果只想旋转图像的一部分,可以点击并拖动矩形框的边缘或角,来调整矩形框的大小和形状,然后再进行旋转操作即可。

图像的翻转操作也非常简单。

在同样的菜单栏中选择"编辑"-"转换"-"翻转",或者使用快捷键Ctrl+T,然后右键点击图像,在弹出的菜单中选择"转换"-"翻转水平"或"翻转垂直"即可实现图像的水平或垂直翻转。

除了基本操作外,PhotoShop软件还提供了一些高级的图像旋转和翻转技巧和应用。

其中之一是图像的任意角度旋转。

在基本操作中,我们只能通过鼠标拖动来实现图像的旋转,而无法准确地控制旋转的角度。

但在PhotoShop中,我们可以使用"自定义旋转"工具来实现任意角度的旋转。

使用"自定义旋转"工具的方法如下:打开PhotoShop软件,并选择需要处理的图像,然后在菜单栏中选择"编辑"-"自定义旋转",或者使用快捷键Ctrl+Alt+Shift+T来调出自定义旋转工具。

图像旋转原理

图像旋转原理

图像旋转原理
图像旋转是一种改变图像方向或角度的操作。

在旋转过程中,图像中的每个像素都会根据指定的角度和旋转中心进行位置调整。

旋转的原理可以通过以下步骤来实现:
1. 确定旋转中心:选择一个点作为旋转中心,通常是图像的中心点或者用户指定的某个点。

2. 计算旋转角度:根据用户的要求或者预设的旋转角度,确定图像需要旋转的角度。

3. 构建旋转矩阵:根据旋转中心和旋转角度,构建一个旋转矩阵。

旋转矩阵可以表示图像平面上所有点的旋转变换。

4. 应用旋转变换:对图像中的每个像素点,根据旋转矩阵进行坐标变换,将原始坐标映射到旋转后的位置上。

5. 边界处理:由于旋转后的图像可能会超出原始图像的边界,需要进行边界处理。

常见的处理方式包括扩展边界、裁剪边界或者使用插值方法填充边界。

通过以上步骤,就可以实现图像的旋转操作。

旋转可以实现任意角度的变换,可以用于图像校正、角度调整、图像合成等应用场景中。

如何使用图像处理技术实现图像旋转

如何使用图像处理技术实现图像旋转

如何使用图像处理技术实现图像旋转图像旋转是图像处理的常见操作之一,它可以改变图像的方向和角度,给图像带来丰富的变化和美感。

在本文中,我们将探讨如何使用图像处理技术实现图像旋转。

图像旋转的基本原理是通过对图像中的像素点进行旋转变换来实现。

旋转变换可以通过应用旋转矩阵来实现,旋转矩阵的计算需要用到旋转角度和旋转中心点。

我们需要确定旋转角度和旋转中心点。

旋转角度可以是任意值,通常以正值表示顺时针旋转,负值表示逆时针旋转。

旋转中心点是旋转操作的中心位置,可以是图像的中心点或者任意其他位置。

接下来,我们需要从图像中获取像素点,并根据旋转变换进行计算。

通过遍历每个像素点,我们可以得到该像素点在旋转后图像中的位置。

旋转变换的计算可以使用以下公式:x' = (x - cx) * cosθ - (y - cy) * sinθ + cxy' = (x - cx) * sinθ + (y - cy) * cosθ + cy其中,(x, y)是原图像中像素点的坐标,(x', y')是旋转后图像中像素点的坐标,(cx, cy)是旋转中心的坐标,θ是旋转角度。

公式中的sin和cos函数可以使用数学库提供的函数进行计算。

在旋转过程中,我们需要注意处理边界点的问题。

由于旋转会改变图像的大小,某些像素点可能超出图像的范围。

为了避免出现超出范围的问题,我们可以采用插值算法来填充缺失的像素点。

常见的插值算法包括最近邻插值法、双线性插值法和双三次插值法等。

我们需要将计算得到的新像素点的值填充到旋转后的图像中。

可以通过创建一个新的图像矩阵来存储旋转后的图像,并根据计算得到的坐标将像素值写入新图像中。

综上所述,我们可以使用图像处理技术实现图像旋转。

通过确定旋转角度和旋转中心点,应用旋转变换公式,处理边界点并进行插值,最终将计算得到的像素值填充到旋转后的图像中。

通过这些步骤,我们可以实现对图像旋转的操作。

图像旋转在很多领域都有广泛的应用,比如图像编辑、计算机视觉和机器人等。

实现bmp位图读取-显示-旋转的代码

实现bmp位图读取-显示-旋转的代码

实现bmp位图读取-显示-旋转的代码在视图类中定义以下两个方法:方法一:void RedFile();方法二:void RotateAnyAngle(HDC dcSrc,int SrcWidth,int SrcHeight,double angle,HDC hDC);代码的实现如下:void CTopView::RedFile(){/***************************读取信息********************************/LPCTSTR lpszFileName="f:\\b.bmp"; //文件路径CFile file; //用于读取BMP文件BITMAPFILEHEADER bfhHeader; //bmp文件头BITMAPINFOHEADER bmiHeader; //bmp格式头LPBITMAPINFO lpBitmapInfo; //bmp格式具体信息int bmpWidth=0; //图片宽度int bmpHeight = 0; //图片高度if(!file.Open(lpszFileName,CFile::modeRead))return ; //打开文件//读取文件头file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));if(bfhHeader.bfType!=((WORD) ('M'<<8)|'B')) //判断是否是"BM"return ;if(bfhHeader.bfSize!=file.GetLength())return ;//读取位图信息if (file.Read((LPSTR)&bmiHeader, sizeof(bmiHeader)) != sizeof(bmiHeader)) return ;bmpHeight = bmiHeader.biHeight; //得到高度和宽度bmpWidth = bmiHeader.biWidth;file.SeekToBegin(); //指针移动到文件的开头file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));UINT uBmpInfoLen=(UINT) bfhHeader.bfOffBits-sizeof(BITMAPFILEHEADER);//File SizelpBitmapInfo=(LPBITMAPINFO) new BYTE[uBmpInfoLen]; //具体信息分配内存file.Read((LPVOID) lpBitmapInfo,uBmpInfoLen);if((* (LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))return ;DWORD dwBitlen=bfhHeader.bfSize - bfhHeader.bfOffBits;//图像数据的字节大小 LPVOID lpSrcBits=new BYTE[dwBitlen]; //将数据读入lpSrcBits数组file.ReadHuge(lpSrcBits,dwBitlen);file.Close(); //关闭文件/*****************************显示图片***********************************/CClientDC hDC(this);StretchDIBits(hDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);/*************************将图片加入内存设备环境*************************************/HDC dcSrc;HBITMAP bitmap;dcSrc=CreateCompatibleDC(hDC);//得到一个内存设备环境bitmap = CreateCompatibleBitmap(hDC,bmpWidth,bmpHeight);SelectObject(dcSrc,bitmap);BitBlt(dcSrc,0,0,bmpWidth,bmpHeight,hDC,0,0,SRCCOPY);//这一步很重要/***********************************旋转*********************************************///调用旋转函数double angle = (45/180.0)*3.14159;//旋转45Degree,可为任意角度RotateAnyAngle(dcSrc,bmpWidth,bmpHeight,angle,hDC);}/*参数解释如下:///////////////////////////////////////////////////////////////////////////// HDC dcSrc:要旋转的位图的内存设备环境,就是第四步创建的int SrcWidth:要旋转位图的宽度int SrcHeight:要旋转位图的高度double angle:所要旋转的角度,以弧度为单位HDC pDC:第三步得到的当前屏幕设备环境void RotateBitmap(HDC dcSrc,int SrcWidth,int SrcHeight,double angle,HDC pDC);*/////////////////////////////////////////////////////////////////////////////// ////////////////////////void CTopView::RotateAnyAngle(HDC dcSrc,int SrcWidth,int SrcHeight,double angle,HDC hDC){double x1,x2,x3;double y1,y2,y3;double maxWidth,maxHeight,minWidth,minHeight;double srcX,srcY;double sinA,cosA;double DstWidth;double DstHeight;HDC dcDst;//旋转后的内存设备环境HBITMAP newBitmap;sinA = sin(angle);cosA = cos(angle);x1 = -SrcHeight * sinA;y1 = SrcHeight * cosA;x2 = SrcWidth * cosA - SrcHeight * sinA;y2 = SrcHeight * cosA + SrcWidth * sinA;x3 = SrcWidth * cosA;y3 = SrcWidth * sinA;minWidth = x3>(x1>x2?x2:x1)?(x1>x2?x2:x1):x3;minWidth = minWidth>0?0:minWidth;minHeight = y3>(y1>y2?y2:y1)?(y1>y2?y2:y1):y3;minHeight = minHeight>0?0:minHeight;maxWidth = x3>(x1>x2?x1:x2)?x3:(x1>x2?x1:x2);maxWidth = maxWidth>0?maxWidth:0;maxHeight = y3>(y1>y2?y1:y2)?y3:(y1>y2?y1:y2);maxHeight = maxHeight>0?maxHeight:0;DstWidth = maxWidth - minWidth;DstHeight = maxHeight - minHeight;dcDst = CreateCompatibleDC(dcSrc);newBitmap = CreateCompatibleBitmap(dcSrc,(int)DstWidth,(int)DstHeight); SelectObject(dcDst,newBitmap);for( int I = 0 ;I<DstHeight;I++){for(int J = 0 ;J< DstWidth;J++){srcX = (J + minWidth) * cosA + (I + minHeight) * sinA;srcY = (I + minHeight) * cosA - (J + minWidth) * sinA;if( (srcX >= 0) && (srcX <= SrcWidth) &&(srcY >= 0) && (srcY <= SrcHeight)) {BitBlt(dcDst, J, I, 1, 1, dcSrc,(int)srcX, (int)srcY, SRCCOPY);}}}//显示旋转后的位图BitBlt(hDC,150,10,(int)DstWidth,(int)DstHeight,dcDst,0,0,SRCCOPY);DeleteObject(newBitmap);DeleteDC(dcDst);。

如何利用Adobe Photoshop软件实现图片移动和旋转操作

如何利用Adobe Photoshop软件实现图片移动和旋转操作

如何利用Adobe Photoshop软件实现图片移动和旋转操作在当今的数字时代,图像编辑软件已经成为我们日常生活中必不可少的工具之一。

而Adobe Photoshop作为业界最受欢迎的图像编辑软件,其功能和操作性也得到了广大用户的认可。

在谈到图像编辑中最基本的操作之一——图片移动和旋转时,Adobe Photoshop的实用性和灵活性再次体现出来。

本文将介绍如何在Adobe Photoshop软件中利用简单的操作实现图片的移动和旋转。

在开始具体操作之前,我们需要先确保已经安装了Adobe Photoshop软件,并且已打开需要编辑的图像。

移动图片操作是最基本且简单的操作之一,主要是通过鼠标或触摸板控制图片在画布上的移动。

首先,选择“移动工具”选项。

这个工具位于工具栏的左侧,图标形状类似于一个十字架加一个箭头。

在点击选中该工具后,我们可以通过鼠标左键点击并拖动图像来实现图片的移动。

在移动过程中,鼠标左键不松开可以调整图片的位置,这样我们就可以根据需要精确地将图像移动到目标位置。

旋转图片操作可以为图片添加更多的动态效果。

与图片移动类似,旋转图片操作也需要先选中“旋转工具”选项。

这个工具的图标位于“移动工具”旁边,形状为一个弧形的箭头。

选中该工具后,我们可以将鼠标光标放在需要旋转的图片上,然后按住鼠标左键并同时移动鼠标,即可实现图片的旋转。

在旋转过程中,鼠标光标的位置与图片的中心点有关,可以根据需要调整鼠标光标的位置来实现不同效果的旋转。

同时,按住Shift键(或者Option键)可以进行等比例调整和自由旋转操作。

除了基本的移动和旋转操作,Adobe Photoshop还提供了一些高级的功能和效果,可以让我们在编辑过程中实现更多的创意和变化。

比如说,我们可以利用“自动内容感应移动”功能来智能地填补或复制移动过程中出现的空白部分。

这个功能可以通过选中“编辑”菜单,然后选择“自动内容感应移动”来进行操作。

delphi实现.bmp位图旋转90度。急求!!!

delphi实现.bmp位图旋转90度。急求!!!

delphi 实现.bmp 位图旋转90度。

急求•小白求助大神们,请问怎么在delphi 中实现位图的旋转啊,比如说打开一幅.bmp 的图片(用系统自带的画图工具就行),然后旋转90度(顺时针逆时针都行),然后保存并输出来。

比如说就像这样,点击图像按钮显示原图,点击旋转按钮后图像旋转并在上面显示注意:你要设置Timage 的Strech 属性为True ,AutoSize 不要设置为True ,否则转换的过程会非常慢。

旋转JPG 图像,必须要把JPG 转换成BMP 图像,所以我自定义了一个函数jptpbmp()Delphi/Pascal code?1 2 3 4 5 6 7 8 9 10 Function TForm1.jptobmp(jpg:Tjpegimage):Tbitmap;beginresult:=nil;if Assigned(jpg) thenbeginresult:=Tbitmap.Create;jpg.DIBNeeded;result.Assign(jpg);end;end;然后放置了4个按钮,左转,右转,水平和垂直,代码为Delphi/Pascal code?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 //左转procedure TForm1.Button1Click(Sender: TObject);vari,j:integer;Myimage:Tbitmap;beginMyimage:=Tbitmap.Create;Myimage.Assign(jptobmp(Tjpegimage(image1.Picture.Graphic))); image1.Picture.Bitmap.Height:=Myimage.Width;image1.Picture.Bitmap.Width:=Myimage.Height;image1.Picture.CleanupInstance;for i := 0 to Myimage.Height dofor j := 0 to Myimage.Width doimage1.Canvas.Pixels[i,(-j+Myimage.Width)]:=Myimage.Canvas.Pixels[j,i];Myimage.Freeend;//右转procedure TForm1.Button2Click(Sender: TObject);vari,j:integer;Myimage:Tbitmap;beginMyimage:=Tbitmap.Create;Myimage.Assign(jptobmp(Tjpegimage(image1.Picture.Graphic))); image1.Picture.Bitmap.Height:=Myimage.Width;image1.Picture.Bitmap.Width:=Myimage.Height;image1.Picture.CleanupInstance;for i := 0 to Myimage.Height dofor j := 0 to Myimage.Width doimage1.Canvas.Pixels[(-i+Myimage.Height),j]:=Myimage.Canvas.Pixels[j,i];Myimage.Freeend;//水平procedure TForm1.Button3Click(Sender: TObject);vari,j:integer;Myimage:Tbitmap;beginMyimage:=Tbitmap.Create;44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 Myimage.Assign(jptobmp(Tjpegimage(image1.Picture.Graphic))); image1.Picture.Bitmap.Height:=Myimage.Height;image1.Picture.Bitmap.Width:=Myimage.Width;image1.Picture.CleanupInstance;for i := 0 to Myimage.Height dofor j := 0 to Myimage.Width doimage1.Canvas.Pixels[(-j+Myimage.Width),i]:=Myimage.Canvas.Pixels[j,i];Myimage.Freeend;//垂直procedure TForm1.Button4Click(Sender: TObject);vari,j:integer;Myimage:Tbitmap;beginMyimage:=Tbitmap.Create;Myimage.Assign(jptobmp(Tjpegimage(image1.Picture.Graphic))); image1.Picture.Bitmap.Height:=Myimage.Height;image1.Picture.Bitmap.Width:=Myimage.Width;image1.Picture.CleanupInstance;for i := 0 to Myimage.Height dofor j := 0 to Myimage.Width doimage1.Canvas.Pixels[j,(-i+Myimage.Height)]:=Myimage.Canvas.Pixels[j,i];Myimage.Freeend;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 顺时针90度procedure TSeleteImageFrm.Button4Click(Sender: TObject); var i,j:integer;k,all:Longint;im:Tbitmap;beginGaugeFrm.show;GaugeFrm.Caption:='处理数据......';GaugeFrm.Gauge1.Progress:=0;im:=Tbitmap.Create;im.Assign(jpbmp(Tjpegimage(image1.Picture.Graphic))); //确定旋转后位图的大小image1.Picture.Bitmap.Height:=im.Width;image1.Picture.Bitmap.Width:=im.Height;image2.Picture.Bitmap.Height:=im.Width;1617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 image2.Picture.Bitmap.Width:=im.Height;image1.Picture.CleanupInstance; //清除图象image2.Picture.CleanupInstance; //清除图象K:=0;all:=Trunc(im.Height*im.Width);for i:=0 to im.Height dofor j:=0 to im.Width dobeginK:=K+1;GaugeFrm.Gauge1.Progress:=Trunc(100*K/all);image1.Canvas.Pixels[(-i+im.Height),j]:=im.Canvas.Pixels[j,i];image2.Canvas.Pixels[(-i+im.Height),j]:=im.Canvas.Pixels[j,i];end;im.Free;ChangeImageSize;GaugeFrm.close;end;反时针90度procedure TSeleteImageFrm.Button6Click(Sender: TObject); var i,j:integer;k,all:Longint;im:Tbitmap;beginGaugeFrm.show;GaugeFrm.Caption:='处理数据......';GaugeFrm.Gauge1.Progress:=0;im:=Tbitmap.Create;im.Assign(jpbmp(Tjpegimage(image1.Picture.Graphic))); //确定旋转后位图的大小image1.Picture.Bitmap.Height:=im.Width;image1.Picture.Bitmap.Width:=im.Height;image2.Picture.Bitmap.Height:=im.Width;image2.Picture.Bitmap.Width:=im.Height;image1.Picture.CleanupInstance; //清除图象image2.Picture.CleanupInstance; //清除图象K:=0;all:=Trunc(im.Height*im.Width);for i:=0 to im.Height dofor j:=0 to im.Width dobeginK:=K+1;60 61 62 63 64 65 GaugeFrm.Gauge1.Progress:=Trunc(100*K/all);image1.Canvas.Pixels[i,(-j+im.Width)]:=im.Canvas.Pixels[j,i];image2.Canvas.Pixels[i,(-J+im.Width)]:=im.Canvas.Pixels[j,i];end;im.Free;ChangeImageSize;GaugeFrm.close;end;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 procedure TSeleteImageFrm.Button7Click(Sender: TObject);var i,j:integer;k,all:Longint;im:Tbitmap;beginGaugeFrm.show;GaugeFrm.Caption:='处理数据......';GaugeFrm.Gauge1.Progress:=0;im:=Tbitmap.Create;im.Assign(jpbmp(Tjpegimage(image1.Picture.Graphic))); //确定旋转后位图的大小image1.Picture.Bitmap.Height:=im.Height;image1.Picture.Bitmap.Width:=im.Width;image2.Picture.Bitmap.Height:=im.Height;image2.Picture.Bitmap.Width:=im.Width;image1.Picture.CleanupInstance; //清除图象image2.Picture.CleanupInstance; //清除图象K:=0;all:=Trunc(im.Height*im.Width);for i:=0 to im.Width dofor j:=0 to im.Height dobeginK:=K+1;GaugeFrm.Gauge1.Progress:=Trunc(100*K/all);image1.Canvas.Pixels[(im.Width-i),(im.Height-j)]:=im.Canvas.Pixels[i,j];image2.Canvas.Pixels[(im.Width-i),(im.Height-j)]:=im.Canvas.Pixels[i,j];end;im.Free;ChangeImageSize;GaugeFrm.close;end;1 procedure TSeleteImageFrm.Button13Click(Sender: TObject);2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 var i,j:integer;k,all:Longint;im:Tbitmap;beginGaugeFrm.show;GaugeFrm.Caption:='处理数据......';GaugeFrm.Gauge1.Progress:=0;im:=Tbitmap.Create;im.Assign(jpbmp(Tjpegimage(image1.Picture.Graphic))); //确定旋转后位图的大小image1.Picture.Bitmap.Height:=im.Height;image1.Picture.Bitmap.Width:=im.Width;image2.Picture.Bitmap.Height:=im.Height;image2.Picture.Bitmap.Width:=im.Width;image1.Picture.CleanupInstance; //清除图象image2.Picture.CleanupInstance; //清除图象K:=0;all:=Trunc(im.Height*im.Width);for i:=0 to im.Height dofor j:=0 to im.Width dobeginK:=K+1;GaugeFrm.Gauge1.Progress:=Trunc(100*K/all);image1.Canvas.Pixels[(-j+im.Width),(i)]:=im.Canvas.Pixels[j,i];image2.Canvas.Pixels[(-J+im.Width),(i)]:=im.Canvas.Pixels[j,i];end;im.Free;ChangeImageSize;GaugeFrm.close;end;有此代码是显示进度条的,可以删除。

bmp翻转旋转放大缩小

bmp翻转旋转放大缩小

bmp文件由三部分组成:文件头,位图信息头,RGB像素数据。

拿24位bmp图片举例,读取文件fread就可以,开始读取sizeof(BITMAPFILEHEADER)长的数据,再读取sizeof(BITMAPINFOHEADER)长的数据,里面有位图的原始高度和宽,然后读取(3*原始宽度*原始高度)长的原始RGB数据到内存,这样对那块数据操作,就能实现旋转,翻转,放大缩小操作了,关键是写出原始宽度、原始高度、原始RGB数据和变换后的宽度、高度、RGB数据的关系,对于24位的图片一个像素占3个字节,举例如下90度旋转:原始RGB数据块5*3 旋转90度旋转RGB数据块3*51 2 3 4 5 11 6 16 7 8 9 10 12 7 211 12 13 14 15 13 8 314 9 415 10 5原始数据在pBuf中旋转后的数据pNewBufpBuf转到pNewBuf中for(int i=0;i<3;i++) //3原始高度{for(int j=0;j<5;j++) //5原始宽度{for(int K = 0;K<3;K++) //每个像素占三个字节{*(pNewBuf + j*5*3+(3 - i- 1)*3+k) = *(pBuf + i*3*5 + j*3 +K) ; //关键是这个算法}}}保存旋转后的图片注意高和宽交换了。

原始RGB数据块5*3 翻转180 旋转RGB数据块 5*31 2 3 4 5 11 12 13 14 156 7 8 9 10 6 7 8 9 1011 12 13 14 15 1 2 3 4 5pBuf转到pNewBuf中for(int i=0;i<3;i++) //3原始高度{for(int j=0;j<5;j++) //5原始宽度{for(int K = 0;K<3;K++) //每个像素占三个字节{*(pNewBuf +(3-i-1)*3*5 + j*3 +K ) = *(pBuf + i*3*5 + j*3 + K) ; //关键是这个算法}}}对于放大和缩小也是对数据块的转换下篇继续!。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

作业要求:将24位或32位真彩色 .bmp 图像文件,顺时针旋转90度。

可执行程序名:rotatebmp用法:rotatebmp src.bmp dest.bmp (文件名可变)生成的dest.bmp是从src.bmp 顺时针旋转90度得到的。

注意事项:C++编译有“结构边界对齐”的概念:struct A {int a;char c;};那么sizeof(A)未必是5,很有可能是8,因为C++编译器为了提高代码执行效率,往往在生成结构变量的时候,自动将其大小调整为4的整数倍,或8的整数倍。

程序员可以在编译选项中指定对齐的方式是1字节,2字节,4字节或8字节(即每个结构变量的大小一定是1的倍数,2的倍数,4的倍数,8的倍数),也可以在程序开头直接用:#pragma pack(2)指定对齐边界是2字节,或1字节,4字节….参考阅读:BMP图像文件格式1BMP是bitmap的缩写形式,bitmap顾名思义,就是位图也即Windows位图。

它一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区组成。

在系统中以BMP为扩展名保存。

打开Windows的画图程序,在保存图像时,可以看到三个选项:2色位图(黑白)、16色位图、256色位图和24位位图。

这是最普通的生成位图的工具,在这里讲解的BMP位图形式,主要就是指用画图生成的位图(当然,也可以用其它工具软件生成)。

现在讲解BMP的4个组成部分:1.文件头信息块0000-0001:文件标识,为字母ASCII码“BM”。

0002-0005:文件大小。

0006-0009:保留,每字节以“00”填写。

000A-000D:记录图像数据区的起始位置。

各字节的信息依次含义为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。

2.图像描述信息块000E-0011:图像描述信息块的大小,常为28H。

0012-0015:图像宽度。

0016-0019:图像高度。

001A-001B:图像的plane总数(恒为1)。

001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。

001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。

0022-0025:图像区数据的大小。

0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H 填写。

002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H 填写。

002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。

3.颜色表颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。

其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(像素的透明度值,一般不需要)。

即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。

4.图像数据区颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。

所以,整个数据区的大小也会随之变化。

究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。

然而,未压缩的图像信息区的大小。

除了真彩色模式外,其余的均大于或等于数据信息的大小。

这是为什么呢?原因有两个:1.BMP文件记录一行图像是以字节为单位的。

因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。

也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。

接下来的一个字节将开始记录下一行的信息。

2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。

如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。

如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。

还有一点我要申明,当屏幕初始化为16或256色模式时,一定要设置调色板或修正颜色值,否则无法得到正确的图像颜色。

BMP图像文件格式2对于现存的所有的图像文件格式,我们在这里主要介绍BMP图像文件格式,并且文件里的图像数据是未压缩的,因为图像的数字化处理主要是对图像中的各个像素进行相应的处理,而未压缩的BMP图像中的像素数值正好与实际要处理的数字图像相对应,这种格式的文件最合适我们对之进行数字化处理。

请读者记住,压缩过的图像是无法直接进行数字化处理的,如JPEG、GIF等格式的文件,此时首先要对图像文件解压缩,这就要涉及到一些比较复杂的压缩算法。

后续章节中我们将针对特殊的文件格式如何转换为BMP格式的文件问题作专门的论述,经过转换,我们就可以利用得到的未压缩的BMP文件格式进行后续处理。

对于JPEG、GIF等格式,由于涉及到压缩算法,这要求读者掌握一定的信息论方面的知识,如果展开的话,可以写一本书,限于篇幅原因,我们只作一般性的讲解,有兴趣的朋友可以参考相关书籍资料。

一、BMP文件结构1. BMP文件组成BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息;位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。

颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。

文件中的数据块表示图像的相应的像素值,需要注意的是:图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的;另外一个需要读者朋友关注的细节是:文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,否则,需要在后端补0,凑足4的倍数。

2. BMP文件头BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

其结构定义如下: typede f struct tagBITMAPFILEHEADER{WORD bfType; // 位图文件的类型,必须为“BM”DWORD bfSize; // 位图文件的大小,以字节为单位WORD bfReserved1; // 位图文件保留字,必须为0WORD bfReserved2; // 位图文件保留字,必须为0DWORD bfOffBits; // 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位} BITMAPFILEHEADER;该结构占据14个字节。

3. 位图信息头BMP位图信息头数据用于说明位图的尺寸等信息。

其结构如下:typedef struct tagBITMAPINFOHEADER{DWORD biSize; // 本结构所占用字节数LONG biWidth; // 位图的宽度,以像素为单位LONG biHeight; // 位图的高度,以像素为单位WORD biPlanes; // 目标设备的平面数不清,必须为1WORD biBitCount// 每个像素所需的位数,必须是1(双色), 4(16色),8(256色)或24(真彩色)之一DWORD biCompression; // 位图压缩类型,必须是0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一DWORD biSizeImage; // 位图的大小,以字节为单位LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数DWORD biClrImportant;// 位图显示过程中重要的颜色数} BITMAPINFOHEADER;该结构占据40个字节。

注意:对于BMP文件格式,在处理单色图像和真彩色图像的时候,无论图象数据多么庞大,都不对图象数据进行任何压缩处理,一般情况下,如果位图采用压缩格式,那么16色图像采用RLE4压缩算法,256色图像采用RLE8压缩算法。

4. 颜色表颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。

RGBQUAD结构的定义如下:typedef struct tagRGBQUAD {BYTErgbBlue;// 蓝色的亮度(值范围为0-255)BYTErgbGreen; // 绿色的亮度(值范围为0-255)BYTErgbRed; // 红色的亮度(值范围为0-255)BYTErgbReserved;// 保留,必须为0} RGBQUAD;颜色表中RGBQUAD结构数据的个数由BITMAPINFOHEADER 中的biBitCount项来确定,当biBitCo unt=1,4,8时,分别有2,16,256个颜色表项,当biBitCount=24时,图像为真彩色,图像中每个像素的颜色用三个字节表示,分别对应R、G、B值,图像文件没有颜色表项。

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:typedef struct tagBITMAPINFO {BITMAPINFOHEADER bmiHeader; // 位图信息头RGBQUAD bmiColors[1]; // 颜色表} BITMAPINFO;注意:RGBQUAD数据结构中,增加了一个保留字段rgbReserved,它不代表任何颜色,必须取固定的值为“0”,同时,RGBQUAD结构中定义的颜色值中,红色、绿色和蓝色的排列顺序与一般真彩色图像文件的颜色数据排列顺序恰好相反,既:若某个位图中的一个像素点的颜色的描述为“00,00,ff,00”,则表示该点为红色,而不是蓝色。

5. 位图数据位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值,图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。

这种格式我们又称为Bottom_Up位图,当然与之相对的还有Up_Down 形式的位图,它的记录顺序是从上到下的,对于这种形式的位图,也不存在压缩形式。

相关文档
最新文档