Кафедра Вычислительной Техники СПбГУ ИТМО

Лабораторная Работа №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

Соседние файлы в папке лабораторные работы (отчеты) по ассемблеру