Subversion Repositories Kolibri OS

Rev

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

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