The task is : Fade the top of a 24 bpp .BMP image to white so that every pixel's color is linearly interpolated between its original color and white based on its distance form the top edge. Pixels of distances >= dist are not faded.
I created all code and tried to fade something . It seems that it works only for distances which are power of 2 so 32,64,128 etc... I am using linear interpolation equaction and i dont have any idea why it doesnt work for other numbers. Any ideas ? :).
Sample image:
After fading I am getting...
global fadetop
; parm.
%define img [ebp+8]
%define width [ebp+12]
%define height [ebp+16]
%define dist [ebp+20]
; local
%define row_bytes [ebp-4]
%define dist_counter [ebp-8]
fadetop:
; create stack frame
push ebp
mov ebp, esp
sub esp, 8
; push register on stack
push ebx
push esi
push edi
; calculate size of row
mov edx, width
lea edx, [edx+edx*2]
add edx, 3
and edx, 0fffffffch
mov row_bytes, edx
; address of datas -calculations to write pixels from top left corner
mov eax,height
mul edx
sub eax ,row_bytes
add eax,3
mov esi, img
add esi,eax
;line couter
xor edx, edx
mov dist_counter , edx
line:
; pixel counter in line
mov edi, width
; index rexister
xor ebx, ebx
; INTERPOlATION STARTS NOW !!!
convert:
movzx eax, byte [esi+ebx+0] ; take color 1
sub eax, 255 ; sub white value
mov ecx, dist_counter
imul ecx ;color * actual position
cdq
mov ecx, dist ; devide by full fade operation distance
idiv ecx
add eax, 255 ; add 255
mov [esi+ebx+0], al ;put in this place
movzx eax,byte [esi+ebx+1] ; take color 2
sub eax, 255
mov ecx , dist_counter
mul ecx
cdq
mov ecx, dist
div ecx
add eax, 255
mov [esi+ebx+1], al
movzx eax,byte [esi+ebx+2] ; take color 3
sub eax, 255
mov ecx , dist_counter
mul ecx
cdq
mov ecx, dist
div ecx
add eax, 255
mov [esi+ebx+2], al
;________________________________________________________________
;if still in one line
add ebx, 3
dec edi
jnz convert
; if next line
sub esi, row_bytes
mov edx,dist_counter
inc edx
mov dist_counter,edx
mov eax, dist
cmp eax, edx
jnz line
; pop registers
pop edi
pop esi
pop ebx
; return trace
mov esp, ebp
pop ebp
ret
code in C for those who would like to run it and try fading :
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void fadetop(void* img, int width, int height ,int dist );
int main (int argc, char** argv) {
char* buff;
if (argc != 3 ) {
printf("Use file: %s [file]\n",argv[0]);
return 1;
}
struct stat st;
stat(argv[1], &st);
buff = (char *) malloc(st.st_size);
if (buff == NULL) {
printf("Memory error!!\n");
return 1;
}
int fd = open(argv[1], O_RDONLY, 0);
if (fd == -1) {
printf("File access error\n");
free(buff);
return 1;
}
int size = read(fd, buff, st.st_size);
uint32_t offset = *(uint32_t *) (buff + 0x0a);
uint32_t width = *(uint32_t *) (buff + 0x12);
uint32_t height = *(uint32_t *) (buff + 0x16);
uint16_t bpp = *(uint16_t *) (buff + 0x1c);
if (bpp == 24) {
int fd_out;
printf("worked dist: %d , heigh: %d\n", atoi(argv[2]), height);
fadetop(buff + offset, width , height , atoi(argv[2]) );
fd_out = creat("fade.bmp", 0644);
write(fd_out, buff, size);
close(fd_out);
printf("Image faded.\n");
}
else {
printf("Invalid BMP\n");
}
close(fd);
free(buff);
return 0;
}
Your formula seems correct: you have something like
although I would suggest the somewhat easier
(which at least visually gives the same result). Your main error is that since you are adding to the current value, you may be overflowing the maximum value of 255. After the calculations, test if
color > 255
and clamp if it is.In assembly (unable to test so I hope I get it right first time):
.. repeated for your 3 color components.
A few additional notes which may be helpful:
My second line of calculating the
color
is a constant for each line. So you only have to calculate it in your y loop and save it somewhere.You don't actually have to repeat the above code for each of the color components per pixel. Just repeat the x loop 3*
width
:Your starting position seems off, not only by a few lines but by a few pixels as well. This is partly because of the
add eax,3
here:but I'm not sure where the larger error comes from, because your padding calculation is correct. I could not test your actual code so I implemented it in bare C, and with that I get the following output for the input
./a.out flower.bmp 400
: