

Кафедра Вычислительной Техники СПбГУ ИТМО
Лабораторная Работа №3 «Отражение изображения»
Выполнил: Раевский С.С. гр. 2103
- Санкт-Петербург 2011 –
Раевский Сергей Сергеевич, группа 2103 |
1 |

Кафедра Вычислительной Техники СПбГУ ИТМО
Цель работы:
∙Изучить формат растровых изображений BMP и написать программу отражения растров с использванием уже полученных в предыдущей работе знаний.
∙Сравнить эффективность использования различных средств (for(;;), movsd, MMX)
Исходный текст программы на языке C:
// BMPFiles.h
#ifndef _BMPFiles_h_ #define _BMPFiles_h_
//
//Small header to provide simple BMP I/O
//So, be careful! This functions are not 100% compatible \w
//all BMP file formats (e.g. 8-4-2-1 bpp)
//The only one format, that supported really good is 24 bpp.
//Enjoy! (C) C.c, Feb 2011
//
#include "Typedef.h"
#include "stdafx.h" #include <fstream> #include <sys/stat.h> #include <malloc.h>
using namespace std;
//Disabling an alignment #pragma pack(push, 1)
//BMP File header structure struct BMPHeader
{
//Raster header part WORD Sign;
DWORD Size;
WORD Reserved1; WORD Reserved2;
DWORD OffBits;
// BMP Info part DWORD HeaderSize; LONG Width;
Раевский Сергей Сергеевич, группа 2103 |
2 |

|
Кафедра Вычислительной Техники СПбГУ ИТМО |
|
|
LONG |
Height; |
WORD |
Planes; |
WORD |
BitCount; |
DWORD |
Compression; |
DWORD |
ImageSize; |
LONG |
XPelsPerMeter; |
LONG |
YPelsPerMeter; |
DWORD |
ClrUsed; |
DWORD |
ClrImportant; |
};
// RGB 24-bit Pixel format struct RGBTriple
{
byte r, g, b;
};
#pragma pack(pop)
// BMP File, C.O. struct BMPFile
{
BMPHeader Header; // |
Header |
|
BYTE *Image; |
// |
Image bytes |
};
// Reads header from bitmap file
bool BMP_ReadHeader(char *InputFile, BMPHeader *Header)
{
// Creating file stream
ifstream BMPFile(InputFile, std::ios::in | std::ios::binary);
if (!BMPFile.is_open())
{
printf ("BMP_ReadHeader(): File not found!\n"); return false;
}
BMPFile.read((char*)Header, sizeof(BMPHeader)); // Reading header BMPFile.close();
return true;
}
// Reads pixels from file
byte *BMP_ReadImage(char *InputFile, BMPHeader *Header)
{
Раевский Сергей Сергеевич, группа 2103 |
3 |

Кафедра Вычислительной Техники СПбГУ ИТМО
// Creating file stream
ifstream BMPFile(InputFile, std::ios::in | std::ios::binary);
//Seeking for beginning of pixels array BMPFile.seekg(Header->OffBits);
//Cause in my test BMP's fields filled
//incorrectly - I don't really know why.
//So, I can't use BMPHeader.ImageSize field :(
DWORD Size = (Header->Height*Header->Width*Header->BitCount) / 8;
// Allocating memory
byte *Image=(byte*)malloc(Size);
// Reading image BMPFile.read((char*)Image, Size); BMPFile.close();
return Image;
}
// Loads BMP file into the memory BMPFile *BMP_LoadBMP(char *InputFile)
{
BMPFile File;
// Trying to read file header
if (!BMP_ReadHeader(InputFile, &File.Header))
{
printf("BMP_LoadBMP(): Can't load %s!\n", InputFile); return NULL;
}
// Checking signature
if (File.Header.Sign!=0x4d42)
{
printf("BMP_LoadBMP(): Not an BMP file!\n"); return NULL;
}
// Reading pixels File.Image=BMP_ReadImage(InputFile, &File.Header);
BMPFile *pFile = new BMPFile; *pFile = File;
return pFile;
}
Раевский Сергей Сергеевич, группа 2103 |
4 |

Кафедра Вычислительной Техники СПбГУ ИТМО
// Writes BMP header
bool BMP_WriteHeader(char *OutputFile, BMPHeader *Header)
{
// Creating stream
ofstream BMPFile(OutputFile);
// Error?
if (!BMPFile.is_open())
{
printf ("BMP_WriteHeader(): Can't open for write!\n"); return false;
}
// Writing header
BMPFile.write((char*)Header, sizeof(BMPHeader));
BMPFile.close();
return true;
}
// Writes BMP pixels
void BMP_WriteImage(char *OutputFile, BMPHeader *Header, byte *Image)
{
// Creating stream
ofstream BMPFile(OutputFile, std::ios::out | std::ios::binary | std::ios::app);
// Seeking for beginning of pixels array BMPFile.seekp(Header->OffBits);
DWORD Size = (Header->Height*Header->Width*Header->BitCount) / 8;
// Writing pixels data BMPFile.write((char*)Image, Size); BMPFile.close();
}
// Saving BMP file to disk
bool BMP_SaveBMP(char *OutputFile, BMPFile *pFile)
{
// Trying to write file header
if (!BMP_WriteHeader(OutputFile, &pFile->Header))
{
printf("BMP_SaveBMP(): Can't save %s!\n", OutputFile); return false;
}
Раевский Сергей Сергеевич, группа 2103 |
5 |

Кафедра Вычислительной Техники СПбГУ ИТМО
// Writing pixels
BMP_WriteImage(OutputFile, &pFile->Header, pFile->Image);
return true;
}
BMPFile *BMP_Clone(BMPFile *Source)
{
// New BMP file struct BMPFile *Clone = new BMPFile;
BMPHeader *Header = &Source->Header;
DWORD Size = (Header->Height*Header->Width*Header->BitCount) / 8;
// Cloning image data Clone->Image=(byte*)malloc(Size); memcpy(Clone->Image, Source->Image, Size);
// Cloning header
Clone->Header = Source->Header;
return Clone;
}
void BMP_Free(BMPFile *pFile)
{
free(pFile->Image); free(pFile);
}
#endif
// Lab3.cpp
#include "stdafx.h"
#include <malloc.h> #include <windows.h> #include <stdio.h> #include <conio.h>
#include "Typedef.h" #include "BMPFiles.h"
// Times to repeat const int TIMES = 1001;
Раевский Сергей Сергеевич, группа 2103 |
6 |

Кафедра Вычислительной Техники СПбГУ ИТМО
void MirrorCPP(BMPFile *pFile)
{
int cW = (pFile->Header.Width*3) / 4; // Calculating line length in 4 byte blocks
DWORD Buf;
dword *_Image = (dword*)pFile->Image;
for (int i=0; i<(pFile->Header.Height / 2); i++)
{
for (int j=0; j<cW; j++)
{
// XChanging lines
Buf=_Image[i*cW + j];
_Image[i*cW + j]=_Image[(pFile->Header.Height-i-1)*cW
+ j];
_Image[(pFile->Header.Height-i-1)*cW + j]=Buf;
}
}
} |
|
|
void MirrorASM(BMPFile *pFile) |
|
|
{ |
|
|
dword *_Image = (dword*)pFile->Image; |
|
|
int |
Width = pFile->Header.Width; |
|
int |
Height = pFile->Header.Height; |
|
_asm |
|
|
{ |
|
|
mov |
esi, _Image |
|
mov |
eax, Width |
|
mov |
ebx, 3 |
|
mul |
ebx |
|
mov |
ebx, Height |
|
mul |
ebx |
|
add |
eax, _Image |
|
mov |
edi, eax |
|
mov |
eax, 0 |
|
mov |
eax, Height |
|
mov |
ebx, 2 |
|
div |
ebx |
|
mov |
ecx, eax |
|
Cycle1: |
|
|
mov |
eax, Width |
|
mov |
ebx, 3 |
|
mul |
ebx |
|
mov |
edx, eax |
|
Раевский Сергей Сергеевич, группа 2103 |
7 |

|
Кафедра Вычислительной Техники СПбГУ ИТМО |
|
|
sub |
edi, eax |
Cycle2: |
|
sub |
edx, 4 |
mov |
eax, [edi+edx] |
mov |
ebx, [esi+edx] |
mov |
[esi+edx], eax |
mov |
[edi+edx], ebx |
mov |
eax, edx |
jnz Cycle2 |
|
mov |
eax, Width |
mov |
ebx, 3 |
mul |
ebx |
add |
esi, eax |
loop Cycle1
}
}
void MirrorMMX(BMPFile *pFile)
{
dword *_Image = (dword*)pFile->Image; int Width = pFile->Header.Width;
int Height = pFile->Header.Height;
_asm |
|
{ |
|
mov |
esi, _Image |
mov |
eax, Width |
mov |
ebx, 3 |
mul |
ebx |
mov |
ebx, Height |
mul |
ebx |
add |
eax, _Image |
mov |
edi, eax |
mov |
eax, 0 |
mov |
eax, Height |
mov |
ebx, 2 |
div |
ebx |
mov |
ecx, eax |
Cycle1: |
|
mov |
eax, Width |
mov |
ebx, 3 |
mul |
ebx |
mov |
edx, eax |
sub |
edi, eax |
Cycle2: |
|
sub |
edx, 8 |
movq mm0, |
[edi+edx] |
|
movq mm1, |
[esi+edx] |
|
Раевский Сергей Сергеевич, группа 2103 |
8 |

Кафедра Вычислительной Техники СПбГУ ИТМО
movq [esi+edx], mm0 movq [edi+edx], mm1 mov eax, edx
and eax, 0xffffffff jnz Cycle2
mov eax, Width mov ebx, 3
mul ebx
add esi, eax loop Cycle1
}
}
// Calculating execution time for MethodDelegate
void CalcTime(char *MethodName, void (*MethodDelegate)(BMPFile *pFile), BMPFile *Source, char *OutputFile)
{
// Creating a copy into the memory BMPFile *Clone = BMP_Clone(Source);
printf("Mirroring image \\w \"%s\"... ", MethodName);
// Begin time
dword Ticks = GetTickCount();
// Doing it for many times
for (int i=0; i<TIMES; i++) MethodDelegate(Clone);
// End - Begin Ticks=GetTickCount()-Ticks;
printf("%d ticks.\n", Ticks);
// Saving and release from RAM BMP_SaveBMP(OutputFile, Clone); BMP_Free(Clone);
}
// FFFFFFFUUUUUUUUUUUUUUUUUUUU
void wtoc(char* Dest, const _TCHAR* Source)
{
while(*Source != '\0')
{
*Dest = (char)*Source; Source++;
Dest++;
}
Раевский Сергей Сергеевич, группа 2103 |
9 |

Кафедра Вычислительной Техники СПбГУ ИТМО
*Dest='\0';
}
// Output files names
char *OutputFileCPP = "test_c++.bmp"; char *OutputFileASM = "test_asm.bmp"; char *OutputFileMMX = "test_MMX.bmp";
// MAIN FUNCTION UHAHAHAHA
int _tmain(int argc, _TCHAR* argv[])
{
//wide char -> char char InputFile[256];
if (argv[1]) wtoc(InputFile, argv[1]);
//Loading source BMP file...
printf("Loading \"%s\"...\n\n", InputFile); BMPFile *bmpFile = BMP_LoadBMP(InputFile);
// can't load?
if (!bmpFile) return 1;
// non 24 bpp?
if (bmpFile->Header.BitCount!=24)
{
printf("Image must be 24 bpp\n"); BMP_Free(bmpFile);
return 1;
}
// CPP
CalcTime("MirrorCPP", MirrorCPP, bmpFile, OutputFileCPP);
// ASM
CalcTime("MirrorASM", MirrorASM, bmpFile, OutputFileASM);
// CPP
CalcTime("MirrorMMX", MirrorMMX, bmpFile, OutputFileMMX);
printf("\nAll done.\n");
// End system("pause"); return 0;
}
Раевский Сергей Сергеевич, группа 2103 |
10 |