Subversion Repositories Kolibri OS

Rev

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