Subversion Repositories Kolibri OS

Rev

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