format MS COFF public EXPORTS section '.flat' code readable align 16 include '../../../../macros.inc' include '../../../../proc32.inc' ;----------------------------------------------------------------------------- mem.alloc dd ? ;функция для выделения памяти mem.free dd ? ;функция для освобождения памяти mem.realloc dd ? ;функция для перераспределения памяти dll.load dd ? BUF_STRUCT_SIZE equ 21 buf2d_data equ dword[edi] ;данные буфера изображения buf2d_w equ dword[edi+8] ;ширина буфера buf2d_h equ dword[edi+12] ;высота буфера buf2d_l equ word[edi+4] buf2d_t equ word[edi+6] ;отступ сверху buf2d_size_lt equ dword[edi+4] ;отступ слева и справа для буфера buf2d_color equ dword[edi+16] ;цвет фона буфера buf2d_bits equ byte[edi+20] ;количество бит в 1-й точке изображения struct buf_2d_header img_data dd ? left dw ? ;+4 left top dw ? ;+6 top size_x dd ? ;+8 w size_y dd ? ;+12 h color dd ? ;+16 color bit_pp db ? ;+21 bit in pixel ends macro swap v1, v2 { push v1 push v2 pop v1 pop v2 } ;флаги, для функции обрезания буфера BUF2D_OPT_CROP_TOP equ 1 ;обрезка сверху BUF2D_OPT_CROP_LEFT equ 2 ;обрезка слева BUF2D_OPT_CROP_BOTTOM equ 4 ;обрезка снизу BUF2D_OPT_CROP_RIGHT equ 8 ;обрезка справа BUF2D_BIT_OPT_CROP_TOP equ 0 BUF2D_BIT_OPT_CROP_LEFT equ 1 BUF2D_BIT_OPT_CROP_BOTTOM equ 2 BUF2D_BIT_OPT_CROP_RIGHT equ 3 ;input: ; eax = указатель на функцию выделения памяти ; ebx = ... освобождения памяти ; ecx = ... перераспределения памяти ; edx = ... загрузки библиотеки (пока не используется) align 16 lib_init: mov dword[mem.alloc], eax mov dword[mem.free], ebx mov dword[mem.realloc], ecx mov dword[dll.load], edx ret include 'fun_draw.inc' ;функции рисования в буфере ;создание буфера align 4 proc buf_create, buf_struc:dword pushad mov edi,dword[buf_struc] mov ecx,buf2d_w mov ebx,buf2d_h imul ecx,ebx cmp buf2d_bits,24 jne @f lea ecx,[ecx+ecx*2] ; 24 bit = 3 ;;;inc ecx ;запасной байт в конце буфера, что-бы не глючили некоторые функции на изображениях кратных 4К @@: cmp buf2d_bits,32 jne @f shl ecx,2 ; 32 bit = 4 @@: invoke mem.alloc,ecx mov buf2d_data,eax stdcall buf_clear,edi,buf2d_color ;очистка буфера фоновым цветом popad ret endp ;создание буфера на основе изображения rgb align 4 proc buf_create_f_img, buf_struc:dword, rgb_data:dword pushad mov edi,dword[buf_struc] mov ecx,buf2d_w cmp ecx,1 jl .error mov ebx,buf2d_h cmp ebx,1 jl .error imul ecx,ebx cmp buf2d_bits,24 jne @f lea ecx,[ecx+ecx*2] ; 24 bit = 3 @@: cmp buf2d_bits,32 jne @f shl ecx,2 ; 32 bit = 4 @@: invoke mem.alloc,ecx mov buf2d_data,eax cmp buf2d_bits,24 jne @f cld mov esi,[rgb_data] or esi,esi jz @f mov edi,eax ;eax=buf2d_data rep movsb ;копируем биты изображения в буфер jmp .end_create @@: stdcall buf_clear,edi,buf2d_color ;очистка буфера фоновым цветом jmp .end_create .error: stdcall print_err,sz_buf2d_create_f_img,txt_err_size_0 .end_create: popad ret endp ;функция для обрезания буферов 8 и 24 битных, по заданому цвету. ;параметр opt задается комбинацией констант: ; BUF2D_OPT_CROP_TOP - обрезка сверху ; BUF2D_OPT_CROP_LEFT - обрезка слева ; BUF2D_OPT_CROP_BOTTOM - обрезка снизу ; BUF2D_OPT_CROP_RIGHT - обрезка справа align 4 proc buf_crop_color, buf_struc:dword, color:dword, opt:dword locals crop_r dd ? endl pushad mov edi,dword[buf_struc] cmp buf2d_bits,24 jne .24end_f bt dword[opt],BUF2D_BIT_OPT_CROP_BOTTOM jae .24no_crop_bottom mov eax,dword[color] mov edx,eax ;ax = colors - r,g shr edx,16 ;dl = color - b mov ecx,buf2d_h cmp ecx,1 jle .24no_crop_bottom ;проверяем на случай если высота буфера 1 пиксель mov ebx,buf2d_w imul ecx,ebx lea esi,[ecx+ecx*2] ;esi=3*ecx add esi,buf2d_data cld @@: sub esi,3 cmp word[esi],ax jne @f cmp byte[esi+2],dl jne @f loop @b @@: lea ebx,[ebx+ebx*2] xor edx,edx mov eax,buf2d_h imul eax,ebx add eax,buf2d_data ;eax - указатель на конец буфера изображения @@: add esi,ebx cmp esi,eax jge @f inc edx ;вычисляем число полных строк для обрезания loop @b @@: cmp edx,0 je .24no_crop_bottom cmp edx,buf2d_h jge .24no_crop_bottom ;что-бы не получить пустой буфер sub buf2d_h,edx ;уменьшаем высоту буфера mov ecx,buf2d_h imul ecx,ebx ;ecx = новый размер изображения invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .24no_crop_bottom: bt dword[opt],BUF2D_BIT_OPT_CROP_TOP jae .24no_crop_top mov eax,dword[color] mov edx,eax ;ax = colors - r,g shr edx,16 ;dl = color - b mov esi,buf2d_data mov ecx,buf2d_h cmp ecx,1 jle .24no_crop_top ;проверяем на случай если высота буфера 1 пиксель dec ecx ;при обрезании должна остаться минимум 1-на строка пикселей mov ebx,buf2d_w imul ecx,ebx cld @@: cmp word[esi],ax jne @f cmp byte[esi+2],dl jne @f add esi,3 loop @b @@: lea ebx,[ebx+ebx*2] xor edx,edx @@: sub esi,ebx cmp esi,buf2d_data jl @f inc edx ;вычисляем число полных строк для обрезания loop @b @@: cmp edx,0 je .24no_crop_top xor eax,eax sub eax,edx mov ebx,buf2d_h sub ebx,edx stdcall buf_offset_h, edi, eax, edx, ebx ;сдвигаем изображение в буфере вверх (eax<0) sub buf2d_h,edx ;уменьшаем высоту буфера mov ecx,buf2d_h add buf2d_t,dx ;сдвигаем отступ вниз, на число обрезанных строк mov ebx,buf2d_w imul ecx,ebx lea ecx,[ecx+ecx*2] invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .24no_crop_top: bt dword[opt],BUF2D_BIT_OPT_CROP_RIGHT jae .24no_crop_right mov eax,dword[color] mov edx,eax ;ax = colors - r,g shr edx,16 ;dl = color - b mov ebx,buf2d_w cmp ebx,1 jle .24no_crop_right ;на случай если ширина буфера 1 пиксель lea ebx,[ebx+ebx*2] mov esi,ebx imul esi,buf2d_h add esi,buf2d_data ;esi - указатель на конец буфера изображения mov dword[crop_r],0 cld .24found_beg_right: sub esi,3 ;двигаемся на 1-ну колонку влево mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: cmp word[esi],ax jne .24found_right cmp byte[esi+2],dl jne .24found_right sub esi,ebx ;прыгаем на верхнюю строку loop @b inc dword[crop_r] mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp dword[crop_r],ecx jge .24found_right sub esi,3 ;двигаемся на 1-ну колонку влево mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: add esi,ebx ;прыгаем на нижнюю строку cmp word[esi],ax jne .24found_right cmp byte[esi+2],dl jne .24found_right loop @b inc dword[crop_r] mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp dword[crop_r],ecx jl .24found_beg_right .24found_right: cmp dword[crop_r],0 je .24no_crop_right mov ecx,buf2d_w sub ecx,dword[crop_r] stdcall img_rgb_crop_r, buf2d_data, buf2d_w, ecx, buf2d_h ;обрезаем буфер, по новому размеру mov buf2d_w,ecx ;ставим новую ширину для буфера mov ebx,buf2d_h imul ecx,ebx lea ecx,[ecx+ecx*2] invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .24no_crop_right: bt dword[opt],BUF2D_BIT_OPT_CROP_LEFT jae .24no_crop_left mov eax,dword[color] mov edx,eax ;ax = colors - r,g shr edx,16 ;dl = color - b mov ebx,buf2d_w cmp ebx,1 jle .24no_crop_left ;на случай если ширина буфера 1 пиксель lea ebx,[ebx+ebx*2] mov esi,buf2d_data ;esi - указатель на начоло буфера изображения mov dword[crop_r],0 cld .24found_beg_left: mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: cmp word[esi],ax jne .24found_left cmp byte[esi+2],dl jne .24found_left add esi,ebx ;прыгаем на нижнюю строку loop @b inc dword[crop_r] add esi,3 ;двигаемся на 1-ну колонку вправо mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp dword[crop_r],ecx jge .24found_left mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: sub esi,ebx ;прыгаем на верхнюю строку cmp word[esi],ax jne .24found_left cmp byte[esi+2],dl jne .24found_left loop @b inc dword[crop_r] add esi,3 ;двигаемся на 1-ну колонку вправо mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp dword[crop_r],ecx jl .24found_beg_left .24found_left: cmp dword[crop_r],0 je .24no_crop_left mov ecx,buf2d_w sub ecx,dword[crop_r] stdcall img_rgb_crop_l, buf2d_data, buf2d_w, ecx, buf2d_h ;обрезаем буфер, по новому размеру mov buf2d_w,ecx ;ставим новую ширину для буфера mov ebx,buf2d_h imul ecx,ebx lea ecx,[ecx+ecx*2] invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные mov eax,dword[crop_r] add buf2d_l,ax .24no_crop_left: .24end_f: cmp buf2d_bits,8 jne .8end_f bt dword[opt],BUF2D_BIT_OPT_CROP_BOTTOM jae .8no_crop_bottom mov eax,dword[color] mov esi,buf2d_data mov ecx,buf2d_h cmp ecx,1 jle .8no_crop_bottom ;проверяем на случай если высота буфера 1 пиксель mov ebx,buf2d_w imul ecx,ebx mov esi,ecx add esi,buf2d_data cld @@: dec esi cmp byte[esi],al jne @f loop @b @@: xor edx,edx mov eax,buf2d_h imul eax,ebx add eax,buf2d_data ;eax - указатель на конец буфера изображения @@: add esi,ebx cmp esi,eax jge @f inc edx loop @b @@: cmp edx,0 je .8no_crop_bottom cmp edx,buf2d_h jge .8no_crop_bottom ;что-бы не получить пустой буфер sub buf2d_h,edx ;уменьшаем высоту буфера mov ecx,buf2d_h imul ecx,ebx ;ecx = новый размер изображения invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .8no_crop_bottom: bt dword[opt],BUF2D_BIT_OPT_CROP_TOP jae .8no_crop_top mov eax,dword[color] mov esi,buf2d_data mov ecx,buf2d_h cmp ecx,1 jle .8no_crop_top ;проверяем на случай если высота буфера 1 пиксель dec ecx ;при обрезании должна остаться минимум 1-на строка пикселей mov ebx,buf2d_w imul ecx,ebx cld @@: cmp byte[esi],al jne @f inc esi loop @b @@: xor edx,edx @@: sub esi,ebx cmp esi,buf2d_data jl @f inc edx loop @b @@: cmp edx,0 je .8no_crop_top xor eax,eax sub eax,edx mov ebx,buf2d_h sub ebx,edx stdcall buf_offset_h, edi, eax, edx, ebx mov ecx,buf2d_h sub ecx,edx mov buf2d_h,ecx ;уменьшаем высоту буфера add buf2d_t,dx ;сдвигаем отступ вниз, на число обрезанных строк mov ebx,buf2d_w imul ecx,ebx invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .8no_crop_top: bt dword[opt],BUF2D_BIT_OPT_CROP_RIGHT jae .8no_crop_right mov eax,dword[color] mov ebx,buf2d_w cmp ebx,1 jle .8no_crop_right ;на случай если ширина буфера 1 пиксель mov esi,ebx imul esi,buf2d_h add esi,buf2d_data ;esi - указатель на конец буфера изображения xor edx,edx cld .8found_beg: dec esi ;двигаемся на 1-ну колонку влево mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: cmp byte[esi],al jne .8found sub esi,ebx ;прыгаем на верхнюю строку loop @b inc edx mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp edx,ecx jge .8found dec esi ;двигаемся на 1-ну колонку влево mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: add esi,ebx ;прыгаем на нижнюю строку cmp byte[esi],al jne .8found loop @b inc edx mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp edx,ecx jl .8found_beg .8found: cmp edx,0 je .8no_crop_right mov ecx,buf2d_w sub ecx,edx stdcall img_gray_crop_r, buf2d_data, buf2d_w, ecx, buf2d_h ;обрезаем буфер, по новому размеру mov buf2d_w,ecx ;ставим новую ширину для буфера mov ebx,buf2d_h imul ecx,ebx invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные .8no_crop_right: bt dword[opt],BUF2D_BIT_OPT_CROP_LEFT jae .8no_crop_left mov eax,dword[color] mov ebx,buf2d_w cmp ebx,1 jle .8no_crop_left ;на случай если ширина буфера 1 пиксель mov esi,buf2d_data ;esi - указатель на начоло буфера изображения mov edx,0 cld .8found_beg_left: mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: cmp word[esi],ax jne .8found_left add esi,ebx ;прыгаем на нижнюю строку loop @b inc edx inc esi ;двигаемся на 1-ну колонку вправо mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp edx,ecx jge .8found_left mov ecx,buf2d_h ;восстановление ecx для нового цикла @@: sub esi,ebx ;прыгаем на верхнюю строку cmp word[esi],ax jne .8found_left loop @b inc edx inc esi ;двигаемся на 1-ну колонку вправо mov ecx,buf2d_w dec ecx ;1 колонка на запас cmp edx,ecx jl .8found_beg_left .8found_left: cmp edx,0 je .8no_crop_left mov ecx,buf2d_w sub ecx,edx stdcall img_gray_crop_l, buf2d_data, buf2d_w, ecx, buf2d_h ;обрезаем буфер, по новому размеру mov buf2d_w,ecx ;ставим новую ширину для буфера mov ebx,buf2d_h imul ecx,ebx invoke mem.realloc,buf2d_data,ecx mov buf2d_data,eax ;на случай если изменился указатель на данные mov eax,edx add buf2d_l,ax .8no_crop_left: .8end_f: popad ret endp ;обрезаем цветное изображение с правой стороны ;input: ;data_rgb - pointer to rgb data ;size_w_old - width img in pixels ;size_w_new - new width img in pixels ;size_h - height img in pixels align 4 proc img_rgb_crop_r, data_rgb:dword, size_w_old:dword, size_w_new:dword, size_h:dword pushad mov eax, dword[size_w_old] lea eax, dword[eax+eax*2] ;eax = width(old) * 3(rgb) mov ebx, dword[size_w_new] lea ebx, dword[ebx+ebx*2] ;ebx = width(new) * 3(rgb) mov edx, dword[size_h] mov edi, dword[data_rgb] ;edi - получает данные mov esi, edi add edi, ebx add esi, eax cld @@: dec edx ;уменьшаем счетчик оставшихся строк на 1 cmp edx,0 jle @f mov ecx, ebx rep movsb ;перенос (копирование) строки пикселей add esi,eax ;переход на новую строчку изображения sub esi,ebx jmp @b @@: popad ret endp ;обрезаем серое изображение с правой стороны ;input: ;data_gray - pointer to gray data ;size_w_old - width img in pixels ;size_w_new - new width img in pixels ;size_h - height img in pixels align 4 proc img_gray_crop_r, data_gray:dword, size_w_old:dword, size_w_new:dword, size_h:dword pushad mov eax, dword[size_w_old] mov ebx, dword[size_w_new] mov edx, dword[size_h] mov edi, dword[data_gray] ;edi - получает данные mov esi, edi add edi, ebx add esi, eax cld @@: dec edx ;уменьшаем счетчик оставшихся строк на 1 cmp edx,0 jle @f mov ecx, ebx rep movsb ;перенос (копирование) строки пикселей add esi,eax ;переход на новую строчку изображения sub esi,ebx jmp @b @@: popad ret endp ;обрезаем цветное изображение с левой стороны ;input: ;data_rgb - pointer to rgb data ;size_w_old - width img in pixels ;size_w_new - new width img in pixels ;size_h - height img in pixels align 4 proc img_rgb_crop_l, data_rgb:dword, size_w_old:dword, size_w_new:dword, size_h:dword pushad mov edi,dword[data_rgb] mov esi,edi mov eax,dword[size_w_old] mov ebx,dword[size_w_new] cmp eax,ebx jle .end_f ;старый размер изображения не может быть меньше нового (при условии обрезания картинки) lea eax,[eax+eax*2] lea ebx,[ebx+ebx*2] sub eax,ebx mov edx,dword[size_h] ;высота изображения cld @@: add esi,eax mov ecx,ebx rep movsb dec edx cmp edx,0 jg @b .end_f: popad ret endp ;обрезаем серое изображение с левой стороны ;input: ;data_gray - pointer to gray data ;size_w_old - width img in pixels ;size_w_new - new width img in pixels ;size_h - height img in pixels align 4 proc img_gray_crop_l, data_gray:dword, size_w_old:dword, size_w_new:dword, size_h:dword pushad mov edi,dword[data_gray] mov esi,edi mov eax,dword[size_w_old] mov ebx,dword[size_w_new] cmp eax,ebx jle .end_f ;старый размер изображения не может быть меньше нового (при условии обрезания картинки) sub eax,ebx mov edx,dword[size_h] ;высота изображения cld @@: add esi,eax mov ecx,ebx rep movsb dec edx cmp edx,0 jg @b .end_f: popad ret endp ;hoffs - колличество пикселей на котрые поднимается/опускается изображение ;img_t - высота, с которой начинается двигающаяся часть изображения align 4 proc buf_offset_h, buf_struc:dword, hoffs:dword, img_t:dword, img_h:dword ;сдвигает изображение по высоте pushad mov edi,dword[buf_struc] cmp buf2d_bits,24 jne .end_move_24 mov eax,[hoffs] cmp eax,0 je .end_move_24 mov ebx,buf2d_w mov edx,dword[img_t] mov ecx,dword[img_h] ;ecx - высота сдвигаемых данных cmp ecx,buf2d_h jge .end_f ;ошибочное условие, высота изображения меньше чем высота сдвигаемого изображения imul ecx,ebx ;ecx - колличество пикселей в сдвигаемых данных lea ecx,[ecx+ecx*2] imul ebx,edx lea ebx,[ebx+ebx*2] mov esi,buf2d_data add esi,ebx add edx,eax ;edx = img_t+hoffs (hoffs<0) mov ebx,buf2d_w imul ebx,edx lea ebx,[ebx+ebx*2] mov edi,buf2d_data ;позиция, куда будет двигаться изображение add edi,ebx cmp eax,0 jg .move_down_24 ;двигаем изображение вверх cld rep movsb jmp .end_f .move_down_24: ;двигаем изображение вниз add esi,ecx dec esi add edi,ecx dec edi std rep movsb jmp .end_f .end_move_24: ;stdcall print_err,sz_buf2d_offset_h,txt_err_n24b cmp buf2d_bits,8 jne .end_move_8 mov eax,[hoffs] cmp eax,0 je .end_move_8 ;двигаем изображение вверх mov ebx,buf2d_w mov edx,dword[img_t] mov ecx,dword[img_h] ;ecx - высота сдвигаемых данных cmp ecx,buf2d_h jge .end_f ;ошибочное условие, высота изображения меньше чем высота сдвигаемого изображения imul ecx,ebx ;ecx - колличество пикселей в сдвигаемых данных imul ebx,edx mov esi,buf2d_data add esi,ebx add edx,eax ;edx = img_t+hoffs (hoffs<0) mov ebx,buf2d_w imul ebx,edx mov edi,buf2d_data ;позиция, куда будет двигаться изображение add edi,ebx cmp eax,0 jg .move_down_8 cld rep movsb jmp .end_f .move_down_8: ;двигаем изображение вниз add esi,ecx dec esi add edi,ecx dec edi std rep movsb jmp .end_f .end_move_8: .end_f: popad ret endp align 4 proc buf_delete, buf_struc:dword push eax edi mov edi,dword[buf_struc] invoke mem.free,buf2d_data pop edi eax ret endp ;input: ; new_w - новая ширина (если 0 то не меняется) ; new_h - новая высота (если 0 то не меняется) ; options - параметры изменения буфера (1 - изменять размер буфера, ; 2 - изменять изображение в буфере, 3 - изменять буфер и изображение) align 4 proc buf_resize, buf_struc:dword, new_w:dword, new_h:dword, options:dword pushad mov edi,dword[buf_struc] cmp buf2d_bits,8 jne .8bit bt dword[options],1 ;сжатие изобр. jnc @f ;... @@: bt dword[options],0 ;измен. буфер jnc .end_f ;... jmp .end_f .8bit: cmp buf2d_bits,24 jne .24bit bt dword[options],1 ;сжатие изобр. jnc .24_end_r mov eax,dword[new_w] cmp eax,1 jl @f cmp eax,buf2d_w jge @f ;сжатие по ширине stdcall img_rgb24_wresize, buf2d_data,buf2d_w,buf2d_h,eax jmp .24_r_h @@: mov eax,buf2d_w .24_r_h: ;eax - ширина буфера или ширина сжатого изображения mov ebx,dword[new_h] cmp ebx,1 jl @f cmp ebx,buf2d_h jge @f ;сжатие по высоте stdcall img_rgb24_hresize, buf2d_data,eax,buf2d_h,ebx @@: .24_end_r: bt dword[options],0 ;измен. буфер jnc .end_f mov eax,dword[new_w] cmp eax,1 jl @f mov buf2d_w,eax @@: mov ecx,buf2d_w mov eax,dword[new_h] cmp eax,1 jl @f mov buf2d_h,eax @@: mov ebx,buf2d_h imul ecx,ebx lea ecx,[ecx+ecx*2] ; 24 bit = 3 invoke mem.realloc,buf2d_data,ecx ;изменяем память занимаемую буфером mov buf2d_data,eax ;на случай если изменился указатель на данные .24bit: .end_f: popad ret endp align 4 rot_table: ;таблица для указания на подфункции для поворотов dd buf_rotate.8b90,buf_rotate.24b90,buf_rotate.32b90,\ buf_rotate.8b180,buf_rotate.24b180,buf_rotate.32b180 ;поворот изображения на 90 или 180 градусов align 4 proc buf_rotate, buf_struc:dword, angle:dword locals n_data dd ? dec_h dd ? ;число байт, для уменьшения координаты y endl pushad mov edi,[buf_struc] mov ebx,buf2d_w mov ecx,buf2d_h lea eax,[rot_table] cmp dword[angle],90 ;проверка угла поворота je .beg_0 cmp dword[angle],180 jne @f add eax,12 jmp .beg_0 @@: jmp .end_f .beg_0: ;проверка битности буфера cmp buf2d_bits,8 jne @f jmp dword[eax] @@: cmp buf2d_bits,24 jne @f add eax,4 jmp dword[eax] @@: cmp buf2d_bits,32 jne @f add eax,8 jmp dword[eax] @@: jmp .end_f .8b90: ;поворот 8 битного буфера на 90 градусов mov edx,ecx ;edx - buf_h imul ecx,ebx invoke mem.alloc,ecx ;выделяем временную память cmp eax,0 je .end_f mov [n_data],eax mov [dec_h],ecx inc dword[dec_h] ;copy buf --> mem mov edi,[buf_struc] mov esi,buf2d_data mov edi,eax ;[n_data] dec edx ;коректируем edx на 1 байт, для компенсации сдвига в movsb add edi,edx xor eax,eax cld .cycle_0: movsb add edi,edx inc eax cmp eax,ebx jl @f xor eax,eax sub edi,[dec_h] @@: loop .cycle_0 ;change buf_w <---> buf_h mov esi,[n_data] mov edi,[buf_struc] mov edi,buf2d_data mov ecx,ebx inc edx ;исправляем скоректированный edx imul ecx,edx ;copy buf <-- mem ;cld rep movsb invoke mem.free,[n_data] jmp .change_w_h .24b90: ;поворот 24 битного буфера на 90 градусов mov esi,ecx imul esi,ebx lea ecx,[ecx+ecx*2] mov edx,ecx ;edx - buf_h * 3 imul ecx,ebx invoke mem.alloc,ecx ;выделяем временную память cmp eax,0 je .end_f mov [n_data],eax mov [dec_h],ecx add dword[dec_h],3 ;copy buf --> mem mov edi,[buf_struc] mov ecx,esi mov esi,buf2d_data mov edi,eax ;[n_data] sub edx,3 ;коректируем edx на 3 байта, для компенсации сдвига add edi,edx xor eax,eax cld .cycle_1: movsw movsb add edi,edx inc eax cmp eax,ebx jl @f xor eax,eax sub edi,[dec_h] @@: loop .cycle_1 ;copy buf <-- mem mov esi,[n_data] mov edi,[buf_struc] mov edi,buf2d_data mov ecx,ebx add edx,3 ;исправляем скоректированный edx imul ecx,edx ;cld rep movsb invoke mem.free,[n_data] jmp .change_w_h .32b90: ;поворот 32 битного буфера на 90 градусов shl ecx,2 mov edx,ecx ;edx - buf_h * 4 imul ecx,ebx invoke mem.alloc,ecx ;выделяем временную память cmp eax,0 je .end_f mov [n_data],eax mov [dec_h],ecx add dword[dec_h],4 ;copy buf --> mem mov edi,[buf_struc] shr ecx,2 mov esi,buf2d_data mov edi,eax ;[n_data] sub edx,4 ;коректируем edx на 4 байта, для компенсации сдвига в movsd add edi,edx xor eax,eax cld .cycle_2: movsd add edi,edx inc eax cmp eax,ebx jl @f xor eax,eax sub edi,[dec_h] @@: loop .cycle_2 ;copy buf <-- mem mov esi,[n_data] mov edi,[buf_struc] mov edi,buf2d_data mov ecx,ebx add edx,4 ;исправляем скоректированный edx imul ecx,edx shr ecx,2 ;cld rep movsd invoke mem.free,[n_data] ;jmp .change_w_h .change_w_h: ;change buf_w <---> buf_h mov edi,[buf_struc] mov eax,buf2d_w mov ebx,buf2d_h mov buf2d_h,eax mov buf2d_w,ebx jmp .end_f .8b180: ;поворот 8 битного буфера на 180 градусов mov edi,buf2d_data mov esi,edi imul ecx,ebx add esi,ecx dec esi shr ecx,1 ;ecx - число пикселей буфера : 2 std @@: lodsb mov ah,byte[edi] mov byte[esi+1],ah mov byte[edi],al inc edi loop @b jmp .end_f .24b180: ;поворот 24 битного буфера на 180 градусов mov esi,buf2d_data mov edi,esi imul ecx,ebx mov eax,ecx lea ecx,[ecx+ecx*2] add edi,ecx sub edi,3 shr eax,1 mov ecx,eax ;ecx - число пикселей буфера : 2 cld @@: lodsw mov edx,eax lodsb mov bx,word[edi] mov word[esi-3],bx mov bl,byte[edi+2] mov byte[esi-1],bl mov byte[edi+2],al mov word[edi],dx sub edi,3 loop @b jmp .end_f .32b180: ;поворот 32 битного буфера на 180 градусов mov edi,buf2d_data mov esi,edi imul ecx,ebx shl ecx,2 add esi,ecx sub esi,4 shr ecx,3 ;ecx - число пикселей буфера : 2 std @@: lodsd mov ebx,dword[edi] mov dword[esi+4],ebx mov dword[edi],eax add edi,4 loop @b ;jmp .end_f .end_f: popad ret endp align 4 proc buf_flip_h, buf_struc:dword pushad mov edi,[buf_struc] cmp buf2d_bits,24 jne .end_24 mov esi,buf2d_data mov eax,buf2d_w mov ecx,eax shr ecx,1 dec eax lea eax,[eax+eax*2] mov ebx,buf2d_h mov edi,esi add esi,eax add eax,3 cld .cycle_24: push ecx edi esi align 4 @@: ;swap word[edi] <-> word[esi] mov dx,[edi] movsw mov [esi-2],dx ;swap byte[edi] <-> byte[esi] mov dl,[edi] movsb mov [esi-1],dl sub esi,6 loop @b pop esi edi ecx add edi,eax add esi,eax dec ebx or ebx,ebx jnz .cycle_24 jmp .end_32 .end_24: cmp buf2d_bits,32 jne .end_32 mov esi,buf2d_data mov eax,buf2d_w dec eax shl eax,2 mov ebx,buf2d_h mov edi,esi add esi,eax add eax,4 cld .cycle_32: mov ecx,eax shr ecx,3 push edi esi align 4 @@: ;swap dword[edi] <-> dword[esi] mov edx,[edi] movsd mov [esi-4],edx sub esi,8 loop @b pop esi edi add edi,eax add esi,eax dec ebx or ebx,ebx jnz .cycle_32 .end_32: popad ret endp ;отразить по вертикали (верх и низ меняются местами) align 4 proc buf_flip_v, buf_struc:dword locals line_pix dd ? ;кол. пикселей в линии буфера line_2byte dd ? ;кол. байт в линии буфера * 2 endl pushad mov edi,[buf_struc] cmp buf2d_bits,24 jne .end_24 mov edx,buf2d_w mov [line_pix],edx mov ebx,buf2d_h lea edx,[edx+edx*2] mov esi,edx imul esi,ebx sub esi,edx add esi,buf2d_data ;указатель на нижнюю линию shr ebx,1 ;кол. линейных циклов shl edx,1 mov [line_2byte],edx mov edi,buf2d_data xchg edi,esi cld .flip_24: cmp ebx,0 jle .end_32 ;здесь выход из функции (потому .end_24 не подходит) mov ecx,[line_pix] align 4 @@: lodsw mov dx,word[edi] mov word[esi-2],dx stosw lodsb mov ah,byte[edi] mov byte[esi-1],ah stosb loop @b sub edi,[line_2byte] dec ebx jmp .flip_24 .end_24: cmp buf2d_bits,32 jne .end_32 mov edx,buf2d_w mov [line_pix],edx mov ebx,buf2d_h shl edx,2 mov esi,edx imul esi,ebx sub esi,edx add esi,buf2d_data ;указатель на нижнюю линию shr ebx,1 ;кол. линейных циклов shl edx,1 mov [line_2byte],edx mov edi,buf2d_data xchg edi,esi cld .flip_32: cmp ebx,0 jle .end_32 mov ecx,[line_pix] align 4 @@: lodsd mov edx,dword[edi] mov dword[esi-4],edx stosd loop @b sub edi,[line_2byte] dec ebx jmp .flip_32 .end_32: popad ret endp ;description: ; сжатие изображения по ширине в 2 раза (размеры буфера не меняются) align 4 proc buf_img_wdiv2, buf_struc:dword pushad mov edi,dword[buf_struc] cmp buf2d_bits,8 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax stdcall img_8b_wdiv2, buf2d_data,ecx @@: cmp buf2d_bits,24 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax stdcall img_rgb24_wdiv2, buf2d_data,ecx @@: cmp buf2d_bits,32 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax stdcall img_rgba32_wdiv2, buf2d_data,ecx @@: popad ret endp ;input: ;data_8b - pointer to rgb data ;size - count img pixels (size img data / 3(rgb) ) align 4 proc img_8b_wdiv2 data_8b:dword, size:dword mov eax,dword[data_8b] mov ecx,dword[size] ;ecx = size cld @@: ;затемнение цвета пикселей shr byte[eax],1 inc eax loop @b mov eax,dword[data_8b] mov ecx,dword[size] ;ecx = size shr ecx,1 @@: ;сложение цветов пикселей mov bl,byte[eax+1] ;копируем цвет соседнего пикселя add byte[eax],bl add eax,2 loop @b mov eax,dword[data_8b] inc eax mov ebx,eax inc ebx mov ecx,dword[size] ;ecx = size shr ecx,1 dec ecx ;лишний пиксель @@: ;поджатие пикселей mov dl,byte[ebx] mov byte[eax],dl inc eax add ebx,2 loop @b ret endp ;input: ;data_rgb - pointer to rgb data ;size - count img pixels (size img data / 3(rgb) ) align 4 proc img_rgb24_wdiv2 data_rgb:dword, size:dword mov eax,dword[data_rgb] mov ecx,dword[size] ;ecx = size lea ecx,[ecx+ecx*2] cld @@: ;затемнение цвета пикселей shr byte[eax],1 inc eax loop @b mov eax,dword[data_rgb] mov ecx,dword[size] ;ecx = size shr ecx,1 @@: ;сложение цветов пикселей mov bx,word[eax+3] ;копируем цвет соседнего пикселя add word[eax],bx mov bl,byte[eax+5] ;копируем цвет соседнего пикселя add byte[eax+2],bl add eax,6 ;=2*3 loop @b mov eax,dword[data_rgb] add eax,3 mov ebx,eax add ebx,3 mov ecx,dword[size] ;ecx = size shr ecx,1 dec ecx ;лишний пиксель @@: ;поджатие пикселей mov edx,dword[ebx] mov word[eax],dx shr edx,16 mov byte[eax+2],dl add eax,3 add ebx,6 loop @b ret endp ;input: ;data_rgba - pointer to rgba data ;size - count img pixels (size img data / 4(rgba) ) align 4 proc img_rgba32_wdiv2 data_rgba:dword, size:dword mov eax,dword[data_rgba] mov eax,dword[data_rgba] mov ebx,eax add ebx,4 mov ecx,dword[size] ;ecx = size shr ecx,1 @@: ;смешивание цветов пикселей call combine_colors_1 mov [eax],edx add eax,8 ;=2*4 add ebx,8 loop @b mov eax,dword[data_rgba] add eax,4 mov ebx,eax add ebx,4 mov ecx,dword[size] ;ecx = size shr ecx,1 dec ecx ;лишний пиксель @@: ;поджатие пикселей mov edx,dword[ebx] mov dword[eax],edx add eax,4 add ebx,8 loop @b ret endp ;description: ; сжатие изображения по высоте в 2 раза (высота буфера не меняется) align 4 proc buf_img_hdiv2, buf_struc:dword pushad mov edi,dword[buf_struc] cmp buf2d_bits,8 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax stdcall img_8b_hdiv2, buf2d_data,ecx,eax jmp .end_f ;edi портится в функции, потому использование buf2d_bits опасно @@: cmp buf2d_bits,24 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax stdcall img_rgb24_hdiv2, buf2d_data,ecx,eax jmp .end_f @@: cmp buf2d_bits,32 jne @f mov eax,buf2d_w mov ecx,buf2d_h imul ecx,eax shl eax,2 stdcall img_rgba32_hdiv2, buf2d_data,ecx,eax ;jmp .end_f @@: .end_f: popad ret endp ;input: ;data_8b - pointer to 8 bit data ;size - count img pixels (size img data) ;size_w - width img in pixels align 4 proc img_8b_hdiv2, data_8b:dword, size:dword, size_w:dword mov eax,dword[data_8b] ;eax = mov ecx,dword[size] cld @@: ;затемнение цвета пикселей shr byte[eax],1 inc eax loop @b mov eax,dword[data_8b] ;eax = mov esi,dword[size_w] mov ebx,esi add ebx,eax mov ecx,dword[size] ;ecx = size shr ecx,1 xor edi,edi @@: ;сложение цветов пикселей mov dl,byte[ebx] ;копируем цвет нижнего пикселя add byte[eax],dl inc eax inc ebx inc edi cmp edi,dword[size_w] jl .old_line add eax,esi add ebx,esi xor edi,edi .old_line: loop @b mov eax,dword[data_8b] ;eax = add eax,esi ;esi = width*3(rgb) mov ebx,eax add ebx,esi mov ecx,dword[size] ;ecx = size shr ecx,1 sub ecx,dword[size_w] ;лишняя строка пикселей xor edi,edi @@: ;поджатие пикселей mov dl,byte[ebx] ;копируем цвет нижнего пикселя mov byte[eax],dl inc eax inc ebx inc edi cmp edi,dword[size_w] jl .old_line_2 add ebx,esi xor edi,edi .old_line_2: loop @b ret endp ;input: ;data_rgb - pointer to rgb data ;size - count img pixels (size img data / 3(rgb) ) ;size_w - width img in pixels align 4 proc img_rgb24_hdiv2, data_rgb:dword, size:dword, size_w:dword mov eax,dword[data_rgb] ;eax = mov ecx,dword[size] ;ecx = size lea ecx,[ecx+ecx*2] cld @@: ;затемнение цвета пикселей shr byte[eax],1 inc eax loop @b mov eax,dword[data_rgb] ;eax = mov esi,dword[size_w] lea esi,[esi+esi*2] ;esi = width*3(rgb) mov ebx,esi add ebx,eax mov ecx,dword[size] ;ecx = size shr ecx,1 xor edi,edi @@: ;сложение цветов пикселей mov dx,word[ebx] ;копируем цвет нижнего пикселя add word[eax],dx mov dl,byte[ebx+2] ;копируем цвет нижнего пикселя add byte[eax+2],dl add eax,3 add ebx,3 inc edi cmp edi,dword[size_w] jl .old_line add eax,esi add ebx,esi xor edi,edi .old_line: loop @b mov eax,dword[data_rgb] ;eax = add eax,esi ;esi = width*3(rgb) mov ebx,eax add ebx,esi mov ecx,dword[size] ;ecx = size shr ecx,1 sub ecx,dword[size_w] ;лишняя строка пикселей xor edi,edi @@: ;поджатие пикселей mov edx,dword[ebx] ;копируем цвет нижнего пикселя mov word[eax],dx shr edx,16 mov byte[eax+2],dl add eax,3 add ebx,3 inc edi cmp edi,dword[size_w] jl .old_line_2 add ebx,esi xor edi,edi .old_line_2: loop @b ret endp ;input: ;data_rgba - pointer to rgba data ;size - count img pixels (size img data / 4(rgba) ) ;size_w_b - width img in bytes align 4 proc img_rgba32_hdiv2, data_rgba:dword, size:dword, size_w_b:dword mov eax,dword[data_rgba] ;eax = mov ebx,dword[size_w_b] add ebx,eax mov ecx,dword[size] ;ecx = size shr ecx,1 xor edi,edi @@: ;смешивание цветов пикселей call combine_colors_1 mov dword[eax],edx add eax,4 add ebx,4 add edi,4 cmp edi,dword[size_w_b] jl .old_line add eax,dword[size_w_b] add ebx,dword[size_w_b] xor edi,edi .old_line: loop @b mov eax,dword[data_rgba] ;eax = mov ebx,dword[size_w_b] add eax,ebx add ebx,eax mov ecx,dword[size] ;ecx = size shl ecx,1 sub ecx,dword[size_w_b] ;лишняя строка пикселей shr ecx,2 xor edi,edi @@: ;поджатие пикселей mov edx,dword[ebx] ;копируем цвет нижнего пикселя mov dword[eax],edx add eax,4 add ebx,4 add edi,4 cmp edi,dword[size_w_b] jl .old_line_2 add ebx,dword[size_w_b] xor edi,edi .old_line_2: loop @b ret endp ;input: ; eax - указатель на 32-битный цвет ; ebx - указатель на 32-битный цвет ;output: ; edx - 32-битный цвет смешанный с учетом прозрачности ;destroy: ; esi align 4 proc combine_colors_1 uses ecx edi locals c_blye dd ? c_green dd ? c_red dd ? endl movzx edi,byte[eax+3] cmp edi,255 je .c0z movzx esi,byte[ebx+3] cmp esi,255 je .c1z cmp edi,esi je .c0_c1 ;переворачиваем значения прозрачностей neg edi inc edi add edi,255 neg esi inc esi add esi,255 movzx ecx,byte[eax] imul ecx,edi mov [c_blye],ecx movzx ecx,byte[ebx] imul ecx,esi add [c_blye],ecx movzx ecx,byte[eax+1] imul ecx,edi mov [c_green],ecx movzx ecx,byte[ebx+1] imul ecx,esi add [c_green],ecx movzx ecx,byte[eax+2] imul ecx,edi mov [c_red],ecx movzx ecx,byte[ebx+2] imul ecx,esi add [c_red],ecx push eax ebx xor ebx,ebx mov eax,[c_red] xor edx,edx mov ecx,edi add ecx,esi div ecx mov bl,al shl ebx,16 mov eax,[c_green] xor edx,edx div ecx mov bh,al mov eax,[c_blye] xor edx,edx div ecx mov bl,al shr ecx,1 ;переворачиваем значения прозрачности neg ecx inc ecx add ecx,255 shl ecx,24 add ebx,ecx mov edx,ebx pop ebx eax jmp .end_f .c0_c1: ;если прозрачности обоих цветов совпадают mov edx,dword[eax] shr edx,1 and edx,011111110111111101111111b mov esi,dword[ebx] shr esi,1 and esi,011111110111111101111111b add edx,esi ror edi,8 ;перемещаем значение прозрачности в старший байт edi or edx,edi jmp .end_f .c0z: ;если цвет в eax прозрачный mov edx,dword[ebx] movzx edi,byte[ebx+3] jmp @f .c1z: ;если цвет в ebx прозрачный mov edx,dword[eax] @@: add edi,255 ;делаем цвет на половину прозрачным shr edi,1 cmp edi,255 jl @f mov edi,255 ;максимальная прозрачность не более 255 @@: shl edi,24 and edx,0xffffff ;снимаем старую прозрачность add edx,edi .end_f: ret endp ;description: ; сжатие изображения по ширине (размеры буфера не меняются) ;input: ; data_rgb - pointer to rgb data ; size_w - width img in pixels ; size_h - height img in pixels ; size_w_new - new width img in pixels align 16 proc img_rgb24_wresize, data_rgb:dword, size_w:dword, size_h:dword, size_w_new:dword locals pr dd 0 pg dd 0 pb dd 0 img_n dd ? ;указатель на данные нового изображения lines dd ? endl pushad ;eax - delta for inp. img ;ebx - delta for outp. img ;esi - pointer to data_rgb mov esi,[data_rgb] mov [img_n],esi mov eax,[size_h] mov [lines],eax align 4 .cycyle_0: mov eax,[size_w_new] mov ecx,[size_w] mov ebx,ecx align 4 .cycyle_1: cmp eax,ebx jg .else_0 ;копируемый пиксель максимально влияет на результат ;накапливаем rgb для интерполяции пикселей mov edx,[size_w_new] movzx edi,byte[esi] imul edi,edx add [pb],edi movzx edi,byte[esi+1] imul edi,edx add [pg],edi movzx edi,byte[esi+2] imul edi,edx add [pr],edi cmp eax,ebx je .d2_add jmp .if_0_end .else_0: ;копируемый пиксель попадет на границу пикселей mov edx,ebx sub edx,eax add edx,[size_w_new] movzx edi,byte[esi] imul edi,edx add [pb],edi movzx edi,byte[esi+1] imul edi,edx add [pg],edi movzx edi,byte[esi+2] imul edi,edx add [pr],edi ;сохраняем готовое rgb .d2_add: push eax mov edi,[img_n] mov eax,[pb] xor edx,edx div dword[size_w] ;eax /= [size_w] stosb mov eax,[pg] xor edx,edx div dword[size_w] ;eax /= [size_w] stosb mov eax,[pr] xor edx,edx div dword[size_w] ;eax /= [size_w] stosb pop eax add dword[img_n],3 ;next pixel ;обновляем rgb для нового пикселя mov edx,eax sub edx,ebx movzx edi,byte[esi] imul edi,edx mov [pb],edi movzx edi,byte[esi+1] imul edi,edx mov [pg],edi movzx edi,byte[esi+2] imul edi,edx mov [pr],edi add ebx,[size_w] .if_0_end: add eax,[size_w_new] add esi,3 ;next pixel dec ecx jnz .cycyle_1 dec dword[lines] jnz .cycyle_0 popad ret endp ;description: ; сжатие изображения по высоте (размеры буфера не меняются) ;input: ; data_rgb - pointer to rgb data ; size_w - width img in pixels ; size_h - height img in pixels ; size_h_new - new height img in pixels align 16 proc img_rgb24_hresize, data_rgb:dword, size_w:dword, size_h:dword, size_h_new:dword locals pr dd 0 pg dd 0 pb dd 0 img_n dd ? ;указатель на данные нового изображения cols dd ? lin_b dd ? ;размер линии изображения в байтах data_n dd ? ;указатель на данные для нового столбца пикселей endl pushad ;eax - delta for inp. img ;ebx - delta for outp. img ;esi - pointer to data_rgb mov esi,[data_rgb] mov [data_n],esi mov eax,[size_w] mov [cols],eax lea eax,[eax+eax*2] mov [lin_b],eax align 4 .cycyle_0: mov eax,[size_h_new] mov ecx,[size_h] mov ebx,ecx mov esi,[data_n] mov [img_n],esi add dword[data_n],3 ;переход на следующий столбец пикселей align 4 .cycyle_1: cmp eax,ebx jg .else_0 ;копируемый пиксель максимально влияет на результат ;накапливаем rgb для интерполяции пикселей mov edx,[size_h_new] movzx edi,byte[esi] imul edi,edx add [pb],edi movzx edi,byte[esi+1] imul edi,edx add [pg],edi movzx edi,byte[esi+2] imul edi,edx add [pr],edi cmp eax,ebx je .d2_add jmp .if_0_end .else_0: ;копируемый пиксель попадет на границу пикселей mov edx,ebx sub edx,eax add edx,[size_h_new] movzx edi,byte[esi] imul edi,edx add [pb],edi movzx edi,byte[esi+1] imul edi,edx add [pg],edi movzx edi,byte[esi+2] imul edi,edx add [pr],edi ;сохраняем готовое rgb .d2_add: push eax mov edi,[img_n] mov eax,[pb] xor edx,edx div dword[size_h] ;eax /= [size_h] stosb mov eax,[pg] xor edx,edx div dword[size_h] ;eax /= [size_h] stosb mov eax,[pr] xor edx,edx div dword[size_h] ;eax /= [size_h] stosb pop eax mov edx,[lin_b] add dword[img_n],edx ;next pixel ;обновляем rgb для нового пикселя mov edx,eax sub edx,ebx movzx edi,byte[esi] imul edi,edx mov [pb],edi movzx edi,byte[esi+1] imul edi,edx mov [pg],edi movzx edi,byte[esi+2] imul edi,edx mov [pr],edi add ebx,[size_h] .if_0_end: add eax,[size_h_new] add esi,[lin_b] ;next pixel dec ecx jnz .cycyle_1 dec dword[cols] jnz .cycyle_0 popad ret endp ;преобразование буфера из 24-битного в 8-битный ; spectr - определяет какой спектр брать при преобразовании 0-синий, 1-зеленый, 2-красный align 4 proc buf_conv_24_to_8, buf_struc:dword, spectr:dword pushad mov edi,dword[buf_struc] cmp buf2d_bits,24 jne .error0 mov eax,buf2d_w cmp eax,1 jl .error1 mov ecx,buf2d_h cmp ecx,1 jl .error1 imul ecx,eax mov esi,ecx ;ebx - память из которой копируется ;edx - память куда копируется mov edx,buf2d_data mov ebx,edx cmp [spectr],3 jge @f add ebx,[spectr] @@: mov al,byte[ebx] mov byte[edx],al add ebx,3 inc edx loop @b mov buf2d_bits,8 invoke mem.realloc,buf2d_data,esi ;уменьшаем память занимаемую буфером jmp .end_conv .error0: stdcall print_err,sz_buf2d_conv_24_to_8,txt_err_n24b jmp .end_conv .error1: stdcall print_err,sz_buf2d_conv_24_to_8,txt_err_size_0 .end_conv: popad ret endp ;преобразование буфера из 24-битного в 32-битный align 4 proc buf_conv_24_to_32, buf_struc:dword, buf_str8:dword pushad mov edi,dword[buf_struc] cmp buf2d_bits,24 jne .error1 mov ecx,buf2d_w mov ebx,buf2d_h imul ebx,ecx mov ecx,ebx ;ecx = size 8 b shl ebx,2 ;ebx = size 32 b invoke mem.realloc,buf2d_data,ebx ;увеличиваем память занимаемую буфером mov buf2d_data,eax ;на случай если изменился указатель на данные mov buf2d_bits,32 mov edx,ebx ;edx = size 32 b sub ebx,ecx ;ebx = size 24 b mov eax,ecx ;eax - размер 8 битных данных ;ebx - размер 24 битных данных ;edx - размер 32 битных данных add ebx,buf2d_data add edx,buf2d_data mov edi,dword[buf_str8] cmp buf2d_bits,8 jne .error2 add eax,buf2d_data mov edi,edx ;eax - указатель на конец 8 битных данных ;ebx - указатель на конец 24 битных данных ;edi - указатель на конец 32 битных данных @@: sub edi,4 ;отнимаем в начале цикла, sub ebx,3 ; потому, что указатели стоят dec eax ; за пределами буферов mov edx,dword[ebx] mov dword[edi],edx mov dl,byte[eax] mov byte[edi+3],dl loop @b jmp .end_conv .error1: stdcall print_err,sz_buf2d_conv_24_to_32,txt_err_n24b jmp .end_conv .error2: stdcall print_err,sz_buf2d_conv_24_to_32,txt_err_n8b .end_conv: popad ret endp ;функция копирует изображение из буфера buf_source (24b|32b) в buf_destination (24b) ; указываются координаты вставки буфера buf_source относительно buf_destination ; прозрачность при копировании не учитывается align 4 proc buf_bit_blt, buf_destination:dword, coord_x:dword, coord_y:dword, buf_source:dword locals right_bytes dd ? endl pushad mov edi,[buf_source] cmp buf2d_bits,24 je .sou24 cmp buf2d_bits,32 je .sou32 jmp .copy_end ;формат буфера не поодерживается .sou24: ;в источнике 24 битная картинка mov eax,buf2d_w mov edx,buf2d_h ;высота копируемой картинки mov esi,buf2d_data ;данные копируемой картинки mov edi,[buf_destination] cmp buf2d_bits,24 jne .copy_end ;формат буфера не поодерживается mov ebx,[coord_x] ;в ebx временно ставим отступ изображения (для проверки) cmp ebx,buf2d_w ;проверяем влазит ли изображение по ширине jge .copy_end ;если изображение полностью вылазит за правую сторону mov ebx,buf2d_h ;ebx - высота основного буфера mov ecx,[coord_y] cmp ecx,0 jge @f ;если координата coord_y<0 (1-я настройка) add edx,ecx ;уменьшаем высоту копируемой картинки cmp edx,0 jle .copy_end ;если копируемое изображение находится полностью над верхней границей буфера (coord_y<0 и |coord_y|>buf_source.h) neg ecx ;inc ecx imul ecx,eax lea ecx,[ecx+ecx*2] ;по 3 байта на пиксель add esi,ecx ;сдвигаем указатель с копируемыми данными, с учетом пропушеной части xor ecx,ecx ;обнуляем координату coord_y @@: cmp ecx,ebx jge .copy_end ;если координата 'y' больше высоты буфера add ecx,edx ;ecx - нижняя координата копируемой картинки cmp ecx,ebx jle @f sub ecx,ebx sub edx,ecx ;уменьшаем высоту копируемой картинки, в случе когда она вылазит за нижнюю границу @@: mov ebx,buf2d_w mov ecx,[coord_y] ;ecx используем для временных целей cmp ecx,0 jg .end_otr_c_y_24 ;если координата coord_y<=0 (2-я настройка) mov ecx,[coord_x] jmp @f .end_otr_c_y_24: imul ecx,ebx add ecx,[coord_x] @@: lea ecx,[ecx+ecx*2] add ecx,buf2d_data sub ebx,eax mov edi,ecx ;edi указатель на данные буфера, куда будет производится копирование mov [right_bytes],0 mov ecx,[coord_x] cmp ecx,ebx jl @f sub ecx,ebx sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера lea ecx,[ecx+ecx*2] ;ecx - число байт в 1-й строке картинки, которые вылазят за правую сторону mov [right_bytes],ecx @@: lea eax,[eax+eax*2] ;колличество байт в 1-й строке копируемой картинки lea ebx,[ebx+ebx*2] ;колличество байт в 1-й строке буфера минус число байт в 1-й строке копируемой картинки cld cmp [right_bytes],0 jg .copy_1 .copy_0: ;простое копирование mov ecx,eax rep movsb add edi,ebx dec edx cmp edx,0 jg .copy_0 jmp .copy_end .copy_1: ;не простое копирование (картинка вылазит за правую сторону) mov ecx,eax rep movsb add edi,ebx add esi,[right_bytes] ;добавляем байты, которые вылазят за правую границу dec edx cmp edx,0 jg .copy_1 jmp .copy_end .sou32: ;в источнике 32 битная картинка mov eax,buf2d_w mov edx,buf2d_h ;высота копируемой картинки mov esi,buf2d_data ;данные копируемой картинки mov edi,[buf_destination] cmp buf2d_bits,24 jne .copy_end ;формат буфера не поодерживается mov ebx,[coord_x] ;в ebx временно ставим отступ изображения (для проверки) cmp ebx,buf2d_w ;проверяем влазит ли изображение по ширине jge .copy_end ;если изображение полностью вылазит за правую сторону mov ebx,buf2d_h ;ebx - высота основного буфера mov ecx,[coord_y] cmp ecx,0 jge @f ;если координата coord_y<0 (1-я настройка) add edx,ecx ;уменьшаем высоту копируемой картинки cmp edx,0 jle .copy_end ;если копируемое изображение находится полностью над верхней границей буфера (coord_y<0 и |coord_y|>buf_source.h) neg ecx ;inc ecx imul ecx,eax shl ecx,2 ;по 4 байта на пиксель add esi,ecx ;сдвигаем указатель с копируемыми данными, с учетом пропушеной части xor ecx,ecx ;обнуляем координату coord_y @@: cmp ecx,ebx jge .copy_end ;если координата 'y' больше высоты буфера add ecx,edx ;ecx - нижняя координата копируемой картинки cmp ecx,ebx jle @f sub ecx,ebx sub edx,ecx ;уменьшаем высоту копируемой картинки, в случе когда она вылазит за нижнюю границу @@: mov ebx,buf2d_w ;mov ecx,ebx ;ecx используем для временных целей ;imul ecx,[coord_y] ;add ecx,[coord_x] mov ecx,[coord_y] ;ecx используем для временных целей cmp ecx,0 jg .end_otr_c_y_32 ;если координата coord_y<=0 (2-я настройка) mov ecx,[coord_x] jmp @f .end_otr_c_y_32: imul ecx,ebx add ecx,[coord_x] @@: lea ecx,[ecx+ecx*2] add ecx,buf2d_data sub ebx,eax mov edi,ecx ;edi указатель на данные буфера, куда будет производится копирование mov [right_bytes],0 mov ecx,[coord_x] cmp ecx,ebx jl @f sub ecx,ebx sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера shl ecx,2 ;ecx - число байт в 1-й строке картинки, которые вылазят за правую сторону mov [right_bytes],ecx @@: ;eax - колличество пикселей в 1-й строке копируемой картинки lea ebx,[ebx+ebx*2] ;колличество байт в 1-й строке буфера минус число байт в 1-й строке копируемой картинки cld cmp [right_bytes],0 jg .copy_3 .copy_2: ;простое копирование mov ecx,eax @@: movsw movsb inc esi loop @b add edi,ebx dec edx cmp edx,0 jg .copy_2 jmp .copy_end .copy_3: ;не простое копирование (картинка вылазит за правую сторону) mov ecx,eax @@: movsw movsb inc esi loop @b add edi,ebx add esi,[right_bytes] ;добавляем байты, которые вылазят за правую границу dec edx cmp edx,0 jg .copy_3 .copy_end: popad ret endp ;input: ; esi = pointer to color1 + transparent ; edi = pointer to background color2 ;output: ; [edi] = combine color align 4 combine_colors_0: push ax bx cx dx mov bx,0x00ff ;---get transparent--- movzx cx,byte[esi+3] ;pro sub bx,cx ;256-pro ;---blye--- movzx ax,byte[esi] imul ax,bx movzx dx,byte[edi] imul dx,cx add ax,dx mov byte[edi],ah ;---green--- movzx ax,byte[esi+1] imul ax,bx movzx dx,byte[edi+1] imul dx,cx add ax,dx mov byte[edi+1],ah ;---red--- movzx ax,byte[esi+2] imul ax,bx movzx dx,byte[edi+2] imul dx,cx add ax,dx mov byte[edi+2],ah pop dx cx bx ax ret ;функция копирует изображение из буфера buf_source (32b) в buf_destination (24b) ; указываются координаты вставки буфера buf_source относительно buf_destination ; при копировании учитывается прозрачность align 4 proc buf_bit_blt_transp, buf_destination:dword, coord_x:dword, coord_y:dword, buf_source:dword locals lost_bytes dd ? endl pushad mov edi,[buf_source] cmp buf2d_bits,32 jne .copy_end ;формат буфера не поодерживается mov eax,buf2d_w mov edx,buf2d_h ;высота копируемой картинки mov esi,buf2d_data ;данные копируемой картинки mov edi,[buf_destination] cmp buf2d_bits,24 jne .copy_end ;формат буфера не поодерживается mov ebx,buf2d_h ;ebx - высота основного буфера mov ecx,[coord_y] cmp ecx,0 jge @f ;если координата coord_y<0 (1-я настройка) add edx,ecx ;уменьшаем высоту копируемой картинки cmp edx,0 jle .copy_end ;если копируемое изображение находится полностью над верхней границей буфера (coord_y<0 и |coord_y|>buf_source.h) neg ecx ;inc ecx imul ecx,eax shl ecx,2 ;по 4 байта на пиксель add esi,ecx ;сдвигаем указатель с копируемыми данными, с учетом пропушеной части xor ecx,ecx ;обнуляем координату coord_y @@: cmp ecx,ebx jge .copy_end ;если координата 'y' больше высоты буфера add ecx,edx ;ecx - нижняя координата копируемой картинки cmp ecx,ebx jle @f sub ecx,ebx sub edx,ecx ;уменьшаем высоту копируемой картинки, в случе когда она вылазит за нижнюю границу @@: mov ebx,buf2d_w mov ecx,ebx ;ecx используем для временных целей cmp [coord_y],0 jg .end_otr_c_y ;если координата coord_y<=0 (2-я настройка) mov ecx,[coord_x] jmp @f .end_otr_c_y: imul ecx,[coord_y] add ecx,[coord_x] @@: lea ecx,[ecx+ecx*2] add ecx,buf2d_data sub ebx,eax mov edi,ecx ;edi указатель на данные буфера, куда будет производится копирование mov dword[lost_bytes],0 mov ecx,[coord_x] cmp ecx,0 jge @f neg ecx ;inc ecx cmp eax,ecx ;eax - ширина копируемой картинки jle .copy_end ;если копируемое изображение находится полностью за левой границей буфера (coord_x<0 и |coord_x|>buf_source.w) shl ecx,2 mov [lost_bytes],ecx add esi,ecx shr ecx,2 sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера lea ecx,[ecx+ecx*2] add edi,ecx ;edi указатель на данные буфера, куда будет производится копирование xor ecx,ecx @@: cmp ecx,ebx jle @f sub ecx,ebx sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера shl ecx,2 ;ecx - число пикселей в 1-й строке картинки, которые вылазят за правую сторону add [lost_bytes],ecx @@: ; mov [right_bytes],0 ; mov ecx,[coord_x] ; cmp ecx,ebx ; jl @f ; sub ecx,ebx ; sub eax,ecx ;укорачиваем копируемую строку ; add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера ; shl ecx,2 ;ecx - число байт в 1-й строке картинки, которые вылазят за правую сторону ; mov [right_bytes],ecx ; @@: lea ebx,[ebx+ebx*2] ;колличество байт в 1-й строке буфера минус число байт в 1-й строке копируемой картинки cld cmp [lost_bytes],0 jg .copy_1 .copy_0: ;простое копирование mov ecx,eax @@: call combine_colors_0 add edi,3 add esi,4 loop @b add edi,ebx dec edx cmp edx,0 jg .copy_0 jmp .copy_end .copy_1: ;не простое копирование (картинка вылазит за правую сторону) mov ecx,eax @@: call combine_colors_0 add edi,3 add esi,4 loop @b add edi,ebx add esi,[lost_bytes] ;добавляем байты, которые вылазят за правую границу dec edx cmp edx,0 jg .copy_1 .copy_end: popad ret endp ;input: ; ebx - color1 ; esi = pointer to transparent ; edi = pointer to background color2 ;output: ; [edi] = combine color align 4 combine_colors_2: push ax ebx cx dx si mov cl,byte[esi] ;pro xor ch,ch mov si,0x00ff ;---get transparent--- sub si,cx ;256-pro ;---blye--- movzx ax,bl shr ebx,8 imul ax,si movzx dx,byte[edi] imul dx,cx add ax,dx mov byte[edi],ah ;---green--- movzx ax,bl shr ebx,8 imul ax,si movzx dx,byte[edi+1] imul dx,cx add ax,dx mov byte[edi+1],ah ;---red--- movzx ax,bl imul ax,si movzx dx,byte[edi+2] imul dx,cx add ax,dx mov byte[edi+2],ah pop si dx cx ebx ax ret ;функция копирует изображение из буфера buf_source (8b) в buf_destination (24b) ; указываются координаты вставки буфера buf_source относительно buf_destination align 4 proc buf_bit_blt_alpha, buf_destination:dword, coord_x:dword, coord_y:dword, buf_source:dword, color:dword locals lost_bytes dd ? ;число потерянных байтов в строке копируемого изображеня (тех что не влазят в буфер) dest_w_bytes dd ? ;колличество байт в буфере приемнике по ширине - ширина вставляемой картинки endl pushad mov edi,[buf_source] cmp buf2d_bits,8 jne .error1 ;формат буфера не поодерживается mov eax,buf2d_w ;ширина копируемой картинки mov edx,buf2d_h ;высота копируемой картинки mov esi,buf2d_data ;данные копируемой картинки mov edi,[buf_destination] cmp buf2d_bits,24 jne .error2 ;формат буфера не поодерживается mov ebx,[coord_x] ;в ebx временно ставим отступ изображения (для проверки) cmp ebx,buf2d_w ;проверяем влазит ли изображение по ширине jge .copy_end ;если изображение полностью вылазит за правую сторону mov ebx,buf2d_h ;ebx - высота основного буфера mov ecx,[coord_y] cmp ecx,0 jge @f ;если координата coord_y<0 (1-я настройка) add edx,ecx ;уменьшаем высоту копируемой картинки cmp edx,0 jle .copy_end ;если копируемое изображение находится полностью над верхней границей буфера (coord_y<0 и |coord_y|>buf_source.h) neg ecx ;inc ecx imul ecx,eax add esi,ecx ;сдвигаем указатель с копируемыми данными, с учетом пропушеной части xor ecx,ecx ;обнуляем координату coord_y @@: cmp ecx,ebx jge .copy_end ;если координата 'y' больше высоты буфера add ecx,edx ;ecx - нижняя координата копируемой картинки cmp ecx,ebx jle @f sub ecx,ebx sub edx,ecx ;уменьшаем высоту копируемой картинки, в случе когда она вылазит за нижнюю границу @@: mov ebx,buf2d_w mov ecx,[coord_y] ;ecx используем для временных целей cmp ecx,0 jg .end_otr_c_y ;если координата coord_y<=0 (2-я настройка) mov ecx,[coord_x] jmp @f .end_otr_c_y: imul ecx,ebx add ecx,[coord_x] @@: lea ecx,[ecx+ecx*2] add ecx,buf2d_data ;buf2d_data данные основного буфера sub ebx,eax ;ebx - ширина основного буфера минус ширина рисуемого буфера mov edi,ecx ;edi указатель на данные буфера, куда будет производится копирование mov dword[lost_bytes],0 mov ecx,[coord_x] cmp ecx,0 jge @f neg ecx ;inc ecx cmp eax,ecx ;eax - ширина копируемой картинки jle .copy_end ;если копируемое изображение находится полностью за левой границей буфера (coord_x<0 и |coord_x|>buf_source.w) mov [lost_bytes],ecx sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера add esi,ecx lea ecx,[ecx+ecx*2] add edi,ecx ;edi указатель на данные буфера, куда будет производится копирование xor ecx,ecx @@: cmp ecx,ebx jle @f sub ecx,ebx sub eax,ecx ;укорачиваем копируемую строку add ebx,ecx ;удлинняем строку для сдвига главной картинки буфера ;ecx - число пикселей в 1-й строке картинки, которые вылазят за правую сторону add [lost_bytes],ecx @@: lea ebx,[ebx+ebx*2] ;колличество байт в 1-й строке буфера минус число байт в 1-й строке копируемой картинки mov [dest_w_bytes],ebx mov ebx,[color] cld cmp dword[lost_bytes],0 jg .copy_1 .copy_0: ;простое копирование mov ecx,eax @@: call combine_colors_2 add edi,3 inc esi loop @b add edi,[dest_w_bytes] dec edx cmp edx,0 jg .copy_0 jmp .copy_end .copy_1: ;не простое копирование (картинка вылазит за левую и/или правую сторону) mov ecx,eax @@: call combine_colors_2 add edi,3 inc esi loop @b add edi,[dest_w_bytes] add esi,[lost_bytes] ;добавляем байты, которые вылазят за правую границу dec edx cmp edx,0 jg .copy_1 jmp .copy_end .error1: stdcall print_err,sz_buf2d_bit_blt_alpha,txt_err_n8b jmp .copy_end .error2: stdcall print_err,sz_buf2d_bit_blt_alpha,txt_err_n24b .copy_end: popad ret endp align 4 proc print_err, fun:dword, mes:dword ;выводим сообщение об шибке на доску отладки pushad mov eax,63 mov ebx,1 mov esi,[fun] @@: mov cl,byte[esi] int 0x40 inc esi cmp byte[esi],0 jne @b mov cl,':' int 0x40 mov cl,' ' int 0x40 mov esi,[mes] @@: mov cl,byte[esi] int 0x40 inc esi cmp byte[esi],0 jne @b popad ret endp ;фильтр align 4 proc buf_filter_dither, buffer:dword, algor:dword pushad mov edi,[buffer] cmp buf2d_bits,24 jne .error mov edx,buf2d_w mov esi,buf2d_h mov edi,buf2d_data ;edi - pointer to 24bit bitmap ;edx - x size ;esi - y size lea edx,[edx+edx*2] imul esi,edx ;определяем какой алгоритм использовать cmp dword[algor],0 jne @f call dither_0 jmp .dither_end @@: cmp dword[algor],1 jne @f call dither_1 jmp .dither_end @@: cmp dword[algor],2 jne @f call dither_2 jmp .dither_end @@: cmp dword[algor],3 jne @f call dither_3 jmp .dither_end @@: call dither_4 jmp .dither_end .error: stdcall print_err,sz_buf2d_filter_dither,txt_err_n24b .dither_end: popad ret endp align 16 dither_0: ; Sierra Filter Lite algorithm newp_0: ; Dithering cycle xor ebx,ebx ; At first threshold movzx ecx,byte[edi] cmp cl,255 je newp_0.next test cl,cl jz newp_0.next jns @f dec ebx sub ecx,255 @@: mov [edi],bl ; putpixel sar ecx,1 ; error/2 ;adc ecx,0 ; round to integer movzx eax,byte[edi+3] ; pixel (x+1;y) add eax,ecx ; add error/2 to (x+1;y) jge @f ; check_overflow xor eax,eax jmp .ok @@: cmp eax,255 jle .ok or al,255 .ok: mov [edi+3],al ; putpixel sar ecx,1 ; error/4 adc ecx,0 ; round to integer movzx eax,byte[edi+edx-3] ; pixel (x-1;y+1) add eax,ecx ; add error/4 to (x-1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok1 @@: cmp eax,255 jle .ok1 or al,255 .ok1: mov [edi+edx-3],al ; putpixel movzx eax,byte[edi+edx] ; pixel (x;y+1) add eax,ecx ; add error/4 to (x;y+1) jge @f ; check_overflow xor eax,eax jmp .ok2 @@: cmp eax,255 jle .ok2 or al,255 .ok2: mov [edi+edx],al ; putpixel .next: inc edi dec esi jnz newp_0 ret align 16 dither_1: ; Floyd-Steinberg algorithm newp_1: ; Dithering cycle xor ebx,ebx ; At first threshold movzx ecx,byte[edi] cmp cl,255 je newp_1.next test cl,cl jz newp_1.next jns @f dec ebx sub ecx,255 @@: mov [edi],bl ; putpixel sar ecx,4 ; error/16 adc ecx,0 ; round to integer mov ebx,ecx movzx eax,byte[edi+edx+3] ; pixel (x+1;y+1) add eax,ecx ; add error/16 to (x+1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok @@: cmp eax,255 jle .ok or al,255 .ok: mov [edi+edx+3],al ;putpixel imul ecx,3 movzx eax,byte[edi+edx-3] ; pixel (x-1;y+1) add eax,ecx ; add 3*error/16 to (x-1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok1 @@: cmp eax,255 jle .ok1 or al,255 .ok1: mov [edi+edx-3],al ;putpixel mov ecx,ebx imul ecx,5 movzx eax,byte[edi+edx] ; pixel (x;y+1) add eax,ecx ; add 5*error/16 to (x;y+1) jge @f ; check_overflow xor eax,eax jmp .ok2 @@: cmp eax,255 jle .ok2 or al,255 .ok2: mov [edi+edx],al ;putpixel mov ecx,ebx imul ecx,7 movzx eax,byte[edi+3] ; pixel (x+1;y) add eax,ecx ; add 7*error/16 to (x+1;y) jge @f ; check_overflow xor eax,eax jmp .ok3 @@: cmp eax,255 jle .ok3 or al,255 .ok3: mov [edi+3],al ;putpixel .next: inc edi dec esi jnz newp_1 ret align 16 dither_2: ; Burkes algorithm newp_2: ; Dithering cycle xor ebx,ebx ; At first threshold movsx ecx,byte[edi] cmp cl,255 je newp_2.next test cl,cl jz newp_2.next jns @f dec ebx @@: mov [edi],bl ; putpixel sar ecx,2 ; error/4 adc ecx,0 ; round to integer movzx eax,byte[edi+3] ; pixel (x+1;y) add eax,ecx ; add error/4 to (x+1;y) jge @f ; check_overflow xor eax,eax jmp .ok @@: cmp eax,255 jle .ok or al,255 .ok: mov [edi+3],al ; putpixel movzx eax,byte[edi+edx] ; pixel (x;y+1) add eax,ecx ; add error/4 to (x;y+1) jge @f ; check_overflow xor eax,eax jmp .ok1 @@: cmp eax,255 jle .ok1 or al,255 .ok1: mov [edi+edx],al ; putpixel sar ecx,1 ; error/8 adc ecx,0 ; round to integer movzx eax,byte[edi+6] ; pixel (x+2;y) add eax,ecx ; add error/8 to (x+2;y) jge @f ; check_overflow xor eax,eax jmp .ok2 @@: cmp eax,255 jle .ok2 or al,255 .ok2: mov [edi+6],al ; putpixel movzx eax,byte[edi+edx-3] ; pixel (x-1;y+1) add eax,ecx ; add error/8 to (x-1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok3 @@: cmp eax,255 jle .ok3 or al,255 .ok3: mov [edi+edx-3],al ; putpixel movzx eax,byte[edi+edx+3] ; pixel (x+1;y+1) add eax,ecx ; add error/8 to (x+1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok4 @@: cmp eax,255 jle .ok4 or al,255 .ok4: mov [edi+edx+3],al ; putpixel sar ecx,1 ; error/16 ;adc ecx,0 ; round to integer movzx eax,byte[edi+edx-6] ; pixel (x-2;y+1) add eax,ecx ; add error/16 to (x-2;y+1) jge @f ; check_overflow xor eax,eax jmp .ok5 @@: cmp eax,255 jle .ok5 or al,255 .ok5: mov [edi+edx-6],al ; putpixel movzx eax,byte[edi+edx+6] ; pixel (x+2;y+1) add eax,ecx ; add error/16 to (x+2;y+1) jge @f ; check_overflow xor eax,eax jmp .ok6 @@: cmp eax,255 jle .ok6 or al,255 .ok6: mov [edi+edx+6],al ; putpixel .next: inc edi dec esi jnz newp_2 ret align 16 dither_3: ; Heavyiron_mod algorithm newp_3: ; Dithering cycle xor ebx,ebx ; At first threshold movzx ecx,byte[edi] cmp cl,255 je .next test cl,cl jz .next jns @f dec ebx sub ecx,255 @@: mov [edi],bl ; putpixel sar ecx,2 ; error/4 movzx eax,byte[edi+3] ; pixel (x+1;y) add eax,ecx ; add error/4 to (x+1;y) jge @f ; check_overflow xor eax,eax jmp .ok @@: cmp eax,255 jle .ok or al,255 .ok: mov [edi+3],al ; putpixel movzx eax,byte[edi+edx-3] ; pixel (x-1;y+1) add eax,ecx ; add error/4 to (x-1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok1 @@: cmp eax,255 jle .ok1 or al,255 .ok1: mov [edi+edx-3],al ; putpixel movzx eax,byte[edi+edx] ; pixel (x;y+1) add eax,ecx ; add error/4 to (x;y+1) jge @f ; check_overflow xor eax,eax jmp .ok2 @@: cmp eax,255 jle .ok2 or al,255 .ok2: mov [edi+edx],al ; putpixel .next: inc edi dec esi jnz newp_3 ret align 16 dither_4: ; Atkinson algorithm newp_4: ; Dithering cycle xor ebx,ebx ; At first threshold movsx ecx,byte[edi] cmp cl,255 je .next test cl,cl jz .next jns @f dec ebx @@: mov [edi],bl ; putpixel sar ecx,3 ; error/8 movzx eax,byte[edi+3] ; pixel (x+1;y) add eax,ecx ; add error/8 to (x+1;y) jge @f ; check_overflow xor eax,eax jmp .ok @@: cmp eax,255 jle .ok or al,255 .ok: mov [edi+3],al ; putpixel movzx eax,byte[edi+edx] ; pixel (x;y+1) add eax,ecx ; add error/8 to (x;y+1) jge @f ; check_overflow xor eax,eax jmp .ok1 @@: cmp eax,255 jle .ok1 or al,255 .ok1: mov [edi+edx],al ; putpixel movzx eax,byte[edi+6] ; pixel (x+2;y) add eax,ecx ; add error/8 to (x+2;y) jge @f ; check_overflow xor eax,eax jmp .ok2 @@: cmp eax,255 jle .ok2 or al,255 .ok2: mov [edi+6],al ; putpixel movzx eax,byte[edi+edx-3] ; pixel (x-1;y+1) add eax,ecx ; add error/8 to (x-1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok3 @@: cmp eax,255 jle .ok3 or al,255 .ok3: mov [edi+edx-3],al ; putpixel movzx eax,byte[edi+edx+3] ; pixel (x+1;y+1) add eax,ecx ; add error/8 to (x+1;y+1) jge @f ; check_overflow xor eax,eax jmp .ok4 @@: cmp eax,255 jle .ok4 or al,255 .ok4: mov [edi+edx+3],al ; putpixel movzx eax,byte[edi+edx+edx] ; pixel (x;y+2) add eax,ecx ; add error/8 to (x;y+2) jge @f ; check_overflow xor eax,eax jmp .ok5 @@: cmp eax,255 jle .ok5 or al,255 .ok5: mov [edi+edx+edx],al ; putpixel .next: inc edi dec esi jnz newp_4 ret include 'fun_voxel.inc' ;функции для работы с воксельной графикой txt_err_size_0 db 'image size < 1 pixel',13,10,0 txt_err_n8b db 'need buffer 8 bit',13,10,0 txt_err_n24b db 'need buffer 24 bit',13,10,0 txt_err_n32b db 'need buffer 32 bit',13,10,0 txt_err_n8_24b db 'need buffer 8 or 24 bit',13,10,0 align 16 EXPORTS: dd sz_lib_init, lib_init dd sz_buf2d_create, buf_create dd sz_buf2d_create_f_img, buf_create_f_img dd sz_buf2d_clear, buf_clear dd sz_buf2d_draw, buf_draw_buf dd sz_buf2d_delete, buf_delete dd sz_buf2d_resize, buf_resize dd sz_buf2d_rotate, buf_rotate dd sz_buf2d_line, buf_line_brs dd sz_buf2d_line_sm, buf_line_brs_sm dd sz_buf2d_rect_by_size, buf_rect_by_size dd sz_buf2d_filled_rect_by_size, buf_filled_rect_by_size dd sz_buf2d_circle, buf_circle dd sz_buf2d_img_hdiv2, buf_img_hdiv2 dd sz_buf2d_img_wdiv2, buf_img_wdiv2 dd sz_buf2d_conv_24_to_8, buf_conv_24_to_8 dd sz_buf2d_conv_24_to_32, buf_conv_24_to_32 dd sz_buf2d_bit_blt, buf_bit_blt dd sz_buf2d_bit_blt_transp, buf_bit_blt_transp dd sz_buf2d_bit_blt_alpha, buf_bit_blt_alpha dd sz_buf2d_curve_bezier, buf_curve_bezier dd sz_buf2d_convert_text_matrix, buf_convert_text_matrix dd sz_buf2d_draw_text, buf_draw_text dd sz_buf2d_crop_color, buf_crop_color dd sz_buf2d_offset_h, buf_offset_h dd sz_buf2d_flood_fill, buf_flood_fill dd sz_buf2d_set_pixel, buf_set_pixel dd sz_buf2d_get_pixel, buf_get_pixel dd sz_buf2d_flip_h, buf_flip_h dd sz_buf2d_flip_v, buf_flip_v dd sz_buf2d_filter_dither, buf_filter_dither dd sz_buf2d_vox_brush_create, vox_brush_create dd sz_buf2d_vox_brush_delete, vox_brush_delete dd sz_buf2d_vox_obj_get_img_w_3g, buf_vox_obj_get_img_w_3g dd sz_buf2d_vox_obj_get_img_h_3g, buf_vox_obj_get_img_h_3g dd sz_buf2d_vox_obj_draw_1g, buf_vox_obj_draw_1g dd sz_buf2d_vox_obj_draw_3g, buf_vox_obj_draw_3g dd sz_buf2d_vox_obj_draw_3g_scaled, buf_vox_obj_draw_3g_scaled dd sz_buf2d_vox_obj_draw_pl, buf_vox_obj_draw_pl dd sz_buf2d_vox_obj_draw_pl_scaled, buf_vox_obj_draw_pl_scaled dd sz_buf2d_vox_obj_draw_3g_shadows, buf_vox_obj_draw_3g_shadows dd 0,0 sz_lib_init db 'lib_init',0 sz_buf2d_create db 'buf2d_create',0 sz_buf2d_create_f_img db 'buf2d_create_f_img',0 sz_buf2d_clear db 'buf2d_clear',0 ;очистка буфера указанным цветом sz_buf2d_draw db 'buf2d_draw',0 sz_buf2d_delete db 'buf2d_delete',0 sz_buf2d_resize db 'buf2d_resize',0 sz_buf2d_rotate db 'buf2d_rotate',0 sz_buf2d_line db 'buf2d_line',0 ;рисование линии sz_buf2d_line_sm db 'buf2d_line_sm',0 ;рисование сглаженной линии sz_buf2d_rect_by_size db 'buf2d_rect_by_size',0 ;рисование рамки прямоугольника, 2-я координата задана по размеру sz_buf2d_filled_rect_by_size db 'buf2d_filled_rect_by_size',0 ;рисование залитого прямоугольника, 2-я координата задана по размеру sz_buf2d_circle db 'buf2d_circle',0 ;рисование окружности sz_buf2d_img_hdiv2 db 'buf2d_img_hdiv2',0 ;сжатие изображения по высоте в 2 раза (размер буфера не меняется) sz_buf2d_img_wdiv2 db 'buf2d_img_wdiv2',0 ;сжатие изображения по ширине в 2 раза (размер буфера не меняется) sz_buf2d_conv_24_to_8 db 'buf2d_conv_24_to_8',0 sz_buf2d_conv_24_to_32 db 'buf2d_conv_24_to_32',0 sz_buf2d_bit_blt db 'buf2d_bit_blt',0 sz_buf2d_bit_blt_transp db 'buf2d_bit_blt_transp',0 sz_buf2d_bit_blt_alpha db 'buf2d_bit_blt_alpha',0 sz_buf2d_curve_bezier db 'buf2d_curve_bezier',0 sz_buf2d_convert_text_matrix db 'buf2d_convert_text_matrix',0 sz_buf2d_draw_text db 'buf2d_draw_text',0 sz_buf2d_crop_color db 'buf2d_crop_color',0 sz_buf2d_offset_h db 'buf2d_offset_h',0 sz_buf2d_flood_fill db 'buf2d_flood_fill',0 sz_buf2d_set_pixel db 'buf2d_set_pixel',0 sz_buf2d_get_pixel db 'buf2d_get_pixel',0 sz_buf2d_flip_h db 'buf2d_flip_h',0 sz_buf2d_flip_v db 'buf2d_flip_v',0 sz_buf2d_filter_dither db 'buf2d_filter_dither',0 sz_buf2d_vox_brush_create db 'buf2d_vox_brush_create',0 sz_buf2d_vox_brush_delete db 'buf2d_vox_brush_delete',0 sz_buf2d_vox_obj_get_img_w_3g db 'buf2d_vox_obj_get_img_w_3g',0 sz_buf2d_vox_obj_get_img_h_3g db 'buf2d_vox_obj_get_img_h_3g',0 sz_buf2d_vox_obj_draw_1g db 'buf2d_vox_obj_draw_1g',0 sz_buf2d_vox_obj_draw_3g db 'buf2d_vox_obj_draw_3g',0 sz_buf2d_vox_obj_draw_3g_scaled db 'buf2d_vox_obj_draw_3g_scaled',0 sz_buf2d_vox_obj_draw_pl db 'buf2d_vox_obj_draw_pl',0 sz_buf2d_vox_obj_draw_pl_scaled db 'buf2d_vox_obj_draw_pl_scaled',0 sz_buf2d_vox_obj_draw_3g_shadows db 'buf2d_vox_obj_draw_3g_shadows',0