Merge remote-tracking branch 'ECOAR/main' into main
136
ECOAR/C/asm_part.asm
Executable file
@ -0,0 +1,136 @@
|
||||
|
||||
|
||||
section .data
|
||||
|
||||
|
||||
|
||||
image_info_address EQU 8 ; First argument passed to our function starts from 8
|
||||
first_piece_address EQU 12 ; From that point we just add 4 to address of next
|
||||
; arguments
|
||||
piece_to_swap_with_address EQU 16
|
||||
horizontal_divisons_address EQU 20
|
||||
piece_width_address EQU 24
|
||||
piece_height_address EQU 28
|
||||
piece_width_bytes_address EQU 32
|
||||
piece_height_bytes_address EQU 36
|
||||
bytes_per_row_address EQU 40
|
||||
firstPieceStartingByte EQU 44
|
||||
secondPieceStartingByte EQU 48
|
||||
|
||||
|
||||
pImg_inside_image_info_address EQU 12
|
||||
|
||||
|
||||
image_width EQU 0
|
||||
image_height EQU 4
|
||||
bytes_per_row_inside_image_info_address EQU 8
|
||||
image_pImg EQU 12
|
||||
image_pHeaderInfo EQU 16 ; not really used
|
||||
|
||||
; first.X, first.Y, second.X, second.Y
|
||||
|
||||
|
||||
|
||||
%macro print 2 ;number of arguments this macro takes
|
||||
mov edx, %1 ;message length
|
||||
mov ecx, %2 ;message to write
|
||||
mov ebx,1 ;file descriptor (stdout)
|
||||
mov eax,4 ;system call number (sys_write)
|
||||
int 0x80 ;call kernel
|
||||
%endmacro
|
||||
|
||||
|
||||
|
||||
section .text
|
||||
global inner_loops ;must be declared for linker (ld)
|
||||
; extern void hello_world(imageInfo* pInfo, int firstPiece, int pieceToSwapWith,
|
||||
; int horizontalDivisions, int pieceWidth,
|
||||
; int pieceHeight);
|
||||
|
||||
; mov ecx, [ebp + 8] ; ecx <- address of imgInfo struct, not saved
|
||||
; mov eax, [ebp + 12] ; eax <- firstPiece, not saved
|
||||
; mov edx, [ebp + 16] ; edx <- pieceToSwapWith, not saved
|
||||
; mov esi, [ecx + image_pImg] ; esi <- start of pixels in picture, saved
|
||||
; mov ebx, [ebp + 20] ; ebx <- horizontalDivisions
|
||||
; mov edi, [ebp + 24] ; edi <- pieceWidth
|
||||
|
||||
inner_loops: ;tells linker entry point
|
||||
|
||||
push ebp ; as per calling convention we need to keep the values of
|
||||
; certain registers
|
||||
mov ebp,esp
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
; what we use:
|
||||
; ecx - firstPieceFirstByteAddress
|
||||
; edx - secondPieceFirstByteAddress
|
||||
; esi
|
||||
; edi
|
||||
|
||||
; what we have:
|
||||
; eax
|
||||
; ebx
|
||||
|
||||
push ebx
|
||||
push eax
|
||||
;mov eax, [ebp + firstPieceStartingByte]
|
||||
;mov eax, [eax + image_pImg]
|
||||
mov edi, 0
|
||||
|
||||
x_pixels_loop:
|
||||
cmp edi, [ebp + piece_width_bytes_address]
|
||||
;cmp edi, 300
|
||||
jge x_pixels_loop_end
|
||||
mov esi, 0
|
||||
|
||||
; ecx = secondPieceStartingByte
|
||||
; edx = firstPieceStartingByte
|
||||
; we still have eax and ebx
|
||||
;
|
||||
y_pixels_loop:
|
||||
cmp esi, [ebp + piece_height_bytes_address]
|
||||
;cmp esi, 96000
|
||||
jge y_pixels_loop_end
|
||||
mov ecx, [ebp + secondPieceStartingByte]
|
||||
mov eax, [ebp + firstPieceStartingByte]
|
||||
add ecx, edi
|
||||
add ecx, esi
|
||||
add eax, edi
|
||||
add eax, esi
|
||||
|
||||
mov BYTE bl, [eax]
|
||||
mov BYTE dl, [ecx]
|
||||
mov BYTE[ecx], bl
|
||||
mov BYTE[eax], dl
|
||||
|
||||
mov BYTE bl, [eax + 1]
|
||||
mov BYTE dl, [ecx + 1]
|
||||
mov BYTE[ecx + 1], bl
|
||||
mov BYTE[eax + 1], dl
|
||||
|
||||
mov BYTE bl, [eax + 2]
|
||||
mov BYTE dl, [ecx + 2]
|
||||
mov BYTE[ecx + 2], bl
|
||||
mov BYTE[eax + 2], dl
|
||||
|
||||
|
||||
|
||||
add esi, [ebp + bytes_per_row_address]
|
||||
jmp y_pixels_loop
|
||||
|
||||
|
||||
; for(x = 0; x < pieceWidth * 3; x += 3)
|
||||
y_pixels_loop_end:
|
||||
add edi, 3
|
||||
jmp x_pixels_loop
|
||||
|
||||
x_pixels_loop_end:
|
||||
|
||||
pop esi
|
||||
pop edi
|
||||
pop ebx
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
136
ECOAR/C/asm_part.lst
Normal file
@ -0,0 +1,136 @@
|
||||
1
|
||||
2
|
||||
3 section .data
|
||||
4
|
||||
5
|
||||
6
|
||||
7 image_info_address EQU 8 ; First argument passed to our function starts from 8
|
||||
8 first_piece_address EQU 12 ; From that point we just add 4 to address of next
|
||||
9 ; arguments
|
||||
10 piece_to_swap_with_address EQU 16
|
||||
11 horizontal_divisons_address EQU 20
|
||||
12 piece_width_address EQU 24
|
||||
13 piece_height_address EQU 28
|
||||
14 piece_width_bytes_address EQU 32
|
||||
15 piece_height_bytes_address EQU 36
|
||||
16 bytes_per_row_address EQU 40
|
||||
17 firstPieceStartingByte EQU 44
|
||||
18 secondPieceStartingByte EQU 48
|
||||
19
|
||||
20
|
||||
21 pImg_inside_image_info_address EQU 12
|
||||
22
|
||||
23
|
||||
24 image_width EQU 0
|
||||
25 image_height EQU 4
|
||||
26 bytes_per_row_inside_image_info_address EQU 8
|
||||
27 image_pImg EQU 12
|
||||
28 image_pHeaderInfo EQU 16 ; not really used
|
||||
29
|
||||
30 ; first.X, first.Y, second.X, second.Y
|
||||
31
|
||||
32
|
||||
33
|
||||
34 %macro print 2 ;number of arguments this macro takes
|
||||
35 mov edx, %1 ;message length
|
||||
36 mov ecx, %2 ;message to write
|
||||
37 mov ebx,1 ;file descriptor (stdout)
|
||||
38 mov eax,4 ;system call number (sys_write)
|
||||
39 int 0x80 ;call kernel
|
||||
40 %endmacro
|
||||
41
|
||||
42
|
||||
43
|
||||
44 section .text
|
||||
45 global inner_loops ;must be declared for linker (ld)
|
||||
46 ; extern void hello_world(imageInfo* pInfo, int firstPiece, int pieceToSwapWith,
|
||||
47 ; int horizontalDivisions, int pieceWidth,
|
||||
48 ; int pieceHeight);
|
||||
49
|
||||
50 ; mov ecx, [ebp + 8] ; ecx <- address of imgInfo struct, not saved
|
||||
51 ; mov eax, [ebp + 12] ; eax <- firstPiece, not saved
|
||||
52 ; mov edx, [ebp + 16] ; edx <- pieceToSwapWith, not saved
|
||||
53 ; mov esi, [ecx + image_pImg] ; esi <- start of pixels in picture, saved
|
||||
54 ; mov ebx, [ebp + 20] ; ebx <- horizontalDivisions
|
||||
55 ; mov edi, [ebp + 24] ; edi <- pieceWidth
|
||||
56
|
||||
57 inner_loops: ;tells linker entry point
|
||||
58
|
||||
59 00000000 55 push ebp ; as per calling convention we need to keep the values of
|
||||
60 ; certain registers
|
||||
61 00000001 89E5 mov ebp,esp
|
||||
62 00000003 53 push ebx
|
||||
63 00000004 56 push esi
|
||||
64 00000005 57 push edi
|
||||
65
|
||||
66 ; what we use:
|
||||
67 ; ecx - firstPieceFirstByteAddress
|
||||
68 ; edx - secondPieceFirstByteAddress
|
||||
69 ; esi
|
||||
70 ; edi
|
||||
71
|
||||
72 ; what we have:
|
||||
73 ; eax
|
||||
74 ; ebx
|
||||
75
|
||||
76 00000006 53 push ebx
|
||||
77 00000007 50 push eax
|
||||
78 ;mov eax, [ebp + firstPieceStartingByte]
|
||||
79 ;mov eax, [eax + image_pImg]
|
||||
80 00000008 BF00000000 mov edi, 0
|
||||
81
|
||||
82 x_pixels_loop:
|
||||
83 0000000D 3B7D20 cmp edi, [ebp + piece_width_bytes_address]
|
||||
84 ;cmp edi, 300
|
||||
85 00000010 7D42 jge x_pixels_loop_end
|
||||
86 00000012 BE00000000 mov esi, 0
|
||||
87
|
||||
88 ; ecx = secondPieceStartingByte
|
||||
89 ; edx = firstPieceStartingByte
|
||||
90 ; we still have eax and ebx
|
||||
91 ;
|
||||
92 y_pixels_loop:
|
||||
93 00000017 3B7524 cmp esi, [ebp + piece_height_bytes_address]
|
||||
94 ;cmp esi, 96000
|
||||
95 0000001A 7D33 jge y_pixels_loop_end
|
||||
96 0000001C 8B4D30 mov ecx, [ebp + secondPieceStartingByte]
|
||||
97 0000001F 8B452C mov eax, [ebp + firstPieceStartingByte]
|
||||
98 00000022 01F9 add ecx, edi
|
||||
99 00000024 01F1 add ecx, esi
|
||||
100 00000026 01F8 add eax, edi
|
||||
101 00000028 01F0 add eax, esi
|
||||
102
|
||||
103 0000002A 8A18 mov BYTE bl, [eax]
|
||||
104 0000002C 8A11 mov BYTE dl, [ecx]
|
||||
105 0000002E 8819 mov BYTE[ecx], bl
|
||||
106 00000030 8810 mov BYTE[eax], dl
|
||||
107
|
||||
108 00000032 8A5801 mov BYTE bl, [eax + 1]
|
||||
109 00000035 8A5101 mov BYTE dl, [ecx + 1]
|
||||
110 00000038 885901 mov BYTE[ecx + 1], bl
|
||||
111 0000003B 885001 mov BYTE[eax + 1], dl
|
||||
112
|
||||
113 0000003E 8A5802 mov BYTE bl, [eax + 2]
|
||||
114 00000041 8A5102 mov BYTE dl, [ecx + 2]
|
||||
115 00000044 885902 mov BYTE[ecx + 2], bl
|
||||
116 00000047 885002 mov BYTE[eax + 2], dl
|
||||
117
|
||||
118
|
||||
119
|
||||
120 0000004A 037528 add esi, [ebp + bytes_per_row_address]
|
||||
121 0000004D EBC8 jmp y_pixels_loop
|
||||
122
|
||||
123
|
||||
124 ; for(x = 0; x < pieceWidth * 3; x += 3)
|
||||
125 y_pixels_loop_end:
|
||||
126 0000004F 83C703 add edi, 3
|
||||
127 00000052 EBB9 jmp x_pixels_loop
|
||||
128
|
||||
129 x_pixels_loop_end:
|
||||
130
|
||||
131 00000054 5E pop esi
|
||||
132 00000055 5F pop edi
|
||||
133 00000056 5B pop ebx
|
||||
134 00000057 89EC mov esp, ebp
|
||||
135 00000059 5D pop ebp
|
||||
136 0000005A C3 ret
|
||||
BIN
ECOAR/C/asm_part.o
Normal file
BIN
ECOAR/C/dest.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
14
ECOAR/C/makefile
Executable file
@ -0,0 +1,14 @@
|
||||
CC=gcc
|
||||
ASMBIN=nasm
|
||||
|
||||
all : asm cc link
|
||||
asm :
|
||||
$(ASMBIN) -o asm_part.o -f elf32 -g -l asm_part.lst asm_part.asm
|
||||
cc :
|
||||
$(CC) -m32 -c -g -O0 puzzle.c
|
||||
link :
|
||||
$(CC) -m32 -g -o puzzle.out -g puzzle.o asm_part.o -no-pie
|
||||
clean :
|
||||
rm *.o
|
||||
rm setcol_test
|
||||
rm asm_part.lst
|
||||
BIN
ECOAR/C/pictures/source.bmp
Executable file
|
After Width: | Height: | Size: 225 KiB |
369
ECOAR/C/puzzle.c
Executable file
@ -0,0 +1,369 @@
|
||||
// ECOAR x86 PUZZLE Project Krzysztof Rudnicki, 307585
|
||||
#include <stdio.h> // fopen(); fread(); fwrite(); fclose()
|
||||
#include <stdlib.h> // printf(); srand();
|
||||
#include <memory.h> // malloc(); free();
|
||||
#include <time.h> // time();
|
||||
|
||||
const int BMP_HEADER_SIZE = 54;
|
||||
// as per: https://www.daubnet.com/en/file-format-bmp
|
||||
const int BMP_SIGNATURE_0x = 0x4D42;
|
||||
// as per: https://www.daubnet.com/en/file-format-bmp
|
||||
const int NUMBER_OF_HEADERS = 1; // There is only one header in BMP file
|
||||
const int BYTE_PER_PIXEL = 24; // as per project description of the bmp file
|
||||
const int DESIRED_COMPRESSION_VALUE = 0;
|
||||
// as per project description of the bmp file
|
||||
const int CANNOT_OPEN_FILE_FOR_WRITING = -1;
|
||||
const int CANNOT_WRITE_HEADER_OR_IMAGE = -2;
|
||||
const int BYTES_FOR_SINGLE_PIXEL = 3; // R byte + G byte + B byte
|
||||
const int WRONG_BMP_HEADER_SIZE = 1;
|
||||
const int ERROR_READING_SOURCE_FILE = 2;
|
||||
|
||||
const char ENTER_VERTICAL_DIVISON_MESSAGE[]
|
||||
= "Enter number of vertical divisons: ";
|
||||
|
||||
const char ENTER_HORIZONTAL_DIVISON_MESSAGE[]
|
||||
= "Enter number of horizontal divisons: ";
|
||||
|
||||
const char WRONG_BMP_HEADER_SIZE_MESSAGE[]
|
||||
= "Check compilation options so as bmpHeaderInfo struct size is 54 bytes.\n";
|
||||
|
||||
const char READ_AND_BINARY_MODE[] = "rb"; // open file to read and binary mode
|
||||
const char WRITE_AND_BINARY_MODE[] = "wb"; // open file to write and binary mode
|
||||
const char SOURCE_IMAGE_NAME[] = "source.bmp"; // as per project description
|
||||
const char DESTINATION_IMAGE_NAME[] = "dest.bmp"; // as per project description
|
||||
const char ERROR_READING_SOURCE_FILE_MESSAGE[]
|
||||
= "Error reading source file (probably).\n";
|
||||
|
||||
// "Specifies the packing alignment for structure, union, and class members."
|
||||
// something like .align in MIPS?
|
||||
// https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=msvc-160
|
||||
#pragma pack(push, 1)
|
||||
/* push - pushed to stack, n = 1
|
||||
n - (Optional) Specifies the value, in bytes, to be used for packing.
|
||||
If the compiler option /Zp isn't set for the module,
|
||||
the default value for n is 8. Valid values are 1, 2, 4, 8, and 16.
|
||||
The alignment of a member is on a boundary that's either a
|
||||
multiple of n, or a multiple of the size of the member,
|
||||
whichever is smaller. */
|
||||
// We pack it to "1" to get exactly 54 bytes for bmpHeaderInfo structure
|
||||
// Changing it to "8" gives us an error, changing it to "2" does not
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short bytesImageType; // 0x4D42 = "BMP" in Ascii, not used
|
||||
unsigned long bytesFileSize; // file size in bytes, not used
|
||||
unsigned short bfReservedOne; // reserved bytes from bmp file
|
||||
unsigned short bfReservedTwo; // reserved bytes from bmp file
|
||||
unsigned long bytesPixelDataOffset; // offset of pixel data, not used
|
||||
unsigned long bytesHeaderSize;
|
||||
// header size (bitmap info size), not used
|
||||
long bytesImageWidth; // image width, USED
|
||||
long bytesImageHeight; // image height, USED
|
||||
short bytesBitmapPlanes; // bitmap planes (== 1) USED
|
||||
short bytesPixelBitCount;
|
||||
// bit count of a pixel (== 24) (24 from project description), USED
|
||||
unsigned long bytesImageCompression;
|
||||
// should be 0 (no compression), USED
|
||||
unsigned long bytesImageSize; // image size (not file size!), USED
|
||||
long bytesHorizontalResolution; // horizontal resolution, not used
|
||||
long bytesVerticalResolution; // vertical resolution, not used
|
||||
unsigned long bytesColorsUsed;
|
||||
// not important for RGB images, not used
|
||||
unsigned long bytesColorsImportant;
|
||||
// not important for RGB images, not used
|
||||
} bmpHeaderInfo;
|
||||
// Struct containing info from header of a RGB type BMP file
|
||||
|
||||
#pragma pack(pop)
|
||||
// stack popped
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int imageWidth;
|
||||
unsigned int imageHeight; // same as in bmpHeaderInfo
|
||||
unsigned int bytesPerRow;
|
||||
// Bytes per row, important in MIPS, important here
|
||||
unsigned char* pImg;
|
||||
// pImg is a pointer to the begining of pixels data of the picture
|
||||
bmpHeaderInfo *pHeaderInfo; // pointer to info from header
|
||||
} imageInfo; // Stores info about image
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// If we want to write something to imageInfo struct first we need to empty it
|
||||
imageInfo* allocateSpaceForImageInfo()
|
||||
{
|
||||
// we allocate as much space as this struct needs
|
||||
imageInfo* emptyImageInfo = malloc(sizeof(imageInfo));
|
||||
// Then in this "if" we basically set starting values for
|
||||
// everything we care about
|
||||
if (emptyImageInfo != NULL)
|
||||
{
|
||||
emptyImageInfo->imageWidth = 0;
|
||||
emptyImageInfo->imageHeight = 0;
|
||||
emptyImageInfo->bytesPerRow = 0;
|
||||
emptyImageInfo->pImg = NULL;
|
||||
emptyImageInfo->pHeaderInfo = NULL;
|
||||
}
|
||||
return emptyImageInfo; // Then we retun the struct that we will use
|
||||
}
|
||||
|
||||
void* freeImageInfo(imageInfo* toFree)
|
||||
{
|
||||
if (toFree != NULL) // If image info is already empty no need to free it
|
||||
{
|
||||
if (toFree->pImg != NULL) free(toFree->pImg);
|
||||
// pImg is an char* so we need to free it extra
|
||||
if (toFree->pHeaderInfo != NULL) free(toFree->pHeaderInfo);
|
||||
// pHeaderInfo is a struct so we need to free it extra
|
||||
free(toFree); // Finally we can free the rest of the struct
|
||||
}
|
||||
return NULL;
|
||||
// we return void* since function readBMP calling freeImageInfo returns a
|
||||
// pointer
|
||||
}
|
||||
|
||||
// We use pFile to read/write to file and struct containing imageInfo in our
|
||||
// program, we have to free memory after using these two
|
||||
void* freeResources(FILE* pFile, imageInfo* toFree)
|
||||
{
|
||||
if (pFile != NULL) fclose(pFile); // Close file if it isn't already closed
|
||||
return freeImageInfo(toFree);
|
||||
}
|
||||
|
||||
|
||||
imageInfo* readBMP(const char* fileName)
|
||||
{
|
||||
imageInfo* pInfo = 0;
|
||||
/* https://stackoverflow.com/q/48288191
|
||||
Assignment of the constant 0 to a pointer will produce a null pointer
|
||||
distinguishable from a pointer to any object. */
|
||||
FILE* bmpFile = 0;
|
||||
|
||||
// allocateSpaceForImageInfo returns NULL if something went bad
|
||||
pInfo = allocateSpaceForImageInfo();
|
||||
if (pInfo == NULL) return NULL;
|
||||
|
||||
|
||||
// if fopen returns NULL then something bad happened
|
||||
bmpFile = fopen(fileName, READ_AND_BINARY_MODE);
|
||||
// cannot open file
|
||||
if (bmpFile == NULL) return freeResources(bmpFile, pInfo);
|
||||
|
||||
/* 1. if malloc didn't allocate any memory then something bad happened
|
||||
fread arguments: buffer to which we will save data that we read
|
||||
size of single data element in bytes
|
||||
number of elements that we will read
|
||||
stream on which this operation will be done
|
||||
We will save data to pHeaderInfo so that's our buffer
|
||||
We will get as much data as there is in bmpHeader
|
||||
There is just one header so we will read just from one header
|
||||
We will read all of that from bmp file
|
||||
it returns number of correctly read values, our desired return value is
|
||||
1 so if it returns any other then there was a mistake
|
||||
NUMBER_OF_HEADERS = 1 */
|
||||
pInfo->pHeaderInfo = malloc(sizeof(bmpHeaderInfo));
|
||||
size_t returnedElements = fread( (void*)pInfo->pHeaderInfo,
|
||||
sizeof(bmpHeaderInfo),
|
||||
NUMBER_OF_HEADERS,
|
||||
bmpFile );
|
||||
|
||||
if (pInfo->pHeaderInfo == NULL || returnedElements != NUMBER_OF_HEADERS)
|
||||
{
|
||||
return freeResources(bmpFile, pInfo);
|
||||
}
|
||||
|
||||
/* We check if image type is different than BMP
|
||||
We check if bitmap planes are different than 1
|
||||
we check if number of bits in one pixels is differnt than 24
|
||||
we check if there is any image compresssion
|
||||
those are the project assumptions if any of them are broken then there
|
||||
was a mistake
|
||||
BMP_SIGNATURE_0x = 0x4D42
|
||||
BYTE_PER_PIXEL = 24
|
||||
DESIRED_COMPRESSION_VALUE = 0 */
|
||||
if( pInfo->pHeaderInfo->bytesImageType != BMP_SIGNATURE_0x ||
|
||||
pInfo->pHeaderInfo->bytesBitmapPlanes != 1 ||
|
||||
pInfo->pHeaderInfo->bytesPixelBitCount != BYTE_PER_PIXEL ||
|
||||
pInfo->pHeaderInfo->bytesImageCompression != DESIRED_COMPRESSION_VALUE)
|
||||
{
|
||||
return (imageInfo*) freeResources(bmpFile, pInfo);
|
||||
}
|
||||
|
||||
/* We check if we allocated any memory to the image
|
||||
We check if number of read elements from the file are different than
|
||||
image size in bytes if any of this this is true then
|
||||
something went wrong
|
||||
*/
|
||||
pInfo->pImg = malloc(pInfo->pHeaderInfo->bytesImageSize);
|
||||
size_t returnedElementsData = fread((void *)pInfo->pImg,
|
||||
1,
|
||||
pInfo->pHeaderInfo->bytesImageSize,
|
||||
bmpFile);
|
||||
if( pInfo->pImg == NULL ||
|
||||
returnedElementsData != pInfo->pHeaderInfo->bytesImageSize)
|
||||
{
|
||||
return (imageInfo*) freeResources(bmpFile, pInfo);
|
||||
}
|
||||
|
||||
|
||||
fclose(bmpFile); // We can close the file
|
||||
|
||||
pInfo->imageWidth = pInfo->pHeaderInfo->bytesImageWidth;
|
||||
pInfo->imageHeight = pInfo->pHeaderInfo->bytesImageHeight;
|
||||
|
||||
pInfo->bytesPerRow = pInfo->pHeaderInfo->bytesImageSize /
|
||||
pInfo->pHeaderInfo->bytesImageHeight;
|
||||
|
||||
// bytesPerRow = imageSize / imageHeight
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
int saveBMP(const imageInfo* pInfo, const char* fileName)
|
||||
{
|
||||
FILE *bmpFile = fopen(fileName, WRITE_AND_BINARY_MODE);
|
||||
|
||||
// fopen returns NULL if something went bad
|
||||
// WRITE_AND_BINARY_MODE = "wb"
|
||||
// cannot open file for writing
|
||||
if (bmpFile == NULL) return CANNOT_OPEN_FILE_FOR_WRITING;
|
||||
|
||||
/* if we wrote more or less than one header then there is something wrong
|
||||
if we wrote more or less bytes to the image than there are bytes in the
|
||||
image then there is something wrong
|
||||
CANNOT_WRITE_HEADER_OR_IMAGE = -2 */
|
||||
size_t returnedHeaders = fwrite(pInfo->pHeaderInfo, sizeof(bmpHeaderInfo),
|
||||
NUMBER_OF_HEADERS, bmpFile);
|
||||
size_t returnedData = fwrite(pInfo->pImg, 1,
|
||||
pInfo->pHeaderInfo->bytesImageSize, bmpFile);
|
||||
|
||||
if (returnedHeaders != NUMBER_OF_HEADERS ||
|
||||
returnedData != pInfo->pHeaderInfo->bytesImageSize)
|
||||
{
|
||||
fclose(bmpFile); // cannot write header or image
|
||||
return CANNOT_WRITE_HEADER_OR_IMAGE;
|
||||
}
|
||||
|
||||
fclose(bmpFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_pixel(unsigned char * pPix, unsigned int color)
|
||||
{
|
||||
/* pImg -> pImg returns the starting addres of pixels
|
||||
then we calculate byte position of a pixel we want to change by:
|
||||
bytesPerRow * y_coordinate + x * 3 (3 bytes for RGB)
|
||||
BYTES_FOR_SINGLE_PIXEL = 3 */
|
||||
|
||||
// if x and y are inside the image then we can commence forward
|
||||
|
||||
*pPix = (color >> 16) & 0xFF; // R color of the pixel
|
||||
*(pPix + 1) = (color >> 8) & 0xFF; // G color of the pixel
|
||||
*(pPix + 2) = color & 0xFF; // B color of the pixel
|
||||
}
|
||||
|
||||
unsigned int getColor(unsigned char * pPix)
|
||||
{
|
||||
char R, G, B; // change to unsigned char
|
||||
R = *pPix;
|
||||
G = *(pPix + 1);
|
||||
B = *(pPix + 2);
|
||||
unsigned int color = 0;
|
||||
color = ( ((R & 0xFF) << 16) | (( G & 0xFF) << 8) | (B & 0xFF));
|
||||
return color;
|
||||
}
|
||||
|
||||
int calculateStartingPixelX(int pieceNumber, int horizontalDivisons,
|
||||
int pieceWidth)
|
||||
{
|
||||
int temp = pieceNumber % horizontalDivisons;
|
||||
if(temp == 0) temp = horizontalDivisons;
|
||||
return (temp - 1) * pieceWidth;
|
||||
}
|
||||
|
||||
int calculateStartingPixelY(int pieceNumber, int horizontalDivisons,
|
||||
int pieceHeight)
|
||||
{
|
||||
return (((pieceNumber - 1) / horizontalDivisons) * pieceHeight);
|
||||
}
|
||||
|
||||
extern void inner_loops(imageInfo* pInfo, int firstPiece, int pieceToSwapWith,
|
||||
int horizontalDivisions, int pieceWidth,
|
||||
int pieceHeight, int pieceWidthBytes, int bieceHeightBytes,
|
||||
unsigned int bytesPerRow,
|
||||
unsigned char *firstPieceStartingByte,
|
||||
unsigned char *secondPieceStartingByte); // Incomplete x86 solution
|
||||
|
||||
int main(/*int argc, char* argv[]*/) // argc and argv[] are not used anywhere
|
||||
{
|
||||
|
||||
imageInfo* pInfo; // imageInfo holds all header data from image
|
||||
unsigned int columnIndex = 0;
|
||||
// bmp header and info header should be 54 bytes as per BMP documentation
|
||||
// https://www.daubnet.com/en/file-format-bmp
|
||||
if (sizeof(bmpHeaderInfo) != BMP_HEADER_SIZE)
|
||||
{
|
||||
printf(WRONG_BMP_HEADER_SIZE_MESSAGE);
|
||||
return WRONG_BMP_HEADER_SIZE;
|
||||
}
|
||||
if ((pInfo = readBMP(SOURCE_IMAGE_NAME)) == NULL)
|
||||
{
|
||||
printf(ERROR_READING_SOURCE_FILE_MESSAGE);
|
||||
return ERROR_READING_SOURCE_FILE;
|
||||
}
|
||||
|
||||
int verticalDivisions, horizontalDivisions;
|
||||
printf(ENTER_VERTICAL_DIVISON_MESSAGE);
|
||||
scanf("%d", &verticalDivisions);
|
||||
printf(ENTER_HORIZONTAL_DIVISON_MESSAGE);
|
||||
scanf("%d", &horizontalDivisions);
|
||||
|
||||
int numberOfPieces = verticalDivisions * horizontalDivisions;
|
||||
int pieceWidth = (pInfo -> imageWidth) / horizontalDivisions;
|
||||
int pieceHeight = (pInfo -> imageHeight) / verticalDivisions;
|
||||
int pieceWidthBytes = pieceWidth * 3;
|
||||
int bieceHeightBytes = pieceHeight * (pInfo -> bytesPerRow);
|
||||
srand(time(NULL));
|
||||
int firstPiece;
|
||||
for(firstPiece = 1; firstPiece <= numberOfPieces; firstPiece++)
|
||||
{
|
||||
int pieceToSwapWith = rand() % numberOfPieces;
|
||||
// hello_world(pInfo, firstPiece, pieceToSwapWith, horizontalDivisions,
|
||||
// pieceWidth, pieceHeight, pieceWidthBytes, bieceHeightBytes, pInfo -> bytesPerRow); // Incomplete x86 solution
|
||||
|
||||
|
||||
|
||||
int firstPieceStartingX = calculateStartingPixelX(firstPiece, horizontalDivisions, pieceWidth);
|
||||
int firstPieceStartingY = calculateStartingPixelY(firstPiece, horizontalDivisions, pieceHeight);
|
||||
unsigned char *firstPieceStartingByte = firstPieceStartingX * 3 + firstPieceStartingY * pInfo -> bytesPerRow + pInfo -> pImg;
|
||||
|
||||
int secondPieceStartingX = calculateStartingPixelX(pieceToSwapWith, horizontalDivisions, pieceWidth);
|
||||
int secondPieceStartingY = calculateStartingPixelY(pieceToSwapWith, horizontalDivisions, pieceHeight);
|
||||
unsigned char *secondPieceStartingByte = secondPieceStartingX * 3 + secondPieceStartingY * pInfo -> bytesPerRow + pInfo -> pImg;
|
||||
|
||||
inner_loops(pInfo, firstPiece, pieceToSwapWith, horizontalDivisions,
|
||||
pieceWidth, pieceHeight, pieceWidthBytes, bieceHeightBytes, pInfo -> bytesPerRow, firstPieceStartingByte, secondPieceStartingByte);
|
||||
/* int x = 0;
|
||||
for(x = 0; x < pieceWidth * 3; x += 3)
|
||||
{
|
||||
int y = 0;
|
||||
for(y = 0; y < pieceHeight * pInfo -> bytesPerRow; y += pInfo -> bytesPerRow)
|
||||
{
|
||||
unsigned int colorOne = getColor(secondPieceStartingByte + x + y);
|
||||
unsigned int colorTwo = getColor(firstPieceStartingByte + x + y);
|
||||
set_pixel(firstPieceStartingByte + x + y, colorOne);
|
||||
set_pixel(secondPieceStartingByte + x + y, colorTwo);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
saveBMP(pInfo, DESTINATION_IMAGE_NAME);
|
||||
freeResources(NULL, pInfo);
|
||||
// printf("Operation failed succesfully\n");
|
||||
return 0;
|
||||
}
|
||||
BIN
ECOAR/C/puzzle.o
Normal file
BIN
ECOAR/C/puzzle.out
Executable file
BIN
ECOAR/C/source.bmp
Executable file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test1.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test2.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test3.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test4.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test5.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test6.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test7.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Outputs/test8.bmp
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
ECOAR/C/tests/Sources/source1.bmp
Executable file
|
After Width: | Height: | Size: 225 KiB |
50
ECOAR/C/tests/testDescription.txt
Normal file
@ -0,0 +1,50 @@
|
||||
One of the easiest scenarios, divisable in both dimensions, both being same number and low number
|
||||
1. Input file : source1.bmp,
|
||||
Vertical Divisions: 2
|
||||
Horizontal Divisions: 2
|
||||
Result: test1.bmp
|
||||
|
||||
Both divisable and equal to 10 but higher number
|
||||
2. Input file : source1.bmp,
|
||||
Vertical Divisions: 10
|
||||
Horizontal Divisions: 10
|
||||
Result: test2.bmp
|
||||
|
||||
Low number, divisable, different
|
||||
3. Input file : source1.bmp,
|
||||
Vertical Divisions: 3
|
||||
Horizontal Divisions: 4
|
||||
Result: test3.bmp
|
||||
|
||||
Low number, not divisable, diffrent
|
||||
4. Input file : source1.bmp,
|
||||
Vertical Divisions: 4
|
||||
Horizontal Divisions: 3
|
||||
Result: test4.bmp
|
||||
|
||||
Very different number, divisable
|
||||
5. Input file : source1.bmp,
|
||||
Vertical Divisions: 2
|
||||
Horizontal Divisions: 20
|
||||
Result: test5.bmp
|
||||
|
||||
Very different number, divisable
|
||||
6. Input file : source1.bmp,
|
||||
Vertical Divisions: 20
|
||||
Horizontal Divisions: 2
|
||||
Result: test6.bmp
|
||||
|
||||
Highest number, different, non divisable
|
||||
7. Input file : source1.bmp,
|
||||
Vertical Divisions: 320
|
||||
Horizontal Divisions: 240
|
||||
Result: test7.bmp
|
||||
|
||||
Highest number, different, divisable
|
||||
8. Input file : source1.bmp,
|
||||
Vertical Divisions: 240
|
||||
Horizontal Divisions: 320
|
||||
Result: test8.bmp
|
||||
|
||||
|
||||
|
||||
21
ECOAR/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Krzysztof Rudnicki
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
406
ECOAR/Puzzle/puzzle.asm
Executable file
@ -0,0 +1,406 @@
|
||||
#only 24-bits 320x240 pixels BMP files are supported
|
||||
# 24 * 320 * 240 = 1843200 bits = 1843200 / 8 bytes = 230400 bytes
|
||||
# let's round it to 240000 for a good measure
|
||||
.eqv BMP_FILE_SIZE 230454
|
||||
.eqv BYTES_PER_ROW 960
|
||||
|
||||
.data
|
||||
.align 4
|
||||
res: .space 2
|
||||
image: .space BMP_FILE_SIZE
|
||||
start_message_vertical: .asciiz "\nEnter number of vertical divisions:\n" # .asciiz stores the string
|
||||
end_message_vertical: .asciiz "You entered this many vertical divisions: "
|
||||
start_message_horizontal: .asciiz "\nEnter number of horizontal divisions:\n"
|
||||
end_message_horizontal : .asciiz "You entered this many horizontal divisions: "
|
||||
start_message: .asciiz "Enter number of vertical and horizontal divisions:\n"
|
||||
buffer: .space 1024
|
||||
HEIGHT: .word 240
|
||||
WIDTH: .word 320
|
||||
newline: .asciiz "\n"
|
||||
pieces: .word
|
||||
input_file_name: .asciiz "source.bmp" # name of input file as choosen in the project instruction
|
||||
output_file_name: .asciiz "dest.bmp" # name of output file as choosen in the project instruction
|
||||
|
||||
.text
|
||||
|
||||
_main:
|
||||
jal user_input_horizontal_division # puts number of horizontal divisions to $s5
|
||||
jal user_input_vertical_division # puts number of vertical divisions to $s4
|
||||
jal calculate_number_of_pieces # puts number of pieces to $s3
|
||||
jal random_number
|
||||
jal calculate_piece_WIDTH # calculates the WIDTH of a single piece based on number of vertical divisons
|
||||
jal calculate_piece_HEIGHT # calculates the WIDTH of a single piece based on number of horizontal divisons
|
||||
jal read_bmp
|
||||
|
||||
li $a0, 8
|
||||
jal calculate_piece_position_x
|
||||
li $a0, 8
|
||||
jal calculate_piece_position_y
|
||||
li $a0, 9
|
||||
jal calculate_piece_position_y
|
||||
li $a0, 5
|
||||
jal calculate_piece_position_y
|
||||
li $a0, 2
|
||||
jal calculate_piece_position_y
|
||||
li $a0, 10
|
||||
jal calculate_piece_position_y
|
||||
|
||||
#put red pixel in bottom left corner
|
||||
li $a0, 0 #x
|
||||
li $a1, 0 #y
|
||||
li $a2, 0x00FF0000 #color - 00RRGGBB
|
||||
jal put_pixel
|
||||
|
||||
#get pixel from x y
|
||||
li $a0, 0 #x
|
||||
li $a1, 0 #y
|
||||
jal get_pixel_v0
|
||||
#get pixel from x y
|
||||
li $a0, 0 #x
|
||||
li $a1, 5 #y
|
||||
jal get_pixel_v1
|
||||
|
||||
#put pixel that we got from the previous get pixel to x y position
|
||||
li $a0, 0 #x
|
||||
li $a1, 1 #y
|
||||
move $a2, $v0
|
||||
jal put_pixel
|
||||
|
||||
#put pixel that we got from the previous get pixel to x y position
|
||||
li $a0, 0 #x
|
||||
li $a1, 2 #y
|
||||
move $a2, $v1
|
||||
jal put_pixel
|
||||
|
||||
jal save_bmp
|
||||
jal end_program
|
||||
|
||||
.macro print(%text)
|
||||
la $a0, %text
|
||||
li $v0, 4
|
||||
syscall
|
||||
.end_macro
|
||||
|
||||
.macro print_int(%num)
|
||||
li $v0, 1 # If you want to print the integer the code is 1
|
||||
move $a0, %num # move the integer stored in %num to $a0
|
||||
syscall
|
||||
.end_macro
|
||||
|
||||
.macro println()
|
||||
la $a0, newline # New line string stored here
|
||||
li $v0, 4
|
||||
syscall
|
||||
.end_macro
|
||||
|
||||
|
||||
calculate_piece_position_x: # piece value is taken from $a0
|
||||
div $a0, $s4 # number of vertical divisons is stored in $s4
|
||||
mfhi $a1
|
||||
beq $a1, 0, piece_position_x_mod_zero
|
||||
sub $a1, $a1, 1
|
||||
println()
|
||||
print_int($a1)
|
||||
jr $ra
|
||||
|
||||
piece_position_x_mod_zero:
|
||||
li $a2, 0
|
||||
add $a2, $a2, $s5
|
||||
println()
|
||||
print_int($a2)
|
||||
jr $ra
|
||||
|
||||
|
||||
calculate_piece_position_y: #piece value is taken from $a0
|
||||
div $a0, $s4
|
||||
mfhi $a1
|
||||
beq $a1, 0, piece_position_y_mod_zero
|
||||
div $a2, $a0, $s4
|
||||
move $t0, $s4
|
||||
sub $a2, $t0, $a2
|
||||
println()
|
||||
print_int($a2)
|
||||
jr $ra
|
||||
|
||||
|
||||
piece_position_y_mod_zero:
|
||||
div $a2, $a0, $s4
|
||||
li $t0, 0
|
||||
add $t0, $s4, 1
|
||||
sub $a2, $t0, $a2
|
||||
println()
|
||||
print_int($a2)
|
||||
jr $ra
|
||||
|
||||
calculate_number_of_pieces:
|
||||
mul $s3, $s4, $s5
|
||||
jr $ra
|
||||
|
||||
random_number:
|
||||
move $a1, $s3 #Here you set $a1 to the max bound.
|
||||
li $v0, 42 #generates the random number.
|
||||
syscall
|
||||
#add $a0, $a0, 100 #Here you add the lowest bound
|
||||
#li $v0, 1 #1 print integer
|
||||
syscall
|
||||
jr $ra
|
||||
|
||||
|
||||
|
||||
close_file:
|
||||
li $v0, 16
|
||||
move $a0, $s6
|
||||
syscall
|
||||
jr $ra
|
||||
|
||||
calculate_piece_WIDTH:
|
||||
lw $a0, HEIGHT
|
||||
div $s1, $a0, $s4 # number of vertical divisons is kept in $s1
|
||||
jr $ra
|
||||
|
||||
calculate_piece_HEIGHT:
|
||||
lw $a0, WIDTH
|
||||
div $s2, $a0, $s5 # number of vertical divisons is kept in $s2
|
||||
jr $ra
|
||||
|
||||
display_start_message:
|
||||
print(start_message)
|
||||
|
||||
|
||||
user_input_vertical_division: # puts number of vertical divisions to $s4
|
||||
print(start_message_vertical)
|
||||
li $v0, 5 # we want to get the integer from the keyboard
|
||||
syscall # this will allow us to enter the number which will be stored in $v0
|
||||
# Store the result in $t0
|
||||
move $s4, $v0 # $t0 = $v0
|
||||
print(end_message_vertical)
|
||||
print_int($s4)
|
||||
jr $ra
|
||||
|
||||
enter_int:
|
||||
li $v0, 5 # we want to get the integer from the keyboard
|
||||
syscall # this will allow us to enter the number which will be stored in $v0
|
||||
# Store the result in $t0
|
||||
move $t0, $v0 # $t0 = $v0
|
||||
jr $ra
|
||||
|
||||
|
||||
|
||||
user_input_horizontal_division: # puts number of vertical divisions to $s5
|
||||
print(start_message_horizontal)
|
||||
li $v0, 5 # we want to get the integer from the keyboard
|
||||
syscall # this will allow us to enter the number which will be stored in $v0
|
||||
# Store the result in $t0
|
||||
move $s5, $v0 # $t0 = $v0
|
||||
print(end_message_horizontal)
|
||||
print_int($s5)
|
||||
jr $ra
|
||||
|
||||
calculate_picture_area:
|
||||
lw $t0, HEIGHT
|
||||
lw $t1, WIDTH
|
||||
mul $t2, $t0, $t1
|
||||
jr $ra
|
||||
|
||||
read_bmp:
|
||||
#description:
|
||||
# reads the contents of a bmp file into memory
|
||||
#arguments:
|
||||
# none
|
||||
#return value: none
|
||||
sub $sp, $sp, 4 #push $ra to the stack
|
||||
sw $ra,($sp)
|
||||
sub $sp, $sp, 4 #push $s1
|
||||
sw $s1, ($sp)
|
||||
#open file
|
||||
li $v0, 13
|
||||
la $a0, input_file_name #file name
|
||||
li $a1, 0 #flags: 0-read file
|
||||
li $a2, 0 #mode: ignored
|
||||
syscall
|
||||
move $s1, $v0 # save the file descriptor
|
||||
|
||||
#check for errors - if the file was opened
|
||||
#...
|
||||
|
||||
#read file
|
||||
li $v0, 14
|
||||
move $a0, $s1
|
||||
la $a1, image
|
||||
li $a2, BMP_FILE_SIZE
|
||||
syscall
|
||||
|
||||
#close file
|
||||
li $v0, 16
|
||||
move $a0, $s1
|
||||
syscall
|
||||
|
||||
lw $s1, ($sp) #restore (pop) $s1
|
||||
add $sp, $sp, 4
|
||||
lw $ra, ($sp) #restore (pop) $ra
|
||||
add $sp, $sp, 4
|
||||
jr $ra
|
||||
|
||||
put_pixel:
|
||||
#description:
|
||||
# sets the color of specified pixel
|
||||
#arguments:
|
||||
# $a0 - x coordinate
|
||||
# $a1 - y coordinate - (0,0) - bottom left corner
|
||||
# $a2 - 0RGB - pixel color
|
||||
#return value: none
|
||||
|
||||
sub $sp, $sp, 4 #push $ra to the stack
|
||||
sw $ra,($sp)
|
||||
|
||||
la $t1, image + 10 #adress of file offset to pixel array
|
||||
lw $t2, ($t1) #file offset to pixel array in $t2
|
||||
la $t1, image #adress of bitmap
|
||||
add $t2, $t1, $t2 #adress of pixel array in $t2
|
||||
|
||||
#pixel address calculation
|
||||
mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW
|
||||
move $t3, $a0
|
||||
sll $a0, $a0, 1
|
||||
add $t3, $t3, $a0 #$t3= 3*x
|
||||
add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW
|
||||
add $t2, $t2, $t1 #pixel address
|
||||
|
||||
#set new color
|
||||
sb $a2,($t2) #store B
|
||||
srl $a2,$a2,8
|
||||
sb $a2,1($t2) #store G
|
||||
srl $a2,$a2,8
|
||||
sb $a2,2($t2) #store R
|
||||
|
||||
lw $ra, ($sp) #restore (pop) $ra
|
||||
add $sp, $sp, 4
|
||||
jr $ra
|
||||
|
||||
|
||||
get_pixel_v0:
|
||||
#description:
|
||||
# returns color of specified pixel
|
||||
#arguments:
|
||||
# $a0 - x coordinate
|
||||
# $a1 - y coordinate - (0,0) - bottom left corner
|
||||
#return value:
|
||||
# $v0 - 0RGB - pixel color
|
||||
|
||||
sub $sp, $sp, 4 #push $ra to the stack
|
||||
sw $ra,($sp)
|
||||
|
||||
la $t1, image + 10 #adress of file offset to pixel array
|
||||
lw $t2, ($t1) #file offset to pixel array in $t2
|
||||
la $t1, image #adress of bitmap
|
||||
add $t2, $t1, $t2 #adress of pixel array in $t2
|
||||
|
||||
#pixel address calculation
|
||||
mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW
|
||||
move $t3, $a0
|
||||
sll $a0, $a0, 1
|
||||
add $t3, $t3, $a0 #$t3= 3*x
|
||||
add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW
|
||||
add $t2, $t2, $t1 #pixel address
|
||||
|
||||
#get color
|
||||
lbu $v0,($t2) #load B
|
||||
lbu $t1,1($t2) #load G
|
||||
sll $t1,$t1,8
|
||||
or $v0, $v0, $t1
|
||||
lbu $t1,2($t2) #load R
|
||||
sll $t1,$t1,16
|
||||
or $v0, $v0, $t1
|
||||
|
||||
lw $ra, ($sp) #restore (pop) $ra
|
||||
add $sp, $sp, 4
|
||||
jr $ra
|
||||
|
||||
get_pixel_v1:
|
||||
#description:
|
||||
# returns color of specified pixel
|
||||
#arguments:
|
||||
# $a0 - x coordinate
|
||||
# $a1 - y coordinate - (0,0) - bottom left corner
|
||||
#return value:
|
||||
# $v1 - 0RGB - pixel color
|
||||
|
||||
sub $sp, $sp, 4 #push $ra to the stack
|
||||
sw $ra,($sp)
|
||||
|
||||
la $t1, image + 10 #adress of file offset to pixel array
|
||||
lw $t2, ($t1) #file offset to pixel array in $t2
|
||||
la $t1, image #adress of bitmap
|
||||
add $t2, $t1, $t2 #adress of pixel array in $t2
|
||||
|
||||
#pixel address calculation
|
||||
mul $t1, $a1, BYTES_PER_ROW #t1= y*BYTES_PER_ROW
|
||||
move $t3, $a0
|
||||
sll $a0, $a0, 1
|
||||
add $t3, $t3, $a0 #$t3= 3*x
|
||||
add $t1, $t1, $t3 #$t1 = 3x + y*BYTES_PER_ROW
|
||||
add $t2, $t2, $t1 #pixel address
|
||||
|
||||
#get color
|
||||
lbu $v1,($t2) #load B
|
||||
lbu $t1,1($t2) #load G
|
||||
sll $t1,$t1,8
|
||||
or $v1 $v1, $t1
|
||||
lbu $t1,2($t2) #load R
|
||||
sll $t1,$t1,16
|
||||
or $v1, $v1, $t1
|
||||
|
||||
lw $ra, ($sp) #restore (pop) $ra
|
||||
add $sp, $sp, 4
|
||||
jr $ra
|
||||
|
||||
save_bmp:
|
||||
#description:
|
||||
# saves bmp file stored in memory to a file
|
||||
#arguments:
|
||||
# none
|
||||
#return value: none
|
||||
sub $sp, $sp, 4 #push $ra to the stack
|
||||
sw $ra,($sp)
|
||||
sub $sp, $sp, 4 #push $s1
|
||||
sw $s1, ($sp)
|
||||
#open file
|
||||
li $v0, 13
|
||||
la $a0, output_file_name #file name
|
||||
li $a1, 1 #flags: 1-write file
|
||||
li $a2, 0 #mode: ignored
|
||||
syscall
|
||||
move $s1, $v0 # save the file descriptor
|
||||
|
||||
#check for errors - if the file was opened
|
||||
#...
|
||||
|
||||
#save file
|
||||
li $v0, 15
|
||||
move $a0, $s1
|
||||
la $a1, image
|
||||
li $a2, BMP_FILE_SIZE
|
||||
syscall
|
||||
|
||||
#close file
|
||||
li $v0, 16
|
||||
move $a0, $s1
|
||||
syscall
|
||||
|
||||
lw $s1, ($sp) #restore (pop) $s1
|
||||
add $sp, $sp, 4
|
||||
lw $ra, ($sp) #restore (pop) $ra
|
||||
add $sp, $sp, 4
|
||||
jr $ra
|
||||
|
||||
|
||||
|
||||
end_program:
|
||||
li $v0, 10
|
||||
syscall
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||