Subversion Repositories Kolibri OS

Rev

Rev 8463 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;============================================================================;;
  2. ;;//// libimg.asm //// (c) mike.dld, 2007-2008                                ;;
  3. ;;                //// (c) diamond, 2009,                                     ;;
  4. ;;                //// (c) dunkaist, 2011-2020                                ;;
  5. ;;============================================================================;;
  6. ;;                                                                            ;;
  7. ;; This file is part of Common development libraries (Libs-Dev).              ;;
  8. ;;                                                                            ;;
  9. ;; Libs-Dev is free software: you can redistribute it and/or modify it under  ;;
  10. ;; the terms of the GNU Lesser General Public License as published by the     ;;
  11. ;; Free Software Foundation, either version 2.1 of the License, or (at your   ;;
  12. ;; option) any later version.                                                 ;;
  13. ;;                                                                            ;;
  14. ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT    ;;
  15. ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      ;;
  16. ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public        ;;
  17. ;; License for more details.                                                  ;;
  18. ;;                                                                            ;;
  19. ;; You should have received a copy of the GNU Lesser General Public License   ;;
  20. ;; along with Libs-Dev. If not, see <http://www.gnu.org/licenses/>.           ;;
  21. ;;                                                                            ;;
  22. ;;============================================================================;;
  23.  
  24.  
  25. format MS COFF
  26.  
  27. public @EXPORT as 'EXPORTS'
  28.  
  29. include 'struct.inc'
  30. include 'proc32.inc'
  31. include 'macros.inc'
  32. include 'config.inc'
  33. include 'debug-fdo.inc'
  34. __DEBUG__ = 0
  35. __DEBUG_LEVEL__ = 1
  36. include 'libio.inc'
  37. purge section,mov,add,sub
  38.  
  39. include 'libimg.inc'
  40.  
  41. section '.flat' code readable align 16
  42.  
  43. include 'bmp/bmp.asm'
  44. include 'gif/gif.asm'
  45. include 'jpeg/jpeg.asm'
  46. include 'png/png.asm'
  47. include 'tga/tga.asm'
  48. include 'z80/z80.asm'
  49. include 'ico_cur/ico_cur.asm'
  50. include 'pcx/pcx.asm'
  51. include 'xcf/xcf.asm'
  52. include 'tiff/tiff.asm'
  53. include 'pnm/pnm.asm'
  54. include 'wbmp/wbmp.asm'
  55. include 'xbm/xbm.asm'
  56.  
  57. include 'scale.asm'
  58. include 'convert.asm'
  59.  
  60. COMPOSITE_MODE equ MMX
  61. ; MMX | pretty fast and compatible
  62. ; SSE | a bit faster, but may be unsupported by some CPUs
  63. include 'blend.asm'
  64.  
  65. ;;============================================================================;;
  66. proc lib_init ;///////////////////////////////////////////////////////////////;;
  67. ;;----------------------------------------------------------------------------;;
  68. ;? Library entry point (called after library load)                            ;;
  69. ;;----------------------------------------------------------------------------;;
  70. ;> eax = pointer to memory allocation routine                                 ;;
  71. ;> ebx = pointer to memory freeing routine                                    ;;
  72. ;> ecx = pointer to memory reallocation routine                               ;;
  73. ;> edx = pointer to library loading routine                                   ;;
  74. ;;----------------------------------------------------------------------------;;
  75. ;< eax = 1 (fail) / 0 (ok) (library initialization result)                    ;;
  76. ;;============================================================================;;
  77.         mov     [mem.alloc], eax
  78.         mov     [mem.free], ebx
  79.         mov     [mem.realloc], ecx
  80.         mov     [dll.load], edx
  81.  
  82.         or      edx, edx
  83.         jz      @f
  84.         invoke  dll.load, @IMPORT
  85. @@:
  86.  
  87.         call    img.initialize.jpeg
  88.  
  89.         xor     eax, eax
  90.         cpuid
  91.         cmp     ecx, 'ntel'
  92.         jnz     @f
  93.         mov     dword [img._.do_rgb.handlers + (Image.bpp15-1)*4], img._.do_rgb.bpp15.intel
  94.         mov     dword [img._.do_rgb.handlers + (Image.bpp16-1)*4], img._.do_rgb.bpp16.intel
  95. @@:
  96.  
  97. .ok:
  98.         xor     eax, eax
  99.         ret
  100. endp
  101.  
  102. ;;============================================================================;;
  103. proc img.is_img _data, _length ;//////////////////////////////////////////////;;
  104. ;;----------------------------------------------------------------------------;;
  105. ;? --- TBD ---                                                                ;;
  106. ;;----------------------------------------------------------------------------;;
  107. ;> --- TBD ---                                                                ;;
  108. ;;----------------------------------------------------------------------------;;
  109. ;< --- TBD ---                                                                ;;
  110. ;;============================================================================;;
  111.         push    ebx
  112.         mov     ebx, img.formats_table
  113. @@:
  114.         stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
  115.         or      eax, eax
  116.         jnz     @f
  117.         add     ebx, sizeof.FormatsTableEntry
  118.         cmp     dword[ebx], 0
  119.         jnz     @b
  120.         xor     eax, eax
  121. @@:
  122.         pop     ebx
  123.         ret
  124. endp
  125.  
  126. ;;============================================================================;;
  127. proc img.info _data, _length ;////////////////////////////////////////////////;;
  128. ;;----------------------------------------------------------------------------;;
  129. ;? --- TBD ---                                                                ;;
  130. ;;----------------------------------------------------------------------------;;
  131. ;> --- TBD ---                                                                ;;
  132. ;;----------------------------------------------------------------------------;;
  133. ;< --- TBD ---                                                                ;;
  134. ;;============================================================================;;
  135.         xor     eax, eax
  136.         ret
  137. endp
  138.  
  139. ;;============================================================================;;
  140. proc img.from_file _filename ;////////////////////////////////////////////////;;
  141. ;;----------------------------------------------------------------------------;;
  142. ;? load file from disk and decode it                                          ;;
  143. ;;----------------------------------------------------------------------------;;
  144. ;> [_filename] = file name as passed to libio                                 ;;
  145. ;;----------------------------------------------------------------------------;;
  146. ;< eax = 0 / pointer to image                                                 ;;
  147. ;;============================================================================;;
  148. locals
  149.         fd              dd ?
  150.         img_data_len    dd ?
  151.         img_data        dd ?    ; raw bytes
  152.         img             dd ?    ; Image pointer
  153. endl
  154.         push    ebx
  155.         mov     [img], 0
  156.         invoke  file.open, [_filename], O_READ
  157.         mov     [fd], eax
  158.         test    eax, eax
  159.         jz      .exit
  160.         invoke  file.size, [_filename]
  161.         test    eax, eax
  162.         jnz     .exit_close
  163.         mov     [img_data_len], ebx
  164.         invoke  mem.alloc, ebx
  165.         test    eax, eax
  166.         jz      .exit_close
  167.         mov     [img_data], eax
  168.         invoke  file.read, [fd], eax, [img_data_len]
  169.         cmp     eax, -1
  170.         jz      .exit_free_close
  171.         cmp     eax, [img_data_len]
  172.         jnz     .exit_free_close
  173.         stdcall img.decode, [img_data], [img_data_len], 0
  174.         test    eax, eax
  175.         jz      .exit_free_close
  176.         mov     [img], eax
  177. .exit_free_close:
  178.         invoke  mem.free, [img_data]
  179. .exit_close:
  180.         invoke  file.close, [fd]
  181.         mov     eax, [img]
  182. .exit:
  183.         pop     ebx
  184.         ret
  185. endp
  186.  
  187. ;;============================================================================;;
  188. proc img.to_file _img, _filename ;////////////////////////////////////////////;;
  189. ;;----------------------------------------------------------------------------;;
  190. ;? --- TBD ---                                                                ;;
  191. ;;----------------------------------------------------------------------------;;
  192. ;> --- TBD ---                                                                ;;
  193. ;;----------------------------------------------------------------------------;;
  194. ;< eax = false / true                                                         ;;
  195. ;;============================================================================;;
  196.         xor     eax, eax
  197.         ret
  198. endp
  199.  
  200. ;;============================================================================;;
  201. proc img.from_rgb _rgb_data ;/////////////////////////////////////////////////;;
  202. ;;----------------------------------------------------------------------------;;
  203. ;? --- TBD ---                                                                ;;
  204. ;;----------------------------------------------------------------------------;;
  205. ;> --- TBD ---                                                                ;;
  206. ;;----------------------------------------------------------------------------;;
  207. ;< eax = 0 / pointer to image                                                 ;;
  208. ;;============================================================================;;
  209.         xor     eax, eax
  210.         ret
  211. endp
  212.  
  213. ;;============================================================================;;
  214. proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////;;
  215. ;;----------------------------------------------------------------------------;;
  216. ;? decodes image data into RGB triplets and stores them where [_out] points to;;
  217. ;;----------------------------------------------------------------------------;;
  218. ;> [_img] = pointer to source image                                           ;;
  219. ;> [_out] = where to store RGB triplets                                       ;;
  220. ;;----------------------------------------------------------------------------;;
  221. ;< none                                                                       ;;
  222. ;;============================================================================;;
  223.         push    esi edi
  224.         mov     esi, [_img]
  225.         stdcall img._.validate, esi
  226.         or      eax, eax
  227.         jnz     .ret
  228.         mov     edi, [_out]
  229.         call    img._.do_rgb
  230. .ret:
  231.         pop     edi esi
  232.         ret
  233. endp
  234.  
  235. ;;============================================================================;;
  236. proc img.to_rgb _img ;////////////////////////////////////////////////////////;;
  237. ;;----------------------------------------------------------------------------;;
  238. ;? decodes image data into RGB triplets and returns pointer to memory area of ;;
  239. ;? following structure:                                                       ;;
  240. ;? width  dd ?                                                                ;;
  241. ;? height dd ?                                                                ;;
  242. ;? rgb triplets                                                               ;;
  243. ;;----------------------------------------------------------------------------;;
  244. ;> [_img] = pointer to source image                                           ;;
  245. ;;----------------------------------------------------------------------------;;
  246. ;< eax = 0 / pointer to rgb_data (array of [rgb] triplets)                    ;;
  247. ;;============================================================================;;
  248.         push    esi edi
  249.         mov     esi, [_img]
  250.         stdcall img._.validate, esi
  251.         or      eax, eax
  252.         jnz     .error
  253.  
  254.         mov     esi, [_img]
  255.         mov     ecx, [esi + Image.Width]
  256.         imul    ecx, [esi + Image.Height]
  257.         lea     eax, [ecx * 3 + 4 * 3]
  258.         invoke  mem.alloc, eax
  259.         or      eax, eax
  260.         jz      .error
  261.  
  262.         mov     edi, eax
  263.         push    eax
  264.         mov     eax, [esi + Image.Width]
  265.         stosd
  266.         mov     eax, [esi + Image.Height]
  267.         stosd
  268.         call    img._.do_rgb
  269.         pop     eax
  270.         pop     edi esi
  271.         ret
  272.  
  273. .error:
  274.         xor     eax, eax
  275.         pop     edi esi
  276.         ret
  277. endp
  278.  
  279. ;;============================================================================;;
  280. proc img._.do_rgb ;///////////////////////////////////////////////////////////;;
  281. ;;----------------------------------------------------------------------------;;
  282. ;? decodes [esi + Image.Data] data into RGB triplets and stores them at [edi] ;;
  283. ;;----------------------------------------------------------------------------;;
  284. ;> esi = pointer to source image                                              ;;
  285. ;> edi = pointer to memory to store RGB triplets                              ;;
  286. ;;----------------------------------------------------------------------------;;
  287. ;< none                                                                       ;;
  288. ;;============================================================================;;
  289.         mov     ecx, [esi + Image.Width]
  290.         imul    ecx, [esi + Image.Height]
  291.         mov     eax, [esi + Image.Type]
  292.         jmp     dword [.handlers + (eax-1)*4]
  293.  
  294. align 16
  295. .bpp8i:
  296. ; 8 BPP WITH PALETTE -> 24 BPP
  297.         push    ebx
  298.         mov     ebx, [esi + Image.Palette]
  299.         mov     esi, [esi + Image.Data]
  300.         sub     ecx, 1
  301.         jz      .bpp8i.last
  302. @@:
  303.         movzx   eax, byte [esi]
  304.         add     esi, 1
  305.         mov     eax, [ebx + eax*4]
  306.         mov     [edi], eax
  307.         add     edi, 3
  308.         sub     ecx, 1
  309.         jnz     @b
  310. .bpp8i.last:
  311.         movzx   eax, byte [esi]
  312.         mov     eax, [ebx + eax*4]
  313.         mov     [edi], ax
  314.         shr     eax, 16
  315.         mov     [edi+2], al
  316.         pop     ebx
  317.         ret
  318.  
  319. align 16
  320. .bpp8g:
  321. ; 8 BPP GRAYSCALE -> 24 BPP
  322.         mov     esi, [esi + Image.Data]
  323. @@:
  324.         lodsb
  325.         mov     ah, al
  326.         stosb
  327.         stosw
  328.         dec     ecx
  329.         jnz     @b
  330.         ret
  331. ;
  332. ;align 16
  333. ;.bpp8a: ; considered application layer, may be changed in the future
  334. ;; 8a BPP -> 24 BPP
  335. ;    mov esi, [esi + Image.Data]
  336. ;@@:
  337. ;    lodsw
  338. ;    mov ah, al
  339. ;    stosb
  340. ;    stosw
  341. ;    dec ecx
  342. ;    jnz @b
  343. ;    ret
  344.  
  345. ; 15 BPP -> 24 BPP
  346. .bpp15.intel:
  347.         push    ebx ebp
  348.         sub     ecx, 4
  349.         jb      .bpp15.tail
  350. align 16
  351. .bpp15.intel.loop:
  352. repeat 2
  353.         mov     ebx, [esi]
  354.         mov     al, [esi]
  355.         mov     ah, [esi+1]
  356.         add     esi, 4
  357.         and     al, 0x1F
  358.         and     ah, 0x1F shl 2
  359.         mov     ebp, ebx
  360.         mov     dl, al
  361.         mov     dh, ah
  362.         shr     al, 2
  363.         shr     ah, 4
  364.         shl     dl, 3
  365.         shl     dh, 1
  366.         and     ebp, 0x1F shl 5
  367.         add     al, dl
  368.         add     ah, dh
  369.         shr     ebp, 2
  370.         mov     [edi], al
  371.         mov     [edi+2], ah
  372.         mov     eax, ebx
  373.         mov     ebx, ebp
  374.         shr     eax, 16
  375.         shr     ebx, 5
  376.         add     ebx, ebp
  377.         mov     ebp, eax
  378.         mov     [edi+1], bl
  379.         and     eax, (0x1F) or (0x1F shl 10)
  380.         and     ebp, 0x1F shl 5
  381.         lea     edx, [eax+eax]
  382.         shr     al, 2
  383.         mov     ebx, ebp
  384.         shr     ah, 4
  385.         shl     dl, 2
  386.         shr     ebx, 2
  387.         shr     ebp, 7
  388.         add     al, dl
  389.         add     ah, dh
  390.         mov     [edi+3], al
  391.         add     ebx, ebp
  392.         mov     [edi+5], ah
  393.         mov     [edi+4], bl
  394.         add     edi, 6
  395. end repeat
  396.         sub     ecx, 4
  397.         jnb     .bpp15.intel.loop
  398. .bpp15.tail:
  399.         add     ecx, 4
  400.         jz      .bpp15.done
  401. @@:
  402.         movzx   eax, word [esi]
  403.         mov     ebx, eax
  404.         add     esi, 2
  405.         and     eax, (0x1F) or (0x1F shl 10)
  406.         and     ebx, 0x1F shl 5
  407.         lea     edx, [eax+eax]
  408.         shr     al, 2
  409.         mov     ebp, ebx
  410.         shr     ebx, 2
  411.         shr     ah, 4
  412.         shl     dl, 2
  413.         shr     ebp, 7
  414.         add     eax, edx
  415.         add     ebx, ebp
  416.         mov     [edi], al
  417.         mov     [edi+1], bl
  418.         mov     [edi+2], ah
  419.         add     edi, 3
  420.         sub     ecx, 1
  421.         jnz     @b
  422. .bpp15.done:
  423.         pop     ebp ebx
  424.         ret
  425.  
  426. .bpp15.amd:
  427.         push    ebx ebp
  428.         sub     ecx, 4
  429.         jb      .bpp15.tail
  430. align 16
  431. .bpp15.amd.loop:
  432. repeat 4
  433. if (% mod 2) = 1
  434.         mov     eax, dword [esi]
  435.         mov     ebx, dword [esi]
  436. else
  437.         movzx   eax, word [esi]
  438.         mov     ebx, eax
  439. end if
  440.         add     esi, 2
  441.         and     eax, (0x1F) or (0x1F shl 10)
  442.         and     ebx, 0x1F shl 5
  443.         lea     edx, [eax+eax]
  444.         shr     al, 2
  445.         mov     ebp, ebx
  446.         shr     ebx, 2
  447.         shr     ah, 4
  448.         shl     dl, 2
  449.         shr     ebp, 7
  450.         add     eax, edx
  451.         add     ebx, ebp
  452.         mov     [edi], al
  453.         mov     [edi+1], bl
  454.         mov     [edi+2], ah
  455.         add     edi, 3
  456. end repeat
  457.         sub     ecx, 4
  458.         jnb     .bpp15.amd.loop
  459.         jmp     .bpp15.tail
  460.  
  461. ; 16 BPP -> 24 BPP
  462. .bpp16.intel:
  463.         push    ebx ebp
  464.         sub     ecx, 4
  465.         jb      .bpp16.tail
  466. align 16
  467. .bpp16.intel.loop:
  468. repeat 2
  469.         mov     ebx, [esi]
  470.         mov     al, [esi]
  471.         mov     ah, [esi+1]
  472.         add     esi, 4
  473.         and     al, 0x1F
  474.         and     ah, 0x1F shl 3
  475.         mov     ebp, ebx
  476.         mov     dl, al
  477.         mov     dh, ah
  478.         shr     al, 2
  479.         shr     ah, 5
  480.         shl     dl, 3
  481.         and     ebp, 0x3F shl 5
  482.         add     al, dl
  483.         add     ah, dh
  484.         shr     ebp, 3
  485.         mov     [edi], al
  486.         mov     [edi+2], ah
  487.         mov     eax, ebx
  488.         mov     ebx, ebp
  489.         shr     eax, 16
  490.         shr     ebx, 6
  491.         add     ebx, ebp
  492.         mov     ebp, eax
  493.         mov     [edi+1], bl
  494.         and     eax, (0x1F) or (0x1F shl 11)
  495.         and     ebp, 0x3F shl 5
  496.         mov     edx, eax
  497.         shr     al, 2
  498.         mov     ebx, ebp
  499.         shr     ah, 5
  500.         shl     dl, 3
  501.         shr     ebx, 3
  502.         shr     ebp, 9
  503.         add     al, dl
  504.         add     ah, dh
  505.         mov     [edi+3], al
  506.         add     ebx, ebp
  507.         mov     [edi+5], ah
  508.         mov     [edi+4], bl
  509.         add     edi, 6
  510. end repeat
  511.         sub     ecx, 4
  512.         jnb     .bpp16.intel.loop
  513. .bpp16.tail:
  514.         add     ecx, 4
  515.         jz      .bpp16.done
  516. @@:
  517.         movzx   eax, word [esi]
  518.         mov     ebx, eax
  519.         add     esi, 2
  520.         and     eax, (0x1F) or (0x1F shl 11)
  521.         and     ebx, 0x3F shl 5
  522.         mov     edx, eax
  523.         shr     al, 2
  524.         mov     ebp, ebx
  525.         shr     ebx, 3
  526.         shr     ah, 5
  527.         shl     dl, 3
  528.         shr     ebp, 9
  529.         add     eax, edx
  530.         add     ebx, ebp
  531.         mov     [edi], al
  532.         mov     [edi+1], bl
  533.         mov     [edi+2], ah
  534.         add     edi, 3
  535.         sub     ecx, 1
  536.         jnz     @b
  537. .bpp16.done:
  538.         pop     ebp ebx
  539.         ret
  540.  
  541. .bpp16.amd:
  542.         push    ebx ebp
  543.         sub     ecx, 4
  544.         jb      .bpp16.tail
  545. align 16
  546. .bpp16.amd.loop:
  547. repeat 4
  548. if (% mod 2) = 1
  549.         mov     eax, dword [esi]
  550.         mov     ebx, dword [esi]
  551. else
  552.         movzx   eax, word [esi]
  553.         mov     ebx, eax
  554. end if
  555.         add     esi, 2
  556.         and     eax, (0x1F) or (0x1F shl 11)
  557.         and     ebx, 0x3F shl 5
  558.         mov     edx, eax
  559.         shr     al, 2
  560.         mov     ebp, ebx
  561.         shr     ebx, 3
  562.         shr     ah, 5
  563.         shl     dl, 3
  564.         shr     ebp, 9
  565.         add     eax, edx
  566.         add     ebx, ebp
  567.         mov     [edi], al
  568.         mov     [edi+1], bl
  569.         mov     [edi+2], ah
  570.         add     edi, 3
  571. end repeat
  572.         sub     ecx, 4
  573.         jnb     .bpp16.amd.loop
  574.         jmp     .bpp16.tail
  575.  
  576. align 16
  577. .bpp24:
  578. ; 24 BPP -> 24 BPP
  579.         lea     ecx, [ecx*3 + 3]
  580.         mov     esi, [esi + Image.Data]
  581.         shr     ecx, 2
  582.         rep movsd
  583.         ret
  584.  
  585. align 16
  586. .bpp32:
  587. ; 32 BPP -> 24 BPP
  588.         mov     esi, [esi + Image.Data]
  589.  
  590. @@:
  591.         mov     eax, [esi]
  592.         mov     [edi], ax
  593.         shr     eax, 16
  594.         mov     [edi+2], al
  595.         add     esi, 4
  596.         add     edi, 3
  597.         sub     ecx, 1
  598.         jnz     @b
  599.  
  600. @@:
  601.         ret
  602.  
  603. align 16
  604. .bpp1:
  605.         push    ebx ebp
  606.         mov     ebp, [esi + Image.Width]
  607.         mov     edx, [esi + Image.Height]
  608.         shl     edx, 16
  609.         mov     ebx, [esi + Image.Palette]
  610.         mov     esi, [esi + Image.Data]
  611. .bpp1.pre:
  612.         mov     dx, bp
  613.         mov     ecx, 7
  614. .bpp1.begin:
  615.         xor     eax, eax
  616.         bt      [esi], ecx
  617.         adc     eax, 0
  618.         mov     eax, [ebx + eax*4]
  619.         mov     [edi], ax
  620.         shr     eax, 16
  621.         mov     [edi + 2], al
  622.         add     edi, 3
  623.         dec     dx
  624.         jz      .bpp1.end_line
  625.         dec     ecx
  626.         jns     .bpp1.begin
  627.         mov     ecx, 7
  628.         inc     esi
  629.         jmp     .bpp1.begin
  630. .bpp1.end_line:
  631.         sub     edx, 0x10000
  632.         jz      .bpp1.quit
  633.         inc     esi
  634.         jmp     .bpp1.pre
  635. .bpp1.quit:
  636.         pop     ebp ebx
  637.         ret
  638.  
  639. align 16
  640. .bpp2i:
  641.         push    ebx ebp
  642.         mov     ebp, [esi + Image.Width]
  643.         mov     edx, [esi + Image.Height]
  644.         shl     edx, 16
  645.         mov     ebx, [esi + Image.Palette]
  646.         mov     esi, [esi + Image.Data]
  647. .bpp2i.pre:
  648.         mov     dx, bp
  649.         mov     ecx, 3
  650. .bpp2i.begin:
  651.         mov     eax, 3
  652.         shl     ecx, 1
  653.         shl     eax, cl
  654.         and     al, [esi]
  655.         shr     eax, cl
  656.         shr     ecx, 1
  657.         mov     eax, [ebx + eax*4]
  658.         mov     [edi], ax
  659.         shr     eax, 16
  660.         mov     [edi + 2], al
  661.         add     edi, 3
  662.         dec     dx
  663.         jz      .bpp2i.end_line
  664.         dec     ecx
  665.         jns     .bpp2i.begin
  666.         mov     ecx, 3
  667.         inc     esi
  668.         jmp     .bpp2i.begin
  669. .bpp2i.end_line:
  670.         sub     edx, 0x10000
  671.         jz      .bpp2i.quit
  672.         inc     esi
  673.         jmp     .bpp2i.pre
  674. .bpp2i.quit:
  675.         pop     ebp ebx
  676.         ret
  677.  
  678. align 16
  679. .bpp4i:
  680.         push    ebx ebp
  681.         mov     ebp, [esi + Image.Width]
  682.         mov     edx, [esi + Image.Height]
  683.         shl     edx, 16
  684.         mov     ebx, [esi + Image.Palette]
  685.         mov     esi, [esi + Image.Data]
  686. .bpp4i.pre:
  687.         mov     dx, bp
  688.         mov     ecx, 1
  689. .bpp4i.begin:
  690.         mov     eax, 15
  691.         shl     ecx, 2
  692.         shl     eax, cl
  693.         and     al, [esi]
  694.         shr     eax, cl
  695.         shr     ecx, 2
  696.         mov     eax, [ebx + eax*4]
  697.         mov     [edi], ax
  698.         shr     eax, 16
  699.         mov     [edi + 2], al
  700.         add     edi, 3
  701.         dec     dx
  702.         jz      .bpp4i.end_line
  703.         dec     ecx
  704.         jns     .bpp4i.begin
  705.         mov     ecx, 1
  706.         inc     esi
  707.         jmp     .bpp4i.begin
  708. .bpp4i.end_line:
  709.         sub     edx, 0x10000
  710.         jz      .bpp4i.quit
  711.         inc     esi
  712.         jmp     .bpp4i.pre
  713. .bpp4i.quit:
  714.         pop     ebp ebx
  715.         ret
  716.  
  717. endp
  718.  
  719. ;;============================================================================;;
  720. proc img.decode _data, _length, _options ;////////////////////////////////////;;
  721. ;;----------------------------------------------------------------------------;;
  722. ;? decodes loaded into memory graphic file                                    ;;
  723. ;;----------------------------------------------------------------------------;;
  724. ;> [_data]    = pointer to file in memory                                     ;;
  725. ;> [_length]  = size in bytes of memory area pointed to by [_data]            ;;
  726. ;> [_options] = 0 / pointer to the structure of additional options            ;;
  727. ;;----------------------------------------------------------------------------;;
  728. ;< eax = 0 / pointer to image                                                 ;;
  729. ;;============================================================================;;
  730.         push    ebx
  731.         mov     ebx, [_length]
  732.         or      ebx, ebx
  733.         jz      .fail
  734.         mov     ebx, img.formats_table
  735. @@:
  736.         stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
  737.         or      eax, eax
  738.         jnz     @f
  739.         add     ebx, sizeof.FormatsTableEntry
  740.         cmp     dword[ebx], eax ;0
  741.         jnz     @b
  742. .fail:
  743.         xor     eax, eax
  744.         pop     ebx
  745.         ret
  746. @@:
  747.         mov     eax, [ebx + FormatsTableEntry.Decode]
  748.         pop     ebx
  749.         leave
  750.         jmp     eax
  751. endp
  752.  
  753. ;;============================================================================;;
  754. proc img.encode uses ebx, _img, _common, _specific ;//////////////////////////;;
  755. ;;----------------------------------------------------------------------------;;
  756. ;? encode image to some format                                                ;;
  757. ;;----------------------------------------------------------------------------;;
  758. ;> [_img]      = pointer to input image                                       ;;
  759. ;> [_common]   = some most important/common options                           ;;
  760. ;     0x00 :  byte : format id (defined in libimg.inc)                        ;;
  761. ;     0x01 :  byte : fast encoding (0) / best compression ratio (255)         ;;
  762. ;                    0 : store uncompressed data (if supported both by the    ;;
  763. ;                        format and libimg)                                   ;;
  764. ;                    1 - 255 : use compression, if supported                  ;;
  765. ;                        this option may be ignored if any format specific    ;;
  766. ;                        options are defined, i.e. 0 here will be ignored if  ;;
  767. ;                        particular compression algorithm is specified        ;;
  768. ;     0x02 :  byte : flags (bitfield)                                         ;;
  769. ;                    0x01 : return an error if format specific conditions     ;;
  770. ;                           cannot be met                                     ;;
  771. ;                    0x02 : preserve current bit depth. means 8bpp/16bpp/     ;;
  772. ;                           24bpp and so on                                   ;;
  773. ;                    0x04 : delete alpha channel, if any                      ;;
  774. ;                    0x08 : flush alpha channel with 0xff, if any; add it if  ;;
  775. ;                           none                                              ;;
  776. ;     0x03 :  byte : reserved, must be 0                                      ;;
  777. ;> [_specific] = 0 / pointer to the structure of format specific options      ;;
  778. ;                   see <format_name>.inc for description                     ;;
  779. ;;----------------------------------------------------------------------------;;
  780. ;< eax = 0 / pointer to encoded data                                          ;;
  781. ;< ecx = error code / the size of encoded data                                ;;
  782. ;     1 : out of memory                                                       ;;
  783. ;     2 : format is not supported                                             ;;
  784. ;     3 : specific conditions cannot be satisfied                             ;;
  785. ;     4 : bit depth cannot be preserved                                       ;;
  786. ;;============================================================================;;
  787.         mov     ebx, [_img]
  788.  
  789.         movzx   eax, byte[_common]
  790.         dec     eax
  791.         imul    eax, sizeof.FormatsTableEntry
  792.         add     eax, FormatsTableEntry.Capabilities
  793.         add     eax, img.formats_table
  794.         mov     eax, [eax]
  795.         test    eax, 1          ; is encoding to this format supported at all?
  796.         jnz     @f
  797.         mov     ecx, LIBIMG_ERROR_FORMAT
  798.         jmp     .error
  799. @@:
  800.         mov     ecx, [ebx + Image.Type]
  801.         mov     edx, 1
  802.         shl     edx, cl
  803.         test    eax, edx
  804.         jnz     .bit_depth_ok
  805.         test    byte[_common+2], LIBIMG_ENCODE_STRICT_BIT_DEPTH
  806.         jz      @f
  807.         mov     ecx, LIBIMG_ERROR_BIT_DEPTH
  808.         jmp     .error
  809. @@:
  810.         mov     edx, 1 SHL Image.bpp24
  811.         test    eax, edx
  812.         jnz     @f
  813.         mov     ecx, LIBIMG_ERROR_BIT_DEPTH
  814.         jmp     .error
  815. @@:
  816.         stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], Image.bpp24
  817.         test    eax, eax
  818.         jnz     @f
  819.         mov     ecx, LIBIMG_ERROR_OUT_OF_MEMORY
  820.         jmp     .error
  821. @@:
  822.         push    eax
  823.         stdcall img.to_rgb2, ebx, [eax + Image.Data]
  824.         pop     ebx
  825.  
  826. .bit_depth_ok:
  827.         movzx   eax, byte[_common]
  828.         dec     eax
  829.         imul    eax, sizeof.FormatsTableEntry
  830.         add     eax, FormatsTableEntry.Encode
  831.         add     eax, img.formats_table
  832.         mov     eax, [eax]
  833.         stdcall eax, [_img], [_common], [_specific]
  834.         push    eax ecx
  835.         cmp     ebx, [_img]
  836.         je      @f
  837.         stdcall img.destroy, ebx
  838. @@:
  839.         pop     ecx eax
  840.         jmp     .quit
  841.  
  842. .error:
  843.         xor     eax, eax
  844. .quit:
  845.         ret
  846. endp
  847.  
  848. ;;============================================================================;;
  849. proc img.create _width, _height, _type ;//////////////////////////////////////;;
  850. ;;----------------------------------------------------------------------------;;
  851. ;? creates an Image structure and initializes some its fields                 ;;
  852. ;;----------------------------------------------------------------------------;;
  853. ;> [_width]  = width of an image in pixels                                    ;;
  854. ;> [_height] = height of an image in pixels                                   ;;
  855. ;> [_type]   = one of the Image.bppN constants from libimg.inc                ;;
  856. ;;----------------------------------------------------------------------------;;
  857. ;< eax = 0 / pointer to image                                                 ;;
  858. ;;============================================================================;;
  859.         push    ecx
  860.  
  861.         stdcall img._.new
  862.         or      eax, eax
  863.         jz      .error
  864.  
  865.         mov     ecx, [_type]
  866.         mov     [eax + Image.Type], ecx
  867.  
  868.         push    eax
  869.  
  870.         stdcall img.resize_data, eax, [_width], [_height]
  871.         or      eax, eax
  872.         jz      .error.2
  873.  
  874.         pop     eax
  875.         jmp     .ret
  876.  
  877. .error.2:
  878. ;       pop     eax
  879.         stdcall img._.delete; eax
  880.         xor     eax, eax
  881.  
  882. .error:
  883. .ret:
  884.         pop     ecx
  885.         ret
  886. endp
  887.  
  888. ;;============================================================================;;
  889. proc img.destroy.layer _img ;/////////////////////////////////////////////////;;
  890. ;;----------------------------------------------------------------------------;;
  891. ;? Frees memory occupied by an image and all the memory regions its fields    ;;
  892. ;? point to. For image sequences deletes only one frame and fixes Previous/   ;;
  893. ;? Next pointers.                                                             ;;
  894. ;;----------------------------------------------------------------------------;;
  895. ;> [_img] = pointer to image                                                  ;;
  896. ;;----------------------------------------------------------------------------;;
  897. ;< eax = 0 (fail) / 1 (success)                                               ;;
  898. ;;============================================================================;;
  899.         mov     eax, [_img]
  900.         mov     edx, [eax + Image.Previous]
  901.         test    edx, edx
  902.         jz      @f
  903.         push    [eax + Image.Next]
  904.         pop     [edx + Image.Next]
  905. @@:
  906.         mov     edx, [eax + Image.Next]
  907.         test    edx, edx
  908.         jz      @f
  909.         push    [eax + Image.Previous]
  910.         pop     [edx + Image.Previous]
  911. @@:
  912.         stdcall img._.delete, eax
  913.         ret
  914. endp
  915.  
  916. ;;============================================================================;;
  917. proc img.destroy _img ;///////////////////////////////////////////////////////;;
  918. ;;----------------------------------------------------------------------------;;
  919. ;? Frees memory occupied by an image and all the memory regions its fields    ;;
  920. ;? point to. Follows Previous/Next pointers and deletes all the images in     ;;
  921. ;? sequence.                                                                  ;;
  922. ;;----------------------------------------------------------------------------;;
  923. ;> [_img] = pointer to image                                                  ;;
  924. ;;----------------------------------------------------------------------------;;
  925. ;< eax = 0 (fail) / 1 (success)                                               ;;
  926. ;;============================================================================;;
  927.         push    1
  928.         mov     eax, [_img]
  929.         mov     eax, [eax + Image.Previous]
  930. .destroy_prev_loop:
  931.         test    eax, eax
  932.         jz      .destroy_prev_done
  933.         pushd   [eax + Image.Previous]
  934.         stdcall img._.delete, eax
  935.         test    eax, eax
  936.         jnz     @f
  937.         mov     byte [esp+4], 0
  938. @@:
  939.         pop     eax
  940.         jmp     .destroy_prev_loop
  941. .destroy_prev_done:
  942.         mov     eax, [_img]
  943. .destroy_next_loop:
  944.         pushd   [eax + Image.Next]
  945.         stdcall img._.delete, eax
  946.         test    eax, eax
  947.         jnz     @f
  948.         mov     byte [esp+4], 0
  949. @@:
  950.         pop     eax
  951.         test    eax, eax
  952.         jnz     .destroy_next_loop
  953.         pop     eax
  954.         ret
  955. endp
  956.  
  957. ;;============================================================================;;
  958. proc img.count _img ;/////////////////////////////////////////////////////////;;
  959. ;;----------------------------------------------------------------------------;;
  960. ;? Get number of images in the list (e.g. in animated GIF file)               ;;
  961. ;;----------------------------------------------------------------------------;;
  962. ;> _img = pointer to image                                                    ;;
  963. ;;----------------------------------------------------------------------------;;
  964. ;< eax = -1 (fail) / >0 (ok)                                                  ;;
  965. ;;============================================================================;;
  966.         push    ecx edx
  967.         mov     edx, [_img]
  968.         stdcall img._.validate, edx
  969.         or      eax, eax
  970.         jnz     .error
  971.  
  972. @@:
  973.         mov     eax, [edx + Image.Previous]
  974.         or      eax, eax
  975.         jz      @f
  976.         mov     edx, eax
  977.         jmp     @b
  978.  
  979. @@:
  980.         xor     ecx, ecx
  981. @@:
  982.         inc     ecx
  983.         mov     eax, [edx + Image.Next]
  984.         or      eax, eax
  985.         jz      .exit
  986.         mov     edx, eax
  987.         jmp     @b
  988.  
  989. .exit:
  990.         mov     eax, ecx
  991.         pop     edx ecx
  992.         ret
  993.  
  994. .error:
  995.         or      eax, -1
  996.         pop     edx ecx
  997.         ret
  998. endp
  999.  
  1000. ;;//// image processing //////////////////////////////////////////////////////;;
  1001.  
  1002. ;;============================================================================;;
  1003. proc img.lock_bits _img, _start_line, _end_line ;/////////////////////////////;;
  1004. ;;----------------------------------------------------------------------------;;
  1005. ;? --- TBD ---                                                                ;;
  1006. ;;----------------------------------------------------------------------------;;
  1007. ;> --- TBD ---                                                                ;;
  1008. ;;----------------------------------------------------------------------------;;
  1009. ;< eax = 0 / pointer to bits                                                  ;;
  1010. ;;============================================================================;;
  1011.         xor     eax, eax
  1012.         ret
  1013. endp
  1014.  
  1015. ;;============================================================================;;
  1016. proc img.unlock_bits _img, _lock ;////////////////////////////////////////////;;
  1017. ;;----------------------------------------------------------------------------;;
  1018. ;? --- TBD ---                                                                ;;
  1019. ;;----------------------------------------------------------------------------;;
  1020. ;> --- TBD ---                                                                ;;
  1021. ;;----------------------------------------------------------------------------;;
  1022. ;< eax = false / true                                                         ;;
  1023. ;;============================================================================;;
  1024.         xor     eax, eax
  1025.         ret
  1026. endp
  1027.  
  1028. ;;============================================================================;;
  1029. proc img.flip.layer _img, _flip_kind ;////////////////////////////////////////;;
  1030. ;;----------------------------------------------------------------------------;;
  1031. ;? Flip image layer                                                           ;;
  1032. ;;----------------------------------------------------------------------------;;
  1033. ;> _img = pointer to image                                                    ;;
  1034. ;> _flip_kind = one of FLIP_* constants                                       ;;
  1035. ;;----------------------------------------------------------------------------;;
  1036. ;< eax = false / true                                                         ;;
  1037. ;;============================================================================;;
  1038. locals
  1039.   scanline_len dd ?
  1040. endl
  1041.  
  1042.         push    ebx esi edi
  1043.         mov     ebx, [_img]
  1044.         stdcall img._.validate, ebx
  1045.         or      eax, eax
  1046.         jnz     .error
  1047.  
  1048.         mov     ecx, [ebx + Image.Height]
  1049.         mov     eax, [ebx + Image.Width]
  1050.         call    img._.get_scanline_len
  1051.         mov     [scanline_len], eax
  1052.  
  1053.         test    [_flip_kind], FLIP_VERTICAL
  1054.         jz      .dont_flip_vert
  1055.  
  1056.         imul    eax, ecx
  1057.         sub     eax, [scanline_len]
  1058.         shr     ecx, 1
  1059.         mov     esi, [ebx + Image.Data]
  1060.         lea     edi, [esi + eax]
  1061.    
  1062. .next_line_vert:
  1063.         push    ecx
  1064.  
  1065.         mov     ecx, [scanline_len]
  1066.         push    ecx
  1067.         shr     ecx, 2
  1068. @@:
  1069.         dec     ecx
  1070.         js      @f
  1071.         mov     eax, [esi]
  1072.         xchg    eax, [edi]
  1073.         mov     [esi], eax
  1074.         add     esi, 4
  1075.         add     edi, 4
  1076.         jmp     @b
  1077. @@:
  1078.  
  1079.         pop     ecx
  1080.         and     ecx, 3
  1081.         jz      .cont_line_vert
  1082. @@:
  1083.         mov     al, [esi]
  1084.         xchg    al, [edi]
  1085.         mov     [esi], al
  1086.         add     esi, 1
  1087.         add     edi, 1
  1088.         dec     ecx
  1089.         jnz     @b
  1090. .cont_line_vert:
  1091.  
  1092.         pop     ecx
  1093.         mov     eax, [scanline_len]
  1094.         shl     eax, 1
  1095.         sub     edi, eax
  1096.         dec     ecx
  1097.         jnz     .next_line_vert
  1098.  
  1099. .dont_flip_vert:
  1100.  
  1101.         test    [_flip_kind], FLIP_HORIZONTAL
  1102.         jz      .exit
  1103.  
  1104.         mov     ecx, [ebx + Image.Height]
  1105.         mov     eax, [ebx + Image.Type]
  1106.         mov     esi, [ebx + Image.Data]
  1107.         mov     edi, [scanline_len]
  1108.         add     edi, esi
  1109.         jmp     dword [.handlers_horz + (eax-1)*4]
  1110.  
  1111. .bpp32_horz:
  1112.         sub     edi, 4
  1113.  
  1114. .next_line_horz:
  1115.         push    ecx esi edi
  1116.  
  1117.         mov     ecx, [scanline_len]
  1118.         shr     ecx, 3
  1119. @@:
  1120.         mov     eax, [esi]
  1121.         xchg    eax, [edi]
  1122.         mov     [esi], eax
  1123.         add     esi, 4
  1124.         add     edi, -4
  1125.         sub     ecx, 1
  1126.         jnz     @b
  1127.  
  1128.         pop     edi esi ecx
  1129.         add     esi, [scanline_len]
  1130.         add     edi, [scanline_len]
  1131.         dec     ecx
  1132.         jnz     .next_line_horz
  1133.         jmp     .exit
  1134.  
  1135. .bpp1x_horz:
  1136.         sub     edi, 2
  1137. .next_line_horz1x:
  1138.         push    ecx esi edi
  1139.  
  1140.         mov     ecx, [ebx + Image.Width]
  1141. @@:
  1142.         mov     ax, [esi]
  1143.         mov     dx, [edi]
  1144.         mov     [edi], ax
  1145.         mov     [esi], dx
  1146.         add     esi, 2
  1147.         sub     edi, 2
  1148.         sub     ecx, 2
  1149.         ja      @b
  1150.  
  1151.         pop     edi esi ecx
  1152.         add     esi, [scanline_len]
  1153.         add     edi, [scanline_len]
  1154.         dec     ecx
  1155.         jnz     .next_line_horz1x
  1156.         jmp     .exit
  1157.  
  1158. .bpp8ig_horz:
  1159.         dec     edi
  1160. .next_line_horz8ig:
  1161.         push    ecx esi edi
  1162.  
  1163.         mov     ecx, [scanline_len]
  1164.         shr     ecx, 1
  1165. @@:
  1166.         mov     al, [esi]
  1167.         mov     dl, [edi]
  1168.         mov     [edi], al
  1169.         mov     [esi], dl
  1170.         add     esi, 1
  1171.         sub     edi, 1
  1172.         sub     ecx, 1
  1173.         jnz     @b
  1174.  
  1175.         pop     edi esi ecx
  1176.         add     esi, [scanline_len]
  1177.         add     edi, [scanline_len]
  1178.         dec     ecx
  1179.         jnz     .next_line_horz8ig
  1180.         jmp     .exit
  1181.  
  1182. .bpp24_horz:
  1183.         sub     edi, 3
  1184. .next_line_horz24:
  1185.         push    ecx esi edi
  1186.  
  1187.         mov     ecx, [ebx + Image.Width]
  1188. @@:
  1189.         mov     al, [esi]
  1190.         mov     dl, [edi]
  1191.         mov     [edi], al
  1192.         mov     [esi], dl
  1193.         mov     al, [esi+1]
  1194.         mov     dl, [edi+1]
  1195.         mov     [edi+1], al
  1196.         mov     [esi+1], dl
  1197.         mov     al, [esi+2]
  1198.         mov     dl, [edi+2]
  1199.         mov     [edi+2], al
  1200.         mov     [esi+2], dl
  1201.         add     esi, 3
  1202.         sub     edi, 3
  1203.         sub     ecx, 2
  1204.         ja      @b
  1205.  
  1206.         pop     edi esi ecx
  1207.         add     esi, [scanline_len]
  1208.         add     edi, [scanline_len]
  1209.         dec     ecx
  1210.         jnz     .next_line_horz24
  1211.         jmp     .exit
  1212.  
  1213. .bpp1_horz:
  1214.         mov     edi, [scanline_len]
  1215.         mov     edx, [ebx + Image.Width]
  1216.         and     edx, 7
  1217.         neg     edx
  1218.         add     edx, 8
  1219.         and     edx, 7
  1220. .bpp1_horz.begin:
  1221.         push    ebx edx esi
  1222.         mov     eax, 7
  1223.         add     edi, esi
  1224.         sub     edi, 1
  1225.         mov     ebx, [ebx + Image.Width]
  1226.         shr     ebx, 1
  1227. .bpp1_horz.bit:
  1228.         bt      [edi], edx
  1229.         jc      @f
  1230.         btr     [esi], eax
  1231.         jmp     .bpp1_horz.right
  1232. @@:
  1233.         bts     [esi], eax
  1234. .bpp1_horz.right:
  1235.         jnc     @f
  1236.         bts     [edi], edx
  1237.         jmp     .bpp1_horz.bit_done
  1238. @@:
  1239.         btr     [edi], edx
  1240. .bpp1_horz.bit_done:
  1241.         inc     edx
  1242.         and     edx, 7
  1243.         jnz     @f
  1244.         dec     edi
  1245. @@:
  1246.         dec     eax
  1247.         jns     @f
  1248.         mov     eax, 7
  1249.         inc     esi
  1250. @@:
  1251.         dec     ebx
  1252.         jnz     .bpp1_horz.bit
  1253.  
  1254.         pop     esi edx ebx
  1255.         add     esi, [scanline_len]
  1256.         mov     edi, [scanline_len]
  1257.         dec     ecx
  1258.         jnz     .bpp1_horz.begin
  1259.         jmp     .exit
  1260.  
  1261.  
  1262. .bpp2i_horz:
  1263.         mov     edi, [scanline_len]
  1264.         mov     edx, [ebx + Image.Width]
  1265.         and     edx, 3
  1266.         neg     edx
  1267.         add     edx, 4
  1268.         and     edx, 3
  1269. .bpp2i_horz.begin:
  1270.         push    ebx edx esi
  1271.         mov     eax, 3
  1272.         add     edi, esi
  1273.         sub     edi, 1
  1274.         mov     ebx, [ebx + Image.Width]
  1275.         shr     ebx, 1
  1276. .bpp2i_horz.pixel:
  1277.         push    ebx ecx
  1278.         mov     ebx, 3
  1279.         mov     ecx, edx
  1280.         shl     ebx, cl
  1281.         shl     ebx, cl
  1282.         and     bl, [edi]
  1283.         shr     ebx, cl
  1284.         shr     ebx, cl
  1285.         mov     bh, 3
  1286.         mov     ecx, eax
  1287.         shl     ebx, cl
  1288.         shl     ebx, cl
  1289.         not     bh
  1290.         and     bh, [esi]
  1291.         or      bl, bh
  1292.         mov     bh, [esi]
  1293.         mov     [esi], bl
  1294.         shr     ebx, 8
  1295.         shr     ebx, cl
  1296.         shr     ebx, cl
  1297.         and     ebx, 3
  1298.         mov     bh, 3
  1299.         mov     ecx, edx
  1300.         shl     ebx, cl
  1301.         shl     ebx, cl
  1302.         not     bh
  1303.         and     bh, [edi]
  1304.         or      bl, bh
  1305.         mov     [edi], bl
  1306.         pop     ecx ebx
  1307. .bpp2i_horz.pixel_done:
  1308.         inc     edx
  1309.         and     edx, 3
  1310.         jnz     @f
  1311.         dec     edi
  1312. @@:
  1313.         dec     eax
  1314.         jns     @f
  1315.         mov     eax, 3
  1316.         inc     esi
  1317. @@:
  1318.         dec     ebx
  1319.         jnz     .bpp2i_horz.pixel
  1320.  
  1321.         pop     esi edx ebx
  1322.         add     esi, [scanline_len]
  1323.         mov     edi, [scanline_len]
  1324.         dec     ecx
  1325.         jnz     .bpp2i_horz.begin
  1326.         jmp     .exit
  1327.  
  1328.  
  1329. .bpp4i_horz:
  1330.         mov     edi, [scanline_len]
  1331.         mov     edx, [ebx + Image.Width]
  1332.         and     edx, 1
  1333.         neg     edx
  1334.         add     edx, 2
  1335.         and     edx, 1
  1336. .bpp4i_horz.begin:
  1337.         push    ebx edx esi
  1338.         mov     eax, 1
  1339.         add     edi, esi
  1340.         sub     edi, 1
  1341.         mov     ebx, [ebx + Image.Width]
  1342.         shr     ebx, 1
  1343. .bpp4i_horz.pixel:
  1344.         push    ebx ecx
  1345.         mov     ebx, 15
  1346.         mov     ecx, edx
  1347.         shl     ecx, 2
  1348.         shl     ebx, cl
  1349.         and     bl, [edi]
  1350.         shr     ebx, cl
  1351.         mov     bh, 15
  1352.         mov     ecx, eax
  1353.         shl     ecx, 2
  1354.         shl     ebx, cl
  1355.         not     bh
  1356.         and     bh, [esi]
  1357.         or      bl, bh
  1358.         mov     bh, [esi]
  1359.         mov     [esi], bl
  1360.         shr     ebx, 8
  1361.         shr     ebx, cl
  1362.         and     ebx, 15
  1363.         mov     bh, 15
  1364.         mov     ecx, edx
  1365.         shl     ecx, 2
  1366.         shl     ebx, cl
  1367.         not     bh
  1368.         and     bh, [edi]
  1369.         or      bl, bh
  1370.         mov     [edi], bl
  1371.         pop     ecx ebx
  1372. .bpp4i_horz.pixel_done:
  1373.         inc     edx
  1374.         and     edx, 1
  1375.         jnz     @f
  1376.         dec     edi
  1377. @@:
  1378.         dec     eax
  1379.         jns     @f
  1380.         mov     eax, 1
  1381.         inc     esi
  1382. @@:
  1383.         dec     ebx
  1384.         jnz     .bpp4i_horz.pixel
  1385.  
  1386.         pop     esi edx ebx
  1387.         add     esi, [scanline_len]
  1388.         mov     edi, [scanline_len]
  1389.         dec     ecx
  1390.         jnz     .bpp4i_horz.begin
  1391.         jmp     .exit
  1392.  
  1393.  
  1394. .exit:
  1395.         xor     eax, eax
  1396.         inc     eax
  1397.         pop     edi esi ebx
  1398.         ret
  1399.  
  1400. .error:
  1401.         xor     eax, eax
  1402.         pop     edi esi ebx
  1403.         ret
  1404. endp
  1405.  
  1406. ;;============================================================================;;
  1407. proc img.flip _img, _flip_kind ;//////////////////////////////////////////////;;
  1408. ;;----------------------------------------------------------------------------;;
  1409. ;? Flip all layers of image                                                   ;;
  1410. ;;----------------------------------------------------------------------------;;
  1411. ;> _img = pointer to image                                                    ;;
  1412. ;> _flip_kind = one of FLIP_* constants                                       ;;
  1413. ;;----------------------------------------------------------------------------;;
  1414. ;< eax = false / true                                                         ;;
  1415. ;;============================================================================;;
  1416.         push    1
  1417.         mov     ebx, [_img]
  1418. @@:
  1419.         mov     eax, [ebx + Image.Previous]
  1420.         test    eax, eax
  1421.         jz      .loop
  1422.         mov     ebx, eax
  1423.         jmp     @b
  1424. .loop:
  1425.         stdcall img.flip.layer, ebx, [_flip_kind]
  1426.         test    eax, eax
  1427.         jnz     @f
  1428.         mov     byte [esp], 0
  1429. @@:
  1430.         mov     ebx, [ebx + Image.Next]
  1431.         test    ebx, ebx
  1432.         jnz     .loop
  1433.         pop     eax
  1434.         ret
  1435. endp
  1436.  
  1437. ;;============================================================================;;
  1438. proc img.rotate.layer _img, _rotate_kind ;////////////////////////////////////;;
  1439. ;;----------------------------------------------------------------------------;;
  1440. ;? Rotate image layer                                                         ;;
  1441. ;;----------------------------------------------------------------------------;;
  1442. ;> _img = pointer to image                                                    ;;
  1443. ;> _rotate_kind = one of ROTATE_* constants                                   ;;
  1444. ;;----------------------------------------------------------------------------;;
  1445. ;< eax = false / true                                                         ;;
  1446. ;;============================================================================;;
  1447. locals
  1448.   scanline_len_old    dd ?
  1449.   scanline_len_new    dd ?
  1450.   scanline_pixels_new dd ?
  1451.   line_buffer         dd ?
  1452.   pixels_ptr          dd ?
  1453. endl
  1454.  
  1455.         mov     [line_buffer], 0
  1456.  
  1457.         push    ebx esi edi
  1458.         mov     ebx, [_img]
  1459.         stdcall img._.validate, ebx
  1460.         or      eax, eax
  1461.         jnz     .error
  1462.  
  1463.         cmp     [_rotate_kind], ROTATE_90_CCW
  1464.         je      .rotate_ccw_low
  1465.         cmp     [_rotate_kind], ROTATE_90_CW
  1466.         je      .rotate_cw_low
  1467.         cmp     [_rotate_kind], ROTATE_180
  1468.         je      .flip
  1469.         jmp     .exit
  1470.  
  1471. .rotate_ccw_low:
  1472.         mov     eax, [ebx + Image.Height]
  1473.         mov     [scanline_pixels_new], eax
  1474.         call    img._.get_scanline_len
  1475.         mov     [scanline_len_new], eax
  1476.  
  1477.         invoke  mem.alloc, eax
  1478.         or      eax, eax
  1479.         jz      .error
  1480.         mov     [line_buffer], eax
  1481.  
  1482.         mov     eax, [ebx + Image.Width]
  1483.         mov     ecx, eax
  1484.         call    img._.get_scanline_len
  1485.         mov     [scanline_len_old], eax
  1486.  
  1487.         mov     eax, [scanline_len_new]
  1488.         imul    eax, ecx
  1489.         add     eax, [ebx + Image.Data]
  1490.         mov     [pixels_ptr], eax
  1491.  
  1492.         cmp     [ebx + Image.Type], Image.bpp1
  1493.         jz      .rotate_ccw1
  1494.         cmp     [ebx + Image.Type], Image.bpp2i
  1495.         jz      .rotate_ccw2i
  1496.         cmp     [ebx + Image.Type], Image.bpp4i
  1497.         jz      .rotate_ccw4i
  1498.         cmp     [ebx + Image.Type], Image.bpp8i
  1499.         jz      .rotate_ccw8ig
  1500.         cmp     [ebx + Image.Type], Image.bpp8g
  1501.         jz      .rotate_ccw8ig
  1502.         cmp     [ebx + Image.Type], Image.bpp24
  1503.         jz      .rotate_ccw24
  1504.         cmp     [ebx + Image.Type], Image.bpp32
  1505.         jz      .rotate_ccw32
  1506.  
  1507. .next_column_ccw_low1x:
  1508.         dec     ecx
  1509.         js      .exchange_dims
  1510.         push    ecx
  1511.  
  1512.         mov     edx, [scanline_len_old]
  1513.         add     [scanline_len_old], -2
  1514.  
  1515.         mov     ecx, [scanline_pixels_new]
  1516.         mov     esi, [ebx + Image.Data]
  1517.         mov     edi, [line_buffer]
  1518. @@:
  1519.         mov     ax, [esi]
  1520.         mov     [edi], ax
  1521.         add     esi, edx
  1522.         add     edi, 2
  1523.         sub     ecx, 1
  1524.         jnz     @b
  1525.  
  1526.         mov     eax, [scanline_pixels_new]
  1527.         mov     edi, [ebx + Image.Data]
  1528.         lea     esi, [edi + 2]
  1529.         mov     edx, [scanline_len_old]
  1530. @@:
  1531.         mov     ecx, edx
  1532.         shr     ecx, 2
  1533.         rep movsd
  1534.         mov     ecx, edx
  1535.         and     ecx, 3
  1536.         rep movsb
  1537.         add     esi, 1
  1538.         sub     eax, 1
  1539.         jnz     @b
  1540.  
  1541.         mov     eax, [scanline_len_new]
  1542.         sub     [pixels_ptr], eax
  1543.         mov     ecx, [scanline_pixels_new]
  1544.         mov     esi, [line_buffer]
  1545.         mov     edi, [pixels_ptr]
  1546.         mov     edx, ecx
  1547.         shr     ecx, 2
  1548.         rep movsd
  1549.         mov     ecx, edx
  1550.         and     ecx, 3
  1551.         rep movsb
  1552.  
  1553.         pop     ecx
  1554.         jmp     .next_column_ccw_low1x
  1555.  
  1556. .rotate_ccw32:
  1557. .next_column_ccw_low:
  1558.         dec     ecx
  1559.         js      .exchange_dims
  1560.         push    ecx
  1561.  
  1562.         mov     edx, [scanline_len_old]
  1563.         add     [scanline_len_old], -4
  1564.  
  1565.         mov     ecx, [scanline_pixels_new]
  1566.         mov     esi, [ebx + Image.Data]
  1567.         mov     edi, [line_buffer]
  1568. @@:
  1569.         mov     eax, [esi]
  1570.         stosd
  1571.         add     esi, edx
  1572.         dec     ecx
  1573.         jnz     @b
  1574.  
  1575.         mov     eax, [scanline_pixels_new]
  1576.         mov     edi, [ebx + Image.Data]
  1577.         lea     esi, [edi + 4]
  1578.         mov     edx, [scanline_len_old]
  1579.         shr     edx, 2
  1580. @@:
  1581.         mov     ecx, edx
  1582.         rep movsd
  1583.         add     esi, 4
  1584.         dec     eax
  1585.         jnz     @b
  1586.  
  1587.         mov     eax, [scanline_len_new]
  1588.         sub     [pixels_ptr], eax
  1589.         mov     ecx, [scanline_pixels_new]
  1590.         mov     esi, [line_buffer]
  1591.         mov     edi, [pixels_ptr]
  1592.         rep movsd
  1593.  
  1594.         pop     ecx
  1595.         jmp     .next_column_ccw_low
  1596.  
  1597. .rotate_ccw8ig:
  1598. .next_column_ccw_low8ig:
  1599.         dec     ecx
  1600.         js      .exchange_dims
  1601.         push    ecx
  1602.  
  1603.         mov     edx, [scanline_len_old]
  1604.         add     [scanline_len_old], -1
  1605.  
  1606.         mov     ecx, [scanline_pixels_new]
  1607.         mov     esi, [ebx + Image.Data]
  1608.         mov     edi, [line_buffer]
  1609. @@:
  1610.         mov     al, [esi]
  1611.         mov     [edi], al
  1612.         add     esi, edx
  1613.         add     edi, 1
  1614.         sub     ecx, 1
  1615.         jnz     @b
  1616.  
  1617.         mov     eax, [scanline_pixels_new]
  1618.         mov     edi, [ebx + Image.Data]
  1619.         lea     esi, [edi + 1]
  1620.         mov     edx, [scanline_len_old]
  1621. @@:
  1622.         mov     ecx, edx
  1623.         shr     ecx, 2
  1624.         rep movsd
  1625.         mov     ecx, edx
  1626.         and     ecx, 3
  1627.         rep movsb
  1628.         add     esi, 1
  1629.         sub     eax, 1
  1630.         jnz     @b
  1631.  
  1632.         mov     eax, [scanline_len_new]
  1633.         sub     [pixels_ptr], eax
  1634.         mov     ecx, [scanline_pixels_new]
  1635.         mov     esi, [line_buffer]
  1636.         mov     edi, [pixels_ptr]
  1637.         mov     edx, ecx
  1638.         shr     ecx, 2
  1639.         rep movsd
  1640.         mov     ecx, edx
  1641.         and     ecx, 3
  1642.         rep movsb
  1643.  
  1644.         pop     ecx
  1645.         jmp     .next_column_ccw_low8ig
  1646.  
  1647. .rotate_ccw24:
  1648. .next_column_ccw_low24:
  1649.         dec     ecx
  1650.         js      .exchange_dims
  1651.         push    ecx
  1652.  
  1653.         mov     edx, [scanline_len_old]
  1654.         add     [scanline_len_old], -3
  1655.  
  1656.         mov     ecx, [scanline_pixels_new]
  1657.         mov     esi, [ebx + Image.Data]
  1658.         mov     edi, [line_buffer]
  1659. @@:
  1660.         mov     al, [esi]
  1661.         mov     [edi], al
  1662.         mov     al, [esi+1]
  1663.         mov     [edi+1], al
  1664.         mov     al, [esi+2]
  1665.         mov     [edi+2], al
  1666.         add     esi, edx
  1667.         add     edi, 3
  1668.         sub     ecx, 1
  1669.         jnz     @b
  1670.  
  1671.         mov     eax, [scanline_pixels_new]
  1672.         mov     edi, [ebx + Image.Data]
  1673.         lea     esi, [edi + 3]
  1674.         mov     edx, [scanline_len_old]
  1675. @@:
  1676.         mov     ecx, edx
  1677.         shr     ecx, 2
  1678.         rep movsd
  1679.         mov     ecx, edx
  1680.         and     ecx, 3
  1681.         rep movsb
  1682.         add     esi, 3
  1683.         sub     eax, 1
  1684.         jnz     @b
  1685.  
  1686.         mov     eax, [scanline_len_new]
  1687.         sub     [pixels_ptr], eax
  1688.         mov     ecx, eax
  1689.         mov     esi, [line_buffer]
  1690.         mov     edi, [pixels_ptr]
  1691.         shr     ecx, 2
  1692.         rep movsd
  1693.         mov     ecx, eax
  1694.         and     ecx, 3
  1695.         rep movsb
  1696.  
  1697.         pop     ecx
  1698.         jmp     .next_column_ccw_low24
  1699.  
  1700. .rotate_ccw1:
  1701.         push    ecx edx
  1702.  
  1703.         mov     eax, [ebx + Image.Height]
  1704.         add     eax, 7
  1705.         shr     eax, 3
  1706.         imul    eax, [ebx + Image.Width]
  1707.         push    eax                             ; save new data size
  1708.  
  1709.         invoke  mem.alloc, eax
  1710.         or      eax, eax
  1711.         jz      .error
  1712.         push    eax                             ; save pointer to new data
  1713.  
  1714.         mov     ecx, [ebx + Image.Width]
  1715.         and     ecx, 7
  1716.         neg     ecx
  1717.         add     ecx, 8
  1718.         and     ecx, 7
  1719.  
  1720.         mov     edi, eax
  1721.         mov     esi, [ebx + Image.Data]
  1722.         mov     eax, 7
  1723.         mov     edx, [scanline_len_old]
  1724.         dec     edx
  1725.         add     esi, edx
  1726.  
  1727. .rotate_ccw1.begin:
  1728.         bt      [esi], ecx
  1729.         jc      .rotate_ccw1.one
  1730. .rotate_ccw1.zero:
  1731.         btr     [edi], eax
  1732.         jmp     @f
  1733. .rotate_ccw1.one:
  1734.         bts     [edi], eax
  1735. @@:
  1736.         add     esi, [scanline_len_old]
  1737.         dec     [scanline_pixels_new]
  1738.         jz      .rotate_ccw1.end_of_line
  1739.         sub     eax, 1
  1740.         adc     edi, 0
  1741.         and     eax, 7
  1742.         jmp     .rotate_ccw1.begin
  1743. .rotate_ccw1.end_of_line:
  1744.         inc     edi
  1745.         mov     eax, [ebx + Image.Height]
  1746.         mov     [scanline_pixels_new], eax
  1747.         mov     eax, 7
  1748.         inc     ecx
  1749.         and     ecx, 7
  1750.         jz      @f
  1751.         mov     esi, [ebx + Image.Data]
  1752.         add     esi, edx
  1753.         jmp     .rotate_ccw1.begin
  1754. @@:
  1755.         dec     edx
  1756.         js      .rotate_ccw1.quit
  1757.         mov     esi, [ebx + Image.Data]
  1758.         add     esi, edx
  1759.         jmp     .rotate_ccw1.begin
  1760. .rotate_ccw1.quit:
  1761.         pop     esi                             ; get pointer to new data
  1762.         mov     edi, [ebx + Image.Data]
  1763.         pop     ecx                             ; get new data size
  1764.         rep movsb
  1765.         invoke  mem.free, esi
  1766.         pop     edx ecx
  1767.         jmp     .exchange_dims
  1768.  
  1769.  
  1770. .rotate_ccw2i:
  1771.         push    ecx edx
  1772.  
  1773.         mov     eax, [ebx + Image.Height]
  1774.         add     eax, 3
  1775.         shr     eax, 2
  1776.         imul    eax, [ebx + Image.Width]
  1777.         push    eax                             ; save new data size
  1778.  
  1779.         invoke  mem.alloc, eax
  1780.         or      eax, eax
  1781.         jz      .error
  1782.         push    eax                             ; save pointer to new data
  1783.  
  1784.         mov     ecx, [ebx + Image.Width]
  1785.         and     ecx, 3
  1786.         neg     ecx
  1787.         add     ecx, 4
  1788.         and     ecx, 3
  1789.  
  1790.         mov     edi, eax
  1791.         mov     esi, [ebx + Image.Data]
  1792.         mov     eax, 3
  1793.         mov     edx, [scanline_len_old]
  1794.         dec     edx
  1795.         add     esi, edx
  1796.  
  1797. .rotate_ccw2i.begin:
  1798.         push    ebx ecx
  1799.         mov     ebx, 3
  1800.         shl     ebx, cl
  1801.         shl     ebx, cl
  1802.         and     bl, [esi]
  1803.         shr     ebx, cl
  1804.         shr     ebx, cl
  1805.         mov     bh, 3
  1806.         mov     ecx, eax
  1807.         shl     ebx, cl
  1808.         shl     ebx, cl
  1809.         not     bh
  1810.         and     bh, [edi]
  1811.         or      bl, bh
  1812.         mov     [edi], bl
  1813.         pop     ecx ebx
  1814.  
  1815.         add     esi, [scanline_len_old]
  1816.         dec     [scanline_pixels_new]
  1817.         jz      .rotate_ccw2i.end_of_line
  1818.         sub     eax, 1
  1819.         adc     edi, 0
  1820.         and     eax, 3
  1821.         jmp     .rotate_ccw2i.begin
  1822. .rotate_ccw2i.end_of_line:
  1823.         inc     edi
  1824.         mov     eax, 3
  1825.         mov     esi, [ebx + Image.Height]
  1826.         mov     [scanline_pixels_new], esi
  1827.         inc     ecx
  1828.         and     ecx, 3
  1829.         jz      @f
  1830.         mov     esi, [ebx + Image.Data]
  1831.         add     esi, edx
  1832.         jmp     .rotate_ccw2i.begin
  1833. @@:
  1834.         dec     edx
  1835.         js      .rotate_ccw2i.quit
  1836.         mov     esi, [ebx + Image.Data]
  1837.         add     esi, edx
  1838.         jmp     .rotate_ccw2i.begin
  1839. .rotate_ccw2i.quit:
  1840.         pop     esi                             ; get pointer to new data
  1841.         mov     edi, [ebx + Image.Data]
  1842.         pop     ecx                             ; get new data size
  1843.         rep movsb
  1844.         invoke  mem.free, esi
  1845.         pop     edx ecx
  1846.         jmp     .exchange_dims
  1847.  
  1848.  
  1849. .rotate_ccw4i:
  1850.         push    ecx edx
  1851.  
  1852.         mov     eax, [ebx + Image.Height]
  1853.         add     eax, 1
  1854.         shr     eax, 1
  1855.         imul    eax, [ebx + Image.Width]
  1856.         push    eax                             ; save new data size
  1857.  
  1858.         invoke  mem.alloc, eax
  1859.         or      eax, eax
  1860.         jz      .error
  1861.         push    eax                             ; save pointer to new data
  1862.  
  1863.         mov     ecx, [ebx + Image.Width]
  1864.         and     ecx, 1
  1865.         neg     ecx
  1866.         add     ecx, 2
  1867.         and     ecx, 1
  1868.  
  1869.         mov     edi, eax
  1870.         mov     esi, [ebx + Image.Data]
  1871.         mov     eax, 1
  1872.         mov     edx, [scanline_len_old]
  1873.         dec     edx
  1874.         add     esi, edx
  1875.  
  1876. .rotate_ccw4i.begin:
  1877.         push    ebx ecx
  1878.         mov     ebx, 15
  1879.         shl     ecx, 2
  1880.         shl     ebx, cl
  1881.         and     bl, [esi]
  1882.         shr     ebx, cl
  1883.         mov     bh, 15
  1884.         mov     ecx, eax
  1885.         shl     ecx, 2
  1886.         shl     ebx, cl
  1887.         not     bh
  1888.         and     bh, [edi]
  1889.         or      bl, bh
  1890.         mov     [edi], bl
  1891.         pop     ecx ebx
  1892.  
  1893.         add     esi, [scanline_len_old]
  1894.         dec     [scanline_pixels_new]
  1895.         jz      .rotate_ccw4i.end_of_line
  1896.         sub     eax, 1
  1897.         adc     edi, 0
  1898.         and     eax, 1
  1899.         jmp     .rotate_ccw4i.begin
  1900. .rotate_ccw4i.end_of_line:
  1901.         inc     edi
  1902.         mov     eax, 1
  1903.         mov     esi, [ebx + Image.Height]
  1904.         mov     [scanline_pixels_new], esi
  1905.         inc     ecx
  1906.         and     ecx, 1
  1907.         jz      @f
  1908.         mov     esi, [ebx + Image.Data]
  1909.         add     esi, edx
  1910.         jmp     .rotate_ccw4i.begin
  1911. @@:
  1912.         dec     edx
  1913.         js      .rotate_ccw4i.quit
  1914.         mov     esi, [ebx + Image.Data]
  1915.         add     esi, edx
  1916.         jmp     .rotate_ccw4i.begin
  1917. .rotate_ccw4i.quit:
  1918.         pop     esi                             ; get pointer to new data
  1919.         mov     edi, [ebx + Image.Data]
  1920.         pop     ecx                             ; get new data size
  1921.         rep movsb
  1922.         invoke  mem.free, esi
  1923.         pop     edx ecx
  1924.         jmp     .exchange_dims
  1925.  
  1926.  
  1927.  
  1928. .rotate_cw_low:
  1929.         mov     eax, [ebx + Image.Height]
  1930.         mov     [scanline_pixels_new], eax
  1931.         call    img._.get_scanline_len
  1932.         mov     [scanline_len_new], eax
  1933.  
  1934.         invoke  mem.alloc, eax
  1935.         or      eax, eax
  1936.         jz      .error
  1937.         mov     [line_buffer], eax
  1938.  
  1939.         mov     eax, [ebx + Image.Width]
  1940.         mov     ecx, eax
  1941.         call    img._.get_scanline_len
  1942.         mov     [scanline_len_old], eax
  1943.  
  1944.         mov     eax, [scanline_len_new]
  1945.         imul    eax, ecx
  1946.         add     eax, [ebx + Image.Data]
  1947.         mov     [pixels_ptr], eax
  1948.  
  1949.         cmp     [ebx + Image.Type], Image.bpp1
  1950.         jz      .rotate_cw1
  1951.         cmp     [ebx + Image.Type], Image.bpp2i
  1952.         jz      .rotate_cw2i
  1953.         cmp     [ebx + Image.Type], Image.bpp4i
  1954.         jz      .rotate_cw4i
  1955.         cmp     [ebx + Image.Type], Image.bpp8i
  1956.         jz      .rotate_cw8ig
  1957.         cmp     [ebx + Image.Type], Image.bpp8g
  1958.         jz      .rotate_cw8ig
  1959.         cmp     [ebx + Image.Type], Image.bpp24
  1960.         jz      .rotate_cw24
  1961.         cmp     [ebx + Image.Type], Image.bpp32
  1962.         jz      .rotate_cw32
  1963.  
  1964. .next_column_cw_low1x:
  1965.         dec     ecx
  1966.         js      .exchange_dims
  1967.         push    ecx
  1968.  
  1969.         mov     edx, [scanline_len_old]
  1970.         add     [scanline_len_old], -2
  1971.  
  1972.         mov     ecx, [scanline_pixels_new]
  1973.         mov     esi, [pixels_ptr]
  1974.         add     esi, -2
  1975.         mov     edi, [line_buffer]
  1976. @@:
  1977.         mov     ax, [esi]
  1978.         mov     [edi], ax
  1979.         sub     esi, edx
  1980.         add     edi, 2
  1981.         sub     ecx, 1
  1982.         jnz     @b
  1983.  
  1984.         mov     eax, [scanline_pixels_new]
  1985.         dec     eax
  1986.         mov     edi, [ebx + Image.Data]
  1987.         add     edi, [scanline_len_old]
  1988.         lea     esi, [edi + 2]
  1989.         mov     edx, [scanline_len_old]
  1990. @@:
  1991.         mov     ecx, edx
  1992.         shr     ecx, 2
  1993.         rep movsd
  1994.         mov     ecx, edx
  1995.         and     ecx, 3
  1996.         rep movsb
  1997.         add     esi, 3
  1998.         sub     eax, 1
  1999.         jnz     @b
  2000.  
  2001.         mov     eax, [scanline_len_new]
  2002.         sub     [pixels_ptr], eax
  2003.         mov     ecx, eax
  2004.         mov     esi, [line_buffer]
  2005.         mov     edi, [pixels_ptr]
  2006.         shr     ecx, 2
  2007.         rep movsd
  2008.         mov     ecx, eax
  2009.         and     ecx, 3
  2010.         rep movsb
  2011.  
  2012.         pop     ecx
  2013.         jmp     .next_column_cw_low1x
  2014.  
  2015. .rotate_cw32:
  2016. .next_column_cw_low:
  2017.         dec     ecx
  2018.         js      .exchange_dims
  2019.         push    ecx
  2020.  
  2021.         mov     edx, [scanline_len_old]
  2022.         add     [scanline_len_old], -4
  2023.  
  2024.         mov     ecx, [scanline_pixels_new]
  2025.         mov     esi, [pixels_ptr]
  2026.         add     esi, -4
  2027.         mov     edi, [line_buffer]
  2028. @@:
  2029.         mov     eax, [esi]
  2030.         stosd
  2031.         sub     esi, edx
  2032.         dec     ecx
  2033.         jnz     @b
  2034.  
  2035.         mov     eax, [scanline_pixels_new]
  2036.         dec     eax
  2037.         mov     edi, [ebx + Image.Data]
  2038.         add     edi, [scanline_len_old]
  2039.         lea     esi, [edi + 4]
  2040.         mov     edx, [scanline_len_old]
  2041.         shr     edx, 2
  2042. @@:
  2043.         mov     ecx, edx
  2044.         rep movsd
  2045.         add     esi, 4
  2046.         dec     eax
  2047.         jnz     @b
  2048.  
  2049.         mov     eax, [scanline_len_new]
  2050.         sub     [pixels_ptr], eax
  2051.         mov     ecx, [scanline_pixels_new]
  2052.         mov     esi, [line_buffer]
  2053.         mov     edi, [pixels_ptr]
  2054.         rep movsd
  2055.  
  2056.         pop     ecx
  2057.         jmp     .next_column_cw_low
  2058.  
  2059. .rotate_cw8ig:
  2060. .next_column_cw_low8ig:
  2061.         dec     ecx
  2062.         js      .exchange_dims
  2063.         push    ecx
  2064.  
  2065.         mov     edx, [scanline_len_old]
  2066.         add     [scanline_len_old], -1
  2067.  
  2068.         mov     ecx, [scanline_pixels_new]
  2069.         mov     esi, [pixels_ptr]
  2070.         add     esi, -1
  2071.         mov     edi, [line_buffer]
  2072. @@:
  2073.         mov     al, [esi]
  2074.         mov     [edi], al
  2075.         sub     esi, edx
  2076.         add     edi, 1
  2077.         sub     ecx, 1
  2078.         jnz     @b
  2079.  
  2080.         mov     eax, [scanline_pixels_new]
  2081.         dec     eax
  2082.         mov     edi, [ebx + Image.Data]
  2083.         add     edi, [scanline_len_old]
  2084.         lea     esi, [edi + 1]
  2085.         mov     edx, [scanline_len_old]
  2086. @@:
  2087.         mov     ecx, edx
  2088.         shr     ecx, 2
  2089.         rep movsd
  2090.         mov     ecx, edx
  2091.         and     ecx, 3
  2092.         rep movsb
  2093.         add     esi, 1
  2094.         sub     eax, 1
  2095.         jnz     @b
  2096.  
  2097.         mov     eax, [scanline_len_new]
  2098.         sub     [pixels_ptr], eax
  2099.         mov     ecx, eax
  2100.         mov     esi, [line_buffer]
  2101.         mov     edi, [pixels_ptr]
  2102.         shr     ecx, 2
  2103.         rep movsd
  2104.         mov     ecx, eax
  2105.         and     ecx, 3
  2106.         rep movsb
  2107.  
  2108.         pop     ecx
  2109.         jmp     .next_column_cw_low8ig
  2110.  
  2111. .rotate_cw24:
  2112. .next_column_cw_low24:
  2113.         dec     ecx
  2114.         js      .exchange_dims
  2115.         push    ecx
  2116.  
  2117.         mov     edx, [scanline_len_old]
  2118.         add     [scanline_len_old], -3
  2119.  
  2120.         mov     ecx, [scanline_pixels_new]
  2121.         mov     esi, [pixels_ptr]
  2122.         add     esi, -3
  2123.         mov     edi, [line_buffer]
  2124. @@:
  2125.         mov     al, [esi]
  2126.         mov     [edi], al
  2127.         mov     al, [esi+1]
  2128.         mov     [edi+1], al
  2129.         mov     al, [esi+2]
  2130.         mov     [edi+2], al
  2131.         sub     esi, edx
  2132.         add     edi, 3
  2133.         sub     ecx, 1
  2134.         jnz     @b
  2135.  
  2136.         mov     eax, [scanline_pixels_new]
  2137.         dec     eax
  2138.         mov     edi, [ebx + Image.Data]
  2139.         add     edi, [scanline_len_old]
  2140.         lea     esi, [edi + 3]
  2141.         mov     edx, [scanline_len_old]
  2142. @@:
  2143.         mov     ecx, edx
  2144.         shr     ecx, 2
  2145.         rep movsd
  2146.         mov     ecx, edx
  2147.         and     ecx, 3
  2148.         rep movsb
  2149.         add     esi, 3
  2150.         sub     eax, 1
  2151.         jnz     @b
  2152.  
  2153.         mov     eax, [scanline_len_new]
  2154.         sub     [pixels_ptr], eax
  2155.         mov     ecx, eax
  2156.         mov     esi, [line_buffer]
  2157.         mov     edi, [pixels_ptr]
  2158.         shr     ecx, 2
  2159.         rep movsd
  2160.         mov     ecx, eax
  2161.         and     ecx, 3
  2162.         rep movsb
  2163.  
  2164.         pop     ecx
  2165.         jmp     .next_column_cw_low24
  2166.  
  2167.  
  2168. .rotate_cw1:
  2169.         push    ecx edx
  2170.  
  2171.         mov     eax, [ebx + Image.Height]
  2172.         add     eax, 7
  2173.         shr     eax, 3
  2174.         imul    [ebx + Image.Width]
  2175.         push    eax                             ; save new data size
  2176.  
  2177.         invoke  mem.alloc, eax
  2178.         or      eax, eax
  2179.         jz      .error
  2180.         push    eax                             ; save pointer to new data
  2181.  
  2182.         mov     edi, eax
  2183.         mov     esi, [ebx + Image.Data]
  2184.         mov     eax, [ebx + Image.Height]
  2185.         dec     eax
  2186.         imul    eax, [scanline_len_old]
  2187.         add     esi, eax
  2188.         mov     eax, 7
  2189.         mov     ecx, 7
  2190.         mov     edx, 0
  2191.  
  2192. .rotate_cw1.begin:
  2193.         bt      [esi], ecx
  2194.         jc      .rotate_cw1.one
  2195. .rotate_cw1.zero:
  2196.         btr     [edi], eax
  2197.         jmp     @f
  2198. .rotate_cw1.one:
  2199.         bts     [edi], eax
  2200. @@:
  2201.         sub     esi, [scanline_len_old]
  2202.         dec     [scanline_pixels_new]
  2203.         jz      .rotate_cw1.end_of_line
  2204.         sub     eax, 1
  2205.         adc     edi, 0
  2206.         and     eax, 7
  2207.         jmp     .rotate_cw1.begin
  2208. .rotate_cw1.end_of_line:
  2209.         inc     edi
  2210.         mov     eax, [ebx + Image.Height]
  2211.         mov     [scanline_pixels_new], eax
  2212.         mov     eax, 7
  2213.         dec     ecx
  2214.         jns     @f
  2215.         mov     ecx, 7
  2216.         inc     edx
  2217.         cmp     edx, [scanline_len_old]
  2218.         je      .rotate_cw1.quit
  2219. @@:
  2220.         mov     esi, [ebx + Image.Height]
  2221.         dec     esi
  2222.         imul    esi, [scanline_len_old]
  2223.         add     esi, [ebx + Image.Data]
  2224.         add     esi, edx
  2225.         jmp     .rotate_cw1.begin
  2226. .rotate_cw1.quit:
  2227.         pop     eax                             ; get pointer to new data
  2228.         mov     esi, eax
  2229.         mov     edi, [ebx + Image.Data]
  2230.         pop     ecx                             ; get new data size
  2231.         rep movsb
  2232.         invoke  mem.free, eax
  2233.         pop     edx ecx
  2234.         jmp     .exchange_dims
  2235.  
  2236.  
  2237. .rotate_cw2i:
  2238.         push    ecx edx
  2239.  
  2240.         mov     eax, [ebx + Image.Height]
  2241.         add     eax, 3
  2242.         shr     eax, 2
  2243.         imul    [ebx + Image.Width]
  2244.         push    eax                             ; save new data size
  2245.  
  2246.         invoke  mem.alloc, eax
  2247.         or      eax, eax
  2248.         jz      .error
  2249.         push    eax                             ; save pointer to new data
  2250.  
  2251.         mov     edi, eax
  2252.         mov     esi, [ebx + Image.Data]
  2253.         mov     eax, [ebx + Image.Height]
  2254.         dec     eax
  2255.         imul    eax, [scanline_len_old]
  2256.         add     esi, eax
  2257.         mov     eax, 3
  2258.         mov     ecx, 3
  2259.         mov     edx, 0
  2260.  
  2261. .rotate_cw2i.begin:
  2262.         push    ebx ecx
  2263.         mov     ebx, 3
  2264.         shl     ebx, cl
  2265.         shl     ebx, cl
  2266.         and     bl, [esi]
  2267.         shr     ebx, cl
  2268.         shr     ebx, cl
  2269.         mov     bh, 3
  2270.         mov     ecx, eax
  2271.         shl     ebx, cl
  2272.         shl     ebx, cl
  2273.         not     bh
  2274.         and     bh, [edi]
  2275.         or      bl, bh
  2276.         mov     [edi], bl
  2277.         pop     ecx ebx
  2278.  
  2279.         sub     esi, [scanline_len_old]
  2280.         dec     [scanline_pixels_new]
  2281.         jz      .rotate_cw2i.end_of_line
  2282.         sub     eax, 1
  2283.         adc     edi, 0
  2284.         and     eax, 3
  2285.         jmp     .rotate_cw2i.begin
  2286. .rotate_cw2i.end_of_line:
  2287.         inc     edi
  2288.         mov     eax, [ebx + Image.Height]
  2289.         mov     [scanline_pixels_new], eax
  2290.         mov     eax, 3
  2291.         dec     ecx
  2292.         jns     @f
  2293.         mov     ecx, 3
  2294.         inc     edx
  2295.         cmp     edx, [scanline_len_old]
  2296.         je      .rotate_cw2i.quit
  2297. @@:
  2298.         mov     esi, [ebx + Image.Height]
  2299.         dec     esi
  2300.         imul    esi, [scanline_len_old]
  2301.         add     esi, [ebx + Image.Data]
  2302.         add     esi, edx
  2303.         jmp     .rotate_cw2i.begin
  2304. .rotate_cw2i.quit:
  2305.         pop     eax                             ; get pointer to new data
  2306.         mov     esi, eax
  2307.         mov     edi, [ebx + Image.Data]
  2308.         pop     ecx                             ; get new data size
  2309.         rep movsb
  2310.         invoke  mem.free, eax
  2311.         pop     edx ecx
  2312.         jmp     .exchange_dims
  2313.  
  2314.  
  2315. .rotate_cw4i:
  2316.         push    ecx edx
  2317.  
  2318.         mov     eax, [ebx + Image.Height]
  2319.         add     eax, 1
  2320.         shr     eax, 1
  2321.         imul    [ebx + Image.Width]
  2322.         push    eax                             ; save new data size
  2323.  
  2324.         invoke  mem.alloc, eax
  2325.         or      eax, eax
  2326.         jz      .error
  2327.         push    eax                             ; save pointer to new data
  2328.  
  2329.         mov     edi, eax
  2330.         mov     esi, [ebx + Image.Data]
  2331.         mov     eax, [ebx + Image.Height]
  2332.         dec     eax
  2333.         imul    eax, [scanline_len_old]
  2334.         add     esi, eax
  2335.         mov     eax, 1
  2336.         mov     ecx, 1
  2337.         mov     edx, 0
  2338.  
  2339. .rotate_cw4i.begin:
  2340.         push    ebx ecx
  2341.         mov     ebx, 15
  2342.         shl     ecx, 2
  2343.         shl     ebx, cl
  2344.         and     bl, [esi]
  2345.         shr     ebx, cl
  2346.         mov     bh, 15
  2347.         mov     ecx, eax
  2348.         shl     ecx, 2
  2349.         shl     ebx, cl
  2350.         not     bh
  2351.         and     bh, [edi]
  2352.         or      bl, bh
  2353.         mov     [edi], bl
  2354.         pop     ecx ebx
  2355.  
  2356.         sub     esi, [scanline_len_old]
  2357.         dec     [scanline_pixels_new]
  2358.         jz      .rotate_cw4i.end_of_line
  2359.         sub     eax, 1
  2360.         adc     edi, 0
  2361.         and     eax, 1
  2362.         jmp     .rotate_cw4i.begin
  2363. .rotate_cw4i.end_of_line:
  2364.         inc     edi
  2365.         mov     eax, [ebx + Image.Height]
  2366.         mov     [scanline_pixels_new], eax
  2367.         mov     eax, 1
  2368.         dec     ecx
  2369.         jns     @f
  2370.         mov     ecx, 1
  2371.         inc     edx
  2372.         cmp     edx, [scanline_len_old]
  2373.         je      .rotate_cw4i.quit
  2374. @@:
  2375.         mov     esi, [ebx + Image.Height]
  2376.         dec     esi
  2377.         imul    esi, [scanline_len_old]
  2378.         add     esi, [ebx + Image.Data]
  2379.         add     esi, edx
  2380.         jmp     .rotate_cw4i.begin
  2381. .rotate_cw4i.quit:
  2382.         pop     eax                             ; get pointer to new data
  2383.         mov     esi, eax
  2384.         mov     edi, [ebx + Image.Data]
  2385.         pop     ecx                             ; get new data size
  2386.         rep movsb
  2387.         invoke  mem.free, eax
  2388.         pop     edx ecx
  2389.         jmp     .exchange_dims
  2390.  
  2391.  
  2392. .flip:
  2393.         stdcall img.flip.layer, [_img], FLIP_VERTICAL
  2394.         test    eax, eax
  2395.         jz      .error
  2396.         jmp     .exit
  2397.  
  2398. .exchange_dims:
  2399.         push    [ebx + Image.Width] [ebx + Image.Height]
  2400.         pop     [ebx + Image.Width] [ebx + Image.Height]
  2401.  
  2402. .exit:
  2403.         invoke  mem.free, [line_buffer]
  2404.         xor     eax, eax
  2405.         inc     eax
  2406.         pop     edi esi ebx
  2407.         ret
  2408.  
  2409. .error:
  2410.         invoke  mem.free, [line_buffer]
  2411.         xor     eax, eax
  2412.         pop     edi esi ebx
  2413.         ret
  2414. endp
  2415.  
  2416. ;;============================================================================;;
  2417. proc img.rotate _img, _rotate_kind ;//////////////////////////////////////////;;
  2418. ;;----------------------------------------------------------------------------;;
  2419. ;? Rotate all layers of image                                                 ;;
  2420. ;;----------------------------------------------------------------------------;;
  2421. ;> _img = pointer to image                                                    ;;
  2422. ;> _rotate_kind = one of ROTATE_* constants                                   ;;
  2423. ;;----------------------------------------------------------------------------;;
  2424. ;< eax = false / true                                                         ;;
  2425. ;;============================================================================;;
  2426.         push    1
  2427.         mov     ebx, [_img]
  2428. @@:
  2429.         mov     eax, [ebx + Image.Previous]
  2430.         test    eax, eax
  2431.         jz      .loop
  2432.         mov     ebx, eax
  2433.         jmp     @b
  2434. .loop:
  2435.         stdcall img.rotate.layer, ebx, [_rotate_kind]
  2436.         test    eax, eax
  2437.         jnz     @f
  2438.         mov     byte [esp], 0
  2439. @@:
  2440.         mov     ebx, [ebx + Image.Next]
  2441.         test    ebx, ebx
  2442.         jnz     .loop
  2443.         pop     eax
  2444.         ret
  2445. endp
  2446.  
  2447. ;;============================================================================;;
  2448. proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;///////////////////;;
  2449. ;;----------------------------------------------------------------------------;;
  2450. ;? Draw image in the window                                                   ;;
  2451. ;;----------------------------------------------------------------------------;;
  2452. ;> _img = pointer to image                                                    ;;
  2453. ;>_x = x-coordinate in the window                                             ;;
  2454. ;>_y = y-coordinate in the window                                             ;;
  2455. ;>_width = maximum width to draw                                              ;;
  2456. ;>_height = maximum height to draw                                            ;;
  2457. ;>_xpos = offset in image by x-axis                                           ;;
  2458. ;>_ypos = offset in image by y-axis                                           ;;
  2459. ;;----------------------------------------------------------------------------;;
  2460. ;< no return value                                                            ;;
  2461. ;;============================================================================;;
  2462.         push    ebx esi edi
  2463.         mov     ebx, [_img]
  2464.         stdcall img._.validate, ebx
  2465.         test    eax, eax
  2466.         jnz     .done
  2467.         mov     ecx, [ebx + Image.Width]
  2468.         sub     ecx, [_xpos]
  2469.         jbe     .done
  2470.         cmp     ecx, [_width]
  2471.         jb      @f
  2472.         mov     ecx, [_width]
  2473. @@:
  2474.         mov     edx, [ebx + Image.Height]
  2475.         sub     edx, [_ypos]
  2476.         jbe     .done
  2477.         cmp     edx, [_height]
  2478.         jb      @f
  2479.         mov     edx, [_height]
  2480. @@:
  2481.         mov     eax, [ebx + Image.Width]
  2482.         sub     eax, ecx
  2483.         call    img._.get_scanline_len
  2484.         shl     ecx, 16
  2485.         add     ecx, edx
  2486.         push    eax
  2487.         mov     eax, [ebx + Image.Width]
  2488.         imul    eax, [_ypos]
  2489.         add     eax, [_xpos]
  2490.         call    img._.get_scanline_len
  2491.         add     eax, [ebx + Image.Data]
  2492.         mov     edx, [_x - 2]
  2493.         mov     dx, word [_y]
  2494.         mov     esi, [ebx + Image.Type]
  2495.         mov     esi, [type2bpp + (esi-1)*4]
  2496.         mov     edi, [ebx + Image.Palette]
  2497.         xchg    eax, ebx
  2498.         pop     eax
  2499.         push    ebp
  2500.         push    65
  2501.         pop     ebp
  2502.         xchg    eax, ebp
  2503.         int     40h
  2504.         pop     ebp
  2505. .done:
  2506.         pop     edi esi ebx
  2507.         ret
  2508. endp
  2509.  
  2510.  
  2511. align 4
  2512. img.formats_table:
  2513.   .bmp  dd LIBIMG_FORMAT_BMP,  img.is.bmp,  img.decode.bmp,     img.encode.bmp, 1 + (1 SHL Image.bpp24) + (1 SHL Image.bpp32)
  2514.   .ico  dd LIBIMG_FORMAT_ICO,  img.is.ico,  img.decode.ico_cur, img.encode.ico, 0
  2515.   .cur  dd LIBIMG_FORMAT_CUR,  img.is.cur,  img.decode.ico_cur, img.encode.cur, 0
  2516.   .gif  dd LIBIMG_FORMAT_GIF,  img.is.gif,  img.decode.gif,     img.encode.gif, 0
  2517.   .png  dd LIBIMG_FORMAT_PNG,  img.is.png,  img.decode.png,     img.encode.png, 1 + (1 SHL Image.bpp24)
  2518.   .jpg  dd LIBIMG_FORMAT_JPEG, img.is.jpg,  img.decode.jpg,     img.encode.jpg, 0
  2519.   .tga  dd LIBIMG_FORMAT_TGA,  img.is.tga,  img.decode.tga,     img.encode.tga, 0
  2520.   .pcx  dd LIBIMG_FORMAT_PCX,  img.is.pcx,  img.decode.pcx,     img.encode.pcx, 0
  2521.   .xcf  dd LIBIMG_FORMAT_XCF,  img.is.xcf,  img.decode.xcf,     img.encode.xcf, 0
  2522.   .tiff dd LIBIMG_FORMAT_TIFF, img.is.tiff, img.decode.tiff,    img.encode.tiff,0
  2523.   .pnm  dd LIBIMG_FORMAT_PNM,  img.is.pnm,  img.decode.pnm,     img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8g) + (1 SHL Image.bpp24)
  2524.   .wbmp dd LIBIMG_FORMAT_WBMP, img.is.wbmp, img.decode.wbmp,    img.encode.wbmp,0
  2525.   .xbm  dd LIBIMG_FORMAT_XBM,  img.is.xbm,  img.decode.xbm,     img.encode.xbm, 0
  2526.   .z80  dd LIBIMG_FORMAT_Z80,  img.is.z80,  img.decode.z80,     img.encode.z80, 0 ;this must be the last entry as there are no signatures in z80 screens at all
  2527.         dd 0
  2528.  
  2529. ;;============================================================================;;
  2530. ;;////////////////////////////////////////////////////////////////////////////;;
  2531. ;;============================================================================;;
  2532. ;! Below are private procs you should never call directly from your code      ;;
  2533. ;;============================================================================;;
  2534. ;;////////////////////////////////////////////////////////////////////////////;;
  2535. ;;============================================================================;;
  2536.  
  2537.  
  2538. ;;============================================================================;;
  2539. proc img._.validate, _img ;///////////////////////////////////////////////////;;
  2540. ;;----------------------------------------------------------------------------;;
  2541. ;? --- TBD ---                                                                ;;
  2542. ;;----------------------------------------------------------------------------;;
  2543. ;> --- TBD ---                                                                ;;
  2544. ;;----------------------------------------------------------------------------;;
  2545. ;< --- TBD ---                                                                ;;
  2546. ;;============================================================================;;
  2547.         xor     eax, eax
  2548.         ret
  2549. endp
  2550.  
  2551. ;;============================================================================;;
  2552. proc img._.new ;//////////////////////////////////////////////////////////////;;
  2553. ;;----------------------------------------------------------------------------;;
  2554. ;? --- TBD ---                                                                ;;
  2555. ;;----------------------------------------------------------------------------;;
  2556. ;> --- TBD ---                                                                ;;
  2557. ;;----------------------------------------------------------------------------;;
  2558. ;< eax = 0 / pointer to image                                                 ;;
  2559. ;;============================================================================;;
  2560.         invoke  mem.alloc, sizeof.Image
  2561.         test    eax, eax
  2562.         jz      @f
  2563.         push    ecx
  2564.         xor     ecx, ecx
  2565.         mov     [eax + Image.Data], ecx
  2566.         mov     [eax + Image.Type], ecx
  2567.         mov     [eax + Image.Flags], ecx
  2568.         mov     [eax + Image.Extended], ecx
  2569.         mov     [eax + Image.Previous], ecx
  2570.         mov     [eax + Image.Next], ecx
  2571.         pop     ecx
  2572. @@:
  2573.         ret
  2574. endp
  2575.  
  2576. ;;============================================================================;;
  2577. proc img._.delete _img ;//////////////////////////////////////////////////////;;
  2578. ;;----------------------------------------------------------------------------;;
  2579. ;? --- TBD ---                                                                ;;
  2580. ;;----------------------------------------------------------------------------;;
  2581. ;> --- TBD ---               &nbs