Subversion Repositories Kolibri OS

Rev

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

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