Subversion Repositories Kolibri OS

Rev

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