Subversion Repositories Kolibri OS

Rev

Rev 7105 | Rev 8341 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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