Блюр-эффект

Тема в разделе "WASM.DOS/BIOS/Vesa/ports", создана пользователем Mikl___, 24 дек 2016.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786

    Блюр-эффект

    Довольно простой эффект, как раз для начинающих. К тому же, этот эффект лежит в основе целого семейства эффектов, и знать его необходимо!
    Blur, в переводе с английского: неясные очертания, размытое пятно.
    Допустим, у нас есть некое изображение размером 320x200x8bit, в буфере экрана screen. Создаем дополнительный буфер экрана, buffer.
    Цвет точки с координатами X,Y в массиве buffer будет рассчитываться по формуле: цвет_точки = среднее арифметическое от значений цвета точек, окружающих точку с координатами X,Y в массиве screen.
    После применения данной формулы ко всем точкам массива buffer, в этом массиве будет находиться сBlur-енное изображение.
    Некоторые замечания:
    1. Естественно, палитра должна содержать плавные переходы от цвета к цвету, иначе вместо сBlur-енного изображения получим невесть что:).
    2. Если это условие не выполняется, то надо преобразовать исходное изображение в Hi или TrueColor и производить размыв изображения отдельно для каждого цвета.
    3. При получении размытого изображения значения цвета на границах buffer не рассчитывается, иначе нам бы пришлось бы залезть за границы массива screen.
    Пример:
    Код (C):
    1. for(short y=1;y<199;y++)
    2.   for(short x=1;x<319;x++)
    3.     buffer[x][y]=(screen[x-1][y+1]+screen[x-1][y]+
    4.                   screen[x-1][y-1]+screen[x][y+1]+
    5.                   screen[x][y-1]+screen[x+1][y+1]+
    6.                   screen[x+1][y]+screen[x+1][y-1])/8;
    В данном примере мы усредняем значение цвета 8 точек, в принципе выбор точек, по которым мы находим усредненное значение цвета, за вами. Например, для более высокой скорости можно выбрать только 4 близлежащих точки:
    Код (C):
    1. buffer[x][y]=(screen[x-1][y]+screen[x][y+1]+
    2.                    screen[x][y-1]+screen[x+1][y])/4;
    Но тогда появляется неприятный побочный эффект: в местах плавных переходов цветов появляется решетка... В общем, не знаю как объяснить, попробуйте и увидите сами.
    Как от этого избавиться? В true блюре - никак. Но есть вариант блюра, в котором этот эффект не появляется:
    Код (C):
    1.   screen[x][y]=(screen[x-1][y]+screen[x][y+1]+
    2.                   screen[x][y-1]+screen[x+1][y])/4;
    Относительно true блюра имеем:

    Преимущества:


    1. Скорость
    2. Отпадает необходимость использования дополнительного frame-буфера.

    Недостаток:

    Искажение геометрических соотношений изображения.
    Обычно такой вариант Blur`a используется для улучшения качества картинки, на различных стадиях вывода изображения.
    Взято здесь, текст программы немного переделан, в результате СОМ-файл уменьшился с 498 байт до 408 байт.
    Код (ASM):
    1. ; masm dos com #
    2. .model tiny
    3. .code
    4. .686p
    5. .mmx
    6. WIDTH_SCREEN    equ 320
    7. HEIGHT_SCREEN   equ 200
    8. SCREENSIZE  equ WIDTH_SCREEN*HEIGHT_SCREEN
    9. MEMBLOCKSIZE    equ SCREENSIZE/16
    10. IMPUT_STATUS_0  equ 3DAh    ;регистр статуса ввода 0
    11. VGA_SEGMENT equ 0A000h
    12. screen      equ word ptr [bp-2]
    13. buffer          equ word ptr [bp-4]
    14. org 100h
    15. start:  mov sp,0B00h      ; ADJUST MEMORY BLOCK SIZE (SETBLOCK)
    16.     mov ah,4Ah        ; ES = segment address of block   to change
    17.     mov bx,0B0h       ; BX = new size   in paragraphs
    18.     int 21h
    19.     enter 4,0    
    20.     mov ax,13h
    21.     int 10h
    22. ;setcolortable-------------------------------
    23. ;   FOR(CL=0;CL<=63;CL++){
    24. ;       setrgbpalette(CL,CL,0,0);
    25. ;       setrgbpalette(CL+64,63,CL,0);
    26. ;       setrgbpalette(CL+128,63,63,CL);
    27. ;       setrgbpalette(CL+192,63,63,63);
    28.     mov cx,63
    29. @@: push    cx
    30.     push    cx
    31.     push    0
    32.     push    0
    33.     call    setrgbpalette
    34.     mov al, cl
    35.     add al,64
    36.     push    ax
    37.     push    63
    38.     push    cx
    39.     push    0
    40.     call    setrgbpalette
    41.     mov al,cl
    42.     add al,128
    43.     push    ax
    44.     push    63
    45.     push    63
    46.     push    cx
    47.     call    setrgbpalette
    48.     mov al,cl
    49.     add al,192
    50.     push    ax
    51.     push    63
    52.     push    63
    53.     push    63
    54.     call    setrgbpalette
    55.     dec cx
    56.     jns @b
    57. ;setcolortable--------------------------------
    58.     mov bx, MEMBLOCKSIZE
    59.     mov ah,48h ; ALLOCATE MEMORY
    60.     int 21h    ; BX = number of 16-byte paragraphs desired
    61.     mov screen, ax
    62.     mov bx, MEMBLOCKSIZE
    63.         mov ah,48h ; ALLOCATE MEMORY
    64.     int 21h    ; BX = number of 16-byte paragraphs desired
    65.     mov buffer, ax
    66. ;CLEARBLOCK------------------------------------------
    67.     mov es, ax
    68.     xor eax, eax
    69.     xor di, di
    70.     mov cx,SCREENSIZE/4
    71.     rep stosd
    72. ;fillscreen-------------------------------------------
    73.     mov es, screen
    74.     mov di,WIDTH_SCREEN+1
    75.     mov si,HEIGHT_SCREEN-2
    76.     or  ax,-1
    77. @@: mov cx,WIDTH_SCREEN/2 - 1
    78.     rep stosw
    79.     add di,2
    80.     dec si
    81.     jnz @b
    82. ;trueblurscreen----------------------------------------
    83. ;   ES=screen;
    84. ;   FS=buffer;
    85. ;   DI=321;
    86. ;   FOR(SI=1;SI<199;SI++){
    87. ;       FOR(BX=1;BX<319;BX++,DI++){
    88. ;           FSBYTE[DI]=int ESBYTE[DI-321]+ESBYTE[DI-320]+ESBYTE[DI-319]+
    89. ;               ESBYTE[DI-1]+ESBYTE[DI+1]+ESBYTE[DI+319]+ESBYTE[DI+320]+
    90. ;               ESBYTE[DI+321]>>3;
    91. a0: mov es,screen
    92.     mov fs,buffer
    93.     mov di, WIDTH_SCREEN+1
    94.     mov si,HEIGHT_SCREEN-2
    95. a1: mov bx,WIDTH_SCREEN-2
    96. @@: movzx   ax, byte ptr es:[di-WIDTH_SCREEN-1]
    97.     movzx   cx, byte ptr es:[di-WIDTH_SCREEN]
    98.     add ax, cx
    99.     movzx   cx, byte ptr es:[di-WIDTH_SCREEN+1]
    100.     add ax, cx
    101.     movzx   cx, byte ptr es:[di-1]
    102.     add ax, cx
    103.     movzx   cx, byte ptr es:[di+1]
    104.     add ax, cx
    105.     movzx   cx, byte ptr es:[di+WIDTH_SCREEN-1]
    106.     add ax, cx
    107.     movzx   cx, byte ptr es:[di+WIDTH_SCREEN]
    108.     add ax, cx
    109.     movzx   cx, byte ptr es:[di+WIDTH_SCREEN+1]
    110.     add ax, cx
    111.     sar ax, 3
    112.     mov fs:[di], al
    113.     inc di
    114.         dec bx
    115.     jnz @b
    116.     add di,2
    117.     dec si
    118.     jnz a1
    119. ;copybufferscreen---------------------------
    120.     push ds
    121.     mov ds,buffer
    122.     xor di,di
    123.     mov cx,SCREENSIZE/4
    124.     rep movsd
    125.     pop ds
    126.     call    copyvirtualscreen
    127.     jz  a0
    128.     mov ah, 0
    129.     int 16h     ; Return: AH = scan code, AL = character
    130. ;fillscreen------------------------------------------------
    131.     mov es, screen
    132.     mov di,WIDTH_SCREEN+1
    133.     mov si,HEIGHT_SCREEN-2
    134.     or  ax,-1
    135. @@: mov cx,WIDTH_SCREEN/2 - 1
    136.     rep stosw
    137.     add di,2
    138.     dec si
    139.     jnz @b
    140. a2:;fastblurscreen
    141. ;ES=screen;
    142. ;   DI=321;
    143. ;   FOR(SI=1;SI<199;SI++){
    144. ;       FOR(BX=1;BX<319;BX++,DI++)
    145. ;ES:[DI]=(ES:[DI-320]+ES:[DI-1]+ES:[DI+1]+ES:[DI+320])/4
    146.     mov es,screen
    147.     mov di,WIDTH_SCREEN+1
    148.     mov si,HEIGHT_SCREEN-2
    149. a3: mov bx,WIDTH_SCREEN-2
    150. @@: movzx   ax,byte ptr es:[di-WIDTH_SCREEN]
    151.     movzx   cx,byte ptr es:[di-1]
    152.     add ax,cx
    153.     movzx   cx,byte ptr es:[di+1]
    154.     add ax,cx
    155.     movzx   cx,byte ptr es:[di+WIDTH_SCREEN]
    156.     add ax,cx
    157.     sar ax,2
    158.     mov es:[di], al
    159.     inc di
    160.     dec bx
    161.     jnz @b
    162.     add di,2
    163.     dec si
    164.     jnz a3
    165. ;fastblurscreen---------------------------------
    166.     call    copyvirtualscreen
    167.     jz  a2
    168.     mov ax,3
    169.     int 10h     ; - VIDEO - SET VIDEO MODE
    170.     mov ah,0
    171.     int 16h     ; KEYBOARD - READ CHAR FROM BUFFER, WAIT IF EMPTY
    172.     int 20h
    173.  
    174.  
    175. setrgbpalette   proc
    176.  
    177. blue        equ byte ptr  [bp+4]
    178. green       equ byte ptr  [bp+6]
    179. red     equ byte ptr  [bp+8]
    180. color       equ byte ptr  [bp+0Ah]
    181.  
    182.     push    bp
    183.     mov bp, sp
    184.     mov dx, 3C8h
    185.     mov al, color
    186.     mov ah, red
    187.     out dx, ax
    188.     inc dx
    189.     mov al, green
    190.     out dx, al
    191.     mov al, blue
    192.     out dx, al
    193.     pop bp
    194.     retn    8
    195. setrgbpalette   endp
    196.  
    197. copyvirtualscreen   proc
    198.     mov dx,IMPUT_STATUS_0
    199. WaitVerticalSync:in al,dx
    200.     test al,8
    201.     jz WaitVerticalSync
    202. WaitNotVerticalSync:in al,dx
    203.     test al,8
    204.     jnz WaitNotVerticalSync
    205.     mov cx,SCREENSIZE/4
    206.     xor si,si
    207.     push    ds
    208.     mov ds,screen
    209.     xor di,di
    210.     push    VGA_SEGMENT
    211.     pop es
    212.     rep movsd
    213.     xor ax, ax
    214.     mov ds, ax
    215.     mov ax, ds:[41Ah]
    216.     sub ax, ds:[41Ch]
    217.     pop ds
    218.     retn
    219. copyvirtualscreen   endp
    220. end start
     
    Последнее редактирование: 24 дек 2016
    >Quiet Snow< нравится это.