Subversion Repositories Kolibri OS

Rev

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

  1. ;;================================================================================================;;
  2. ;;//// gif.asm //// (c) mike.dld, 2007-2008 //////////////////////////////////////////////////////;;
  3. ;;================================================================================================;;
  4. ;;//// Partial (c) by Willow, Diamond and HidnPlayr //////////////////////////////////////////////;;
  5. ;;================================================================================================;;
  6. ;;                                                                                                ;;
  7. ;; This file is part of Common development libraries (Libs-Dev).                                  ;;
  8. ;;                                                                                                ;;
  9. ;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;;
  10. ;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;;
  11. ;; of the License, or (at your option) any later version.                                         ;;
  12. ;;                                                                                                ;;
  13. ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without  ;;
  14. ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  ;;
  15. ;; Lesser General Public License for more details.                                                ;;
  16. ;;                                                                                                ;;
  17. ;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev.  ;;
  18. ;; If not, see <http://www.gnu.org/licenses/>.                                                    ;;
  19. ;;                                                                                                ;;
  20. ;;================================================================================================;;
  21. ;;                                                                                                ;;
  22. ;; References:                                                                                    ;;
  23. ;;   1. GIF LITE v3.0 (2004-2007)                                                                 ;;
  24. ;;      by Willow and Diamond                                                                     ;;
  25. ;;      svn://kolibrios.org/programs/media/gifview/trunk/gif_lite.inc                             ;;
  26. ;;   2. "GIF File Format Summary"                                                                 ;;
  27. ;;      from "Encyclopedia of Graphics File Formats" by O'Reilly                                  ;;
  28. ;;      http://www.fileformat.info/format/gif/                                                    ;;
  29. ;;   3. "LZW and GIF explained" (1987)                                                            ;;
  30. ;;      by Steve Blackstock, IEEE                                                                 ;;
  31. ;;      http://www.cis.udel.edu/~amer/CISC651/lzw.and.gif.explained.html                          ;;
  32. ;;   4. "Graphics Interchange Format (tm)" (June 15, 1987)                                        ;;
  33. ;;      by CompuServe Incorporated                                                                ;;
  34. ;;      http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF87A.TXT         ;;
  35. ;;   5. "Graphics Interchange Format (sm)" (July 31, 1990)                                        ;;
  36. ;;      by CompuServe Incorporated                                                                ;;
  37. ;;      http://examples.oreilly.de/english_examples/gff/CDROM/GFF/VENDSPEC/GIF/GIF89A.TXT         ;;
  38. ;;                                                                                                ;;
  39. ;;================================================================================================;;
  40.  
  41.  
  42. include 'gif.inc'
  43.  
  44. ;;================================================================================================;;
  45. proc img.is.gif _data, _length ;//////////////////////////////////////////////////////////////////;;
  46. ;;------------------------------------------------------------------------------------------------;;
  47. ;? Determine if raw data could be decoded (is in GIF format)                                      ;;
  48. ;;------------------------------------------------------------------------------------------------;;
  49. ;> _data = raw data as read from file/stream                                                      ;;
  50. ;> _length = data length                                                                          ;;
  51. ;;------------------------------------------------------------------------------------------------;;
  52. ;< eax = false / true                                                                             ;;
  53. ;;================================================================================================;;
  54.         cmp     [_length], sizeof.gif.Header
  55.         jb      .nope
  56.         mov     eax, [_data]
  57.         cmp     dword[eax], 'GIF8'
  58.         jne     .nope
  59.         cmp     word[eax + 4], '7a'
  60.         je      .yep
  61.         cmp     word[eax + 4], '9a'
  62.         je      .yep
  63.  
  64.   .nope:
  65.         xor     eax, eax
  66.         ret
  67.  
  68.   .yep:
  69.         xor     eax, eax
  70.         inc     eax
  71.         ret
  72. endp
  73.  
  74. ;;================================================================================================;;
  75. proc img.decode.gif _data, _length ;//////////////////////////////////////////////////////////////;;
  76. ;;------------------------------------------------------------------------------------------------;;
  77. ;? Decode data into image if it contains correctly formed raw data in GIF format                  ;;
  78. ;;------------------------------------------------------------------------------------------------;;
  79. ;> _data = raw data as read from file/stream                                                      ;;
  80. ;> _length = data length                                                                          ;;
  81. ;;------------------------------------------------------------------------------------------------;;
  82. ;< eax = 0 (error) or pointer to image                                                            ;;
  83. ;;================================================================================================;;
  84. locals
  85.   max_color          dd ?
  86.   cur_color_table_size dd ?
  87.   transparent_color  dd ?
  88.   background_color   dd ?
  89.   prev_palette       dd ?
  90.   aux_palette        dd ?
  91.   img                dd ?
  92.   prev_img_data      dd ?
  93.   aux_img_data       dd ?
  94.   aux_img_type       dd ?
  95.   prev_num_colors    dd ?
  96.   main_img           dd ?
  97.   global_color_table dd ?
  98.   global_color_table_size dd ?
  99. endl
  100.  
  101. img.decode.gif.main_img equ main_img
  102. img.decode.gif.prev_img_data equ prev_img_data
  103. img.decode.gif.transparent_color equ transparent_color
  104. img.decode.gif.background_color equ background_color
  105. img.decode.gif._length equ _length
  106. img.decode.gif.prev_num_colors equ prev_num_colors
  107. img.decode.gif.prev_palette equ prev_palette
  108. img.decode.gif.max_color equ max_color
  109. img.decode.gif._data equ _data
  110. img.decode.gif.aux_img_data equ aux_img_data
  111. img.decode.gif.aux_img_type equ aux_img_type
  112. img.decode.gif.aux_palette equ aux_palette
  113. ; offset of _length parameter for child functions with ebp-based frame
  114. ; child saved ebp, return address, 3 saved registers, 14 local variables
  115. img.decode.gif._length_child equ _length + 4 + 4 + 4*3 + 4*14
  116. img.decode.gif.max_color_child equ ebp + 4 + 4 + 4*3
  117. img.decode.gif.cur_color_table_size_child equ ebp + 4 + 4 + 4*3 + 4
  118.  
  119.         push    ebx esi edi
  120.         xor     eax, eax
  121.         mov     [img], eax
  122.         mov     [main_img], eax
  123.         mov     [prev_img_data], eax
  124.         mov     [aux_img_data], eax
  125.         mov     [aux_img_type], eax
  126.         mov     [prev_palette], eax
  127.         mov     [aux_palette], eax
  128. ; when no previous image is available, use background fill with 1-entry palette
  129.         inc     eax
  130.         mov     [prev_num_colors], eax
  131.         lea     eax, [background_color]
  132.         mov     [prev_palette], eax
  133. ; guard against incorrect gif files, which use Restore-To-Background disposal method, but do not define bgr color
  134.         mov     dword [eax], 0xFFFFFF
  135. ; guard against incorrect gif files without any color tables
  136. ; "If no color table is available at
  137. ; all, the decoder is free to use a system color table or a table of its own. In
  138. ; that case, the decoder may use a color table with as many colors as its
  139. ; hardware is able to support; it is recommended that such a table have black and
  140. ; white as its first two entries, so that monochrome images can be rendered
  141. ; adequately." (c) official gif documentation
  142.         mov     [global_color_table], gif_default_palette
  143.         mov     [global_color_table_size], 2
  144.  
  145. ; img.is.gif is called by caller (img.decode)
  146. ;       stdcall img.is.gif, [_data], [_length]
  147. ;       or      eax, eax
  148. ;       jz      .error
  149.  
  150.         mov     ebx, [_data]
  151.         sub     [_length], sizeof.gif.Header
  152.  
  153.         mov     cl, [ebx + gif.Header.lsd.Packed]
  154.         add     ebx, sizeof.gif.Header
  155. ; gif.LSD.Packed.GlobalColorTableFlag = 80h
  156. ;       test    cl, gif.LSD.Packed.GlobalColorTableFlag
  157. ;       jz      @f
  158.         test    cl, cl
  159.         jns     @f
  160.         mov     [global_color_table], ebx
  161.         and     cl, gif.LSD.Packed.SizeOfGlobalColorTableMask
  162. ;       shr     cl, gif.LSD.Packed.SizeOfGlobalColorTableShift  ; here Shift = 0
  163.         push    2
  164.         pop     eax
  165.         shl     eax, cl
  166.         mov     [global_color_table_size], eax
  167.         lea     eax, [eax * 3]
  168.         sub     [_length], eax
  169.         jbe     .error  ; there must be at least 1 additional byte after color table
  170.         movzx   ecx, byte [ebx - sizeof.gif.Header + gif.Header.lsd.BackgroundColor]
  171.         lea     ecx, [ecx*3]
  172.         mov     ecx, [ebx + ecx]        ; eax = xxBBGGRR, convert to Kolibri color
  173.         bswap   ecx
  174.         shr     ecx, 8
  175.         mov     [background_color], ecx
  176.         add     ebx, eax
  177.     @@:
  178.  
  179. ;   @@: cmp     byte[ebx + gif.Block.Introducer], gif.Block.Introducer.Extension
  180. ;       jne     .next_image
  181. ;       cmp     byte[ebx + gif.Extension.Label], gif.Extension.Label.Comment
  182. ;       jne     .error
  183. ;       add     ebx, sizeof.gif.Extension
  184. ;       stdcall ._.skip_data
  185. ;       mov     ebx, eax
  186. ;       jmp     @b
  187.  
  188.   .next_image:
  189.         stdcall img._.new
  190.         or      eax, eax
  191.         jz      .error
  192.         mov     edx, [img]
  193.         mov     [eax + Image.Previous], edx
  194.         push    sizeof.gif.LogicalScreenDescriptor
  195.         pop     ecx
  196.         test    edx, edx
  197.         jz      @f
  198.         mov     [edx + Image.Next], eax
  199.         xor     ecx, ecx
  200.   @@:
  201.         push    eax
  202.         mov     [eax + Image.Type], Image.bpp8
  203.  
  204.         add     ecx, sizeof.gif.Image
  205.         invoke  mem.alloc, ecx
  206.         pop     edx
  207.         or      eax, eax
  208.         jz      .error2
  209.         mov     [edx + Image.Extended], eax
  210.         xor     ecx, ecx
  211.         cmp     [img], ecx
  212.         jnz     @f
  213.         mov     esi, [_data]
  214.         add     esi, gif.Header.lsd
  215.         lea     edi, [eax + sizeof.gif.Image]
  216.         mov     cl, sizeof.gif.LogicalScreenDescriptor
  217.         rep     movsb
  218.         mov     [main_img], edx
  219.   @@:
  220.         mov     [img], edx
  221.  
  222.         stdcall ._.process_extensions
  223.  
  224.         cmp     al, gif.Block.Introducer.ImageDescriptor
  225.         jne     .error
  226.         sub     [_length], sizeof.gif.ImageDescriptor
  227.         jc      .error
  228.         movzx   eax, [ebx + gif.ImageDescriptor.Width]
  229.         movzx   ecx, [ebx + gif.ImageDescriptor.Height]
  230.         push    edx
  231.         stdcall img._.resize_data, [img], eax, ecx
  232.         pop     edx
  233.         or      eax, eax
  234.         jz      .error
  235.  
  236.         mov     esi, ebx
  237.         mov     edi, [edx + Image.Extended]
  238.         mov     ecx, sizeof.gif.ImageDescriptor
  239.         rep     movsb
  240.  
  241.         mov     edi, [edx + Image.Palette]
  242.         mov     esi, [global_color_table]
  243.         mov     ecx, [global_color_table_size]
  244.         test    [ebx + gif.ImageDescriptor.Packed], gif.ID.Packed.LocalColorTableFlag
  245.         jz      @f
  246.         lea     esi, [ebx + sizeof.gif.ImageDescriptor]
  247.         mov     cl, [ebx + gif.ImageDescriptor.Packed]
  248.         and     cl, gif.ID.Packed.SizeOfLocalColorTableMask
  249. ; here Shift = 0
  250. ;       shr     cl, gif.ID.Packed.SizeOfLocalColorTableShift
  251.         push    2
  252.         pop     eax
  253.         shl     eax, cl
  254.         mov     ecx, eax
  255.         lea     eax, [eax*3]
  256.         add     ebx, eax
  257.         sub     [_length], eax
  258.         jbe     .error  ; because we load additional byte, check is 'jbe', not 'jc'
  259. @@:
  260.         mov     [cur_color_table_size], ecx
  261.         dec     [cur_color_table_size]
  262. @@:
  263.         lodsd
  264.         dec     esi
  265.         bswap   eax
  266.         shr     eax, 8
  267.         stosd
  268.         loop    @b
  269.         add     ebx, sizeof.gif.ImageDescriptor
  270.         stdcall ._.process_image
  271.         push    ebx
  272.         mov     edx, [img]
  273.         push    edx
  274.         stdcall ._.superimpose
  275.         pop     edx
  276.         push    edx
  277.         stdcall ._.dispose
  278.         pop     edx
  279.         mov     edx, [edx + Image.Previous]
  280.         test    edx, edx
  281.         jz      .nofreeprev
  282.         mov     ebx, [edx + Image.Extended]
  283.         cmp     [ebx + gif.Image.gce.DelayTime], 0
  284.         jnz     .nofreeprev
  285.         mov     esi, [prev_palette]
  286.         cmp     esi, [edx + Image.Palette]
  287.         jnz     @f
  288.         mov     ecx, [prev_num_colors]
  289.         stdcall ._.alloc_aux_palette
  290.         test    eax, eax
  291.         jz      .nofreeprev
  292.         mov     [prev_palette], eax
  293.     @@:
  294.         mov     esi, [prev_img_data]
  295.         cmp     esi, [edx + Image.Data]
  296.         jnz     .noprevdata
  297.         push    1
  298.         pop     eax
  299.         cmp     [edx + Image.Type], Image.bpp8
  300.         jz      @f
  301.         mov     al, 3
  302.     @@:
  303.         cmp     [aux_img_type], eax
  304.         jb      .resetaux
  305.         mov     edi, [aux_img_data]
  306.         imul    eax, [edx + Image.Width]
  307.         imul    eax, [edx + Image.Height]
  308.         xchg    eax, ecx
  309.         rep     movsb
  310.         jmp     .noprevdata
  311.     .resetaux:
  312.         mov     [aux_img_type], eax
  313.         mov     eax, [aux_img_data]
  314.         test    eax, eax
  315.         jz      @f
  316.         invoke  mem.free, eax
  317.     @@:
  318.         xor     eax, eax
  319.         xchg    eax, [edx + Image.Data]
  320.         mov     [aux_img_data], eax
  321.     .noprevdata:
  322.         cmp     edx, [main_img]
  323.         jnz     @f
  324.         mov     eax, [edx + Image.Next]
  325.         mov     [main_img], eax
  326.         mov     esi, [eax + Image.Extended]
  327.         mov     edi, [edx + Image.Extended]
  328.         mov     [edx + Image.Extended], esi
  329.         mov     [eax + Image.Extended], edi
  330.         push    sizeof.gif.Image
  331.         pop     ecx
  332.         rep     movsb
  333.     @@:
  334.         stdcall img.destroy.layer, edx
  335.   .nofreeprev:
  336.         pop     ebx
  337.         test    ebx, ebx
  338.         jz      .ret
  339.         jmp     .next_image
  340.  
  341.   .error2:
  342.         mov     [img], edx
  343.  
  344.   .error:
  345.         mov     eax, [img]
  346.         test    eax, eax
  347.         jz      .ret
  348.         cmp     [main_img], eax
  349.         jnz     @f
  350.         and     [main_img], 0
  351.   @@:
  352.         stdcall img.destroy.layer, eax
  353.   .ret:
  354.         mov     eax, [aux_img_data]
  355.         test    eax, eax
  356.         jz      @f
  357.         invoke  mem.free, eax
  358.   @@:
  359.         mov     eax, [aux_palette]
  360.         test    eax, eax
  361.         jz      @f
  362.         invoke  mem.free, eax
  363.   @@:
  364.         mov     eax, [main_img]
  365.         cmp     [eax + Image.Next], 0
  366.         jz      @f
  367.         or      [eax + Image.Flags], Image.IsAnimated
  368.   @@:
  369.         pop     edi esi ebx
  370.         ret
  371. endp
  372.  
  373. ;;================================================================================================;;
  374. proc img.encode.gif _img, _p_length ;/////////////////////////////////////////////////////////////;;
  375. ;;------------------------------------------------------------------------------------------------;;
  376. ;? Encode image into raw data in GIF format                                                       ;;
  377. ;;------------------------------------------------------------------------------------------------;;
  378. ;> _img = pointer to image                                                                        ;;
  379. ;;------------------------------------------------------------------------------------------------;;
  380. ;< eax = 0 (error) or pointer to encoded data                                                     ;;
  381. ;< _p_length = encoded data length                                                                ;;
  382. ;;================================================================================================;;
  383.         xor     eax, eax
  384.         ret
  385. endp
  386.  
  387.  
  388. ;;================================================================================================;;
  389. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  390. ;;================================================================================================;;
  391. ;! Below are private procs you should never call directly from your code                          ;;
  392. ;;================================================================================================;;
  393. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  394. ;;================================================================================================;;
  395.  
  396.  
  397. ;;================================================================================================;;
  398. proc img.decode.gif._.process_extensions ;////////////////////////////////////////////////////////;;
  399. ;;------------------------------------------------------------------------------------------------;;
  400. ;? --- TBD ---                                                                                    ;;
  401. ;;------------------------------------------------------------------------------------------------;;
  402. ;> ebx = raw image data                                                                           ;;
  403. ;> edx = image data                                                                               ;;
  404. ;;------------------------------------------------------------------------------------------------;;
  405. ;< --- TBD ---                                                                                    ;;
  406. ;;================================================================================================;;
  407.         mov     esi, ebx
  408.         xor     eax, eax
  409.         mov     [edx + Image.Delay], eax
  410.  
  411.   .next_block:
  412.         dec     [img.decode.gif._length]
  413.         js      .exit_err
  414.         lodsb   ; load gif.Block.Introducer
  415.         cmp     al, gif.Block.Introducer.Extension
  416.         jne     .exit
  417.  
  418.   .ext_block:
  419.         dec     [img.decode.gif._length]
  420.         js      .exit_err
  421.         lodsb   ; load gif.Extension.Label
  422.         cmp     al, gif.Extension.Label.GraphicsControl
  423.         je      .graphics_control_ext
  424. ;       cmp     al, gif.Extension.Label.PlainText
  425. ;       je      .plain_text_ext
  426. ;       cmp     al, gif.Extension.Label.Comment
  427. ;       je      .comment_ext
  428. ;       cmp     al, gif.Extension.Label.Application
  429. ;       je      .application_ext
  430. ; skip all other extensions
  431.   .skip_ext:
  432.         dec     [img.decode.gif._length]
  433.         js      .exit_err
  434.         lodsb   ; load BlockSize
  435.   .1:
  436.         test    al, al
  437.         jz      .next_block
  438.         sub     [img.decode.gif._length], eax
  439.         jc      .exit_err
  440.         add     esi, eax
  441.         jmp     .skip_ext
  442.  
  443.   .graphics_control_ext:
  444.         dec     [img.decode.gif._length]
  445.         js      .exit_err
  446.         lodsb   ; load BlockSize; must be sizeof.gif.GraphicsControlExtension
  447.         cmp     al, sizeof.gif.GraphicsControlExtension
  448.         jnz     .1
  449.         sub     [img.decode.gif._length], eax
  450.         jc      .exit_err
  451.         push    edi
  452.         movzx   edi, [esi + gif.GraphicsControlExtension.DelayTime]
  453.         mov     [edx + Image.Delay], edi
  454.         mov     edi, [edx + Image.Extended]
  455.         add     edi, gif.Image.gce
  456.         mov     ecx, eax
  457.         rep     movsb
  458.         pop     edi
  459.         jmp     .skip_ext
  460.  
  461.   .exit_err:
  462.         xor     eax, eax
  463.  
  464.   .exit:
  465.         mov     ebx, esi
  466.         ret
  467. endp
  468.  
  469. ;;================================================================================================;;
  470. proc img.decode.gif._.process_image ;/////////////////////////////////////////////////////////////;;
  471. ;;------------------------------------------------------------------------------------------------;;
  472. ;? --- TBD ---                                                                                    ;;
  473. ;;------------------------------------------------------------------------------------------------;;
  474. ;> ebx = raw image data                                                                           ;;
  475. ;> edx = image data                                                                               ;;
  476. ;;------------------------------------------------------------------------------------------------;;
  477. ;< --- TBD ---                                                                                    ;;
  478. ;;================================================================================================;;
  479. locals
  480.   width      dd ?
  481.   img_start  dd ?
  482.   img_end    dd ?
  483.   row_end    dd ?
  484.   pass       dd ?
  485.   codesize   dd ?
  486.   compsize   dd ?
  487.   workarea   dd ?
  488.   block_ofs  dd ?
  489.   bit_count  dd ?
  490.   CC         dd ?
  491.   EOI        dd ?
  492. endl
  493.  
  494.         invoke  mem.alloc, 16 * 1024
  495.         mov     [workarea], eax
  496.         or      eax, eax
  497.         jz      .error
  498.  
  499.         mov     ecx, [edx + Image.Width]
  500.         mov     [width], ecx
  501.         mov     eax, [edx + Image.Height]
  502.         imul    eax, ecx
  503.         mov     [img_end], eax
  504.         inc     eax
  505.         mov     [row_end], eax
  506.         and     [pass], 0
  507.         and     dword [img.decode.gif.max_color_child], 0
  508.         mov     eax, [edx + Image.Extended]
  509.         test    [eax + gif.Image.info.Packed], gif.ID.Packed.InterleaceFlag
  510.         jz      @f
  511.         mov     [row_end], ecx
  512.  
  513.     @@: mov     esi, ebx
  514.         mov     edi, [edx + Image.Data]
  515.  
  516.         sub     dword [img.decode.gif._length_child], 2
  517.         jc      .error
  518.         movzx   ecx, byte[esi]
  519.         inc     esi
  520.         cmp     cl, 12
  521.         jae     .error
  522.         mov     [codesize], ecx
  523.         inc     [codesize]
  524.         xor     eax, eax
  525.         lodsb                           ; eax - block_count
  526.         sub     [img.decode.gif._length_child], eax
  527.         jc      .error
  528.         add     eax, esi
  529.         push    edi
  530.         mov     edi, [workarea]
  531.         mov     [block_ofs], eax
  532.         mov     [bit_count], 8
  533.         mov     eax, 1
  534.         shl     eax, cl
  535.         mov     [CC], eax
  536.         mov     ecx, eax
  537.         inc     eax
  538.         mov     [EOI], eax
  539.         mov     eax, gif.Null shl 16
  540.   .filltable:
  541.         stosd
  542.         inc     eax
  543.         loop    .filltable
  544.         pop     edi
  545.         mov     [img_start], edi
  546.         add     [img_end], edi
  547.         add     [row_end], edi
  548.   .reinit:
  549.         mov     edx, [EOI]
  550.         inc     edx
  551.         push    [codesize]
  552.         pop     [compsize]
  553.         call    .get_symbol
  554.         cmp     eax, [CC]
  555.         je      .reinit
  556.         call    .output
  557.   .cycle:
  558.         movzx   ebx, ax
  559.         call    .get_symbol
  560.         cmp     eax, [EOI]
  561.         je      .end
  562.         cmp     eax, edx
  563.         ja      .error
  564.         je      .notintable
  565.         cmp     eax, [CC]
  566.         je      .reinit
  567.         call    .output
  568.   .add:
  569.         cmp     edx, 0x00001000
  570.         jae     .cycle
  571.         mov     ecx, [workarea]
  572.         mov     [ecx + edx * 4], ebx
  573.         inc     edx
  574.         cmp     edx, 0x1000
  575.         je      .noinc
  576.         bsr     ebx, edx
  577.         cmp     ebx, [compsize]
  578.         jne     .noinc
  579.         inc     [compsize]
  580.   .noinc:
  581.         jmp     .cycle
  582.   .notintable:
  583.         push    eax
  584.         mov     eax, ebx
  585.         call    .output
  586.         push    ebx
  587.         movzx   eax, bx
  588.         call    .output
  589.         pop     ebx eax
  590.         jmp     .add
  591.   .end:
  592.         mov     edi, [img_end]
  593.         xor     eax, eax
  594.  
  595.   .exit:
  596.         cmp     [workarea], 0
  597.         je      @f
  598.         invoke  mem.free, [workarea]
  599.     @@:
  600.         mov     ebx, [block_ofs]
  601.     @@:
  602.         dec     [img.decode.gif._length_child]
  603.         js      @f
  604.         movzx   eax, byte [ebx]
  605.         inc     ebx
  606.         test    eax, eax
  607.         jz      .ret
  608.         sub     [img.decode.gif._length_child], eax
  609.         jc      @f
  610.         add     ebx, eax
  611.         jmp     @b
  612.  
  613.   .error:
  614.         cmp     [workarea], 0
  615.         je      @f
  616.         invoke  mem.free, [workarea]
  617.     @@: xor     ebx, ebx
  618.   .ret:
  619.         ret
  620.  
  621. ;;------------------------------------------------------------------------------------------------;;
  622.  
  623. img.decode.gif._.process_image.get_symbol:
  624.         mov     ecx, [compsize]
  625.         push    ecx
  626.         xor     eax, eax
  627.  
  628.   .shift:
  629.         dec     [bit_count]
  630.         jns     .loop1
  631.         inc     esi
  632.         cmp     esi, [block_ofs]
  633.         jb      .noblock
  634.         push    eax
  635.         xor     eax, eax
  636.         sub     [img.decode.gif._length_child], 1
  637.         jc      .error_eof
  638.         lodsb
  639.         test    eax, eax
  640.         jnz     .nextbl
  641.   .error_eof:
  642.         add     esp, 12
  643.         jmp     img.decode.gif._.process_image.error
  644.  
  645.   .nextbl:
  646.         sub     [img.decode.gif._length_child], eax
  647.         jc      .error_eof
  648.         add     eax, esi
  649.         mov     [block_ofs], eax
  650.         pop     eax
  651.  
  652.   .noblock:
  653.         mov     [bit_count], 7
  654.  
  655.   .loop1:
  656.         ror     byte[esi], 1
  657.         rcr     eax,1
  658.         loop    .shift
  659.         pop     ecx
  660.         rol     eax, cl
  661.  
  662.   .exit:
  663.         xor     ecx, ecx
  664.         retn
  665.  
  666. ;;------------------------------------------------------------------------------------------------;;
  667.  
  668. img.decode.gif._.process_image.output:
  669.         push    esi eax edx
  670.         mov     edx, [workarea]
  671.  
  672.   .next:
  673.         pushw   [edx + eax * 4]
  674.         mov     ax, [edx + eax * 4 + 2]
  675.         inc     ecx
  676.         cmp     ax, gif.Null
  677.         jnz     .next
  678.         shl     ebx, 16
  679.         mov     bx, [esp]
  680.  
  681.   .loop2:
  682.         pop     ax
  683.         cmp     al, byte [img.decode.gif.cur_color_table_size_child]
  684.         jbe     @f      ; guard against incorrect GIFs
  685.         mov     al, 0
  686.     @@: cmp     al, byte [img.decode.gif.max_color_child]
  687.         jbe     @f
  688.         mov     [img.decode.gif.max_color_child], al
  689.     @@: stosb
  690.  
  691.         cmp     edi, [img_end]
  692.         jz      .done
  693.         cmp     edi, [row_end]
  694.         jb      .norowend
  695.         mov     eax, [width]
  696.         push    eax
  697.         sub     edi, eax
  698.         add     eax, eax
  699.         cmp     [pass], 3
  700.         je      @f
  701.         add     eax, eax
  702.         cmp     [pass], 2
  703.         je      @f
  704.         add     eax, eax
  705.     @@: add     edi, eax
  706.         pop     eax
  707.         cmp     edi, [img_end]
  708.         jb      .nextrow
  709.         mov     edi, [img_start]
  710.         inc     [pass]
  711.         add     edi, eax
  712.         cmp     [pass], 3
  713.         je      @f
  714.         add     edi, eax
  715.         cmp     [pass], 2
  716.         je      @f
  717.         add     edi, eax
  718.         add     edi, eax
  719.     @@:
  720.  
  721.   .nextrow:
  722.         add     eax, edi
  723.         mov     [row_end], eax
  724.         xor     eax, eax
  725.  
  726.   .norowend:
  727.         loop    .loop2
  728.         pop     edx eax esi
  729.         retn
  730.  
  731.   .done:
  732.         lea     esp, [esp+(ecx-1)*2]
  733.         pop     edx eax esi eax
  734.         jmp     img.decode.gif._.process_image.exit
  735.  
  736. endp
  737.  
  738. ;;================================================================================================;;
  739. proc img.decode.gif._.is_logical_screen ;/////////////////////////////////////////////////////////;;
  740. ;;------------------------------------------------------------------------------------------------;;
  741. ;? Determines whether GIF image occupies the whole logical screen                                 ;;
  742. ;;------------------------------------------------------------------------------------------------;;
  743. ;> eax = extended image data                                                                      ;;
  744. ;> ebx = main image                                                                               ;;
  745. ;;------------------------------------------------------------------------------------------------;;
  746. ;< ZF set <=> image area equals logical screen                                                    ;;
  747. ;;================================================================================================;;
  748.         mov     ebx, [ebx + Image.Extended]
  749.         cmp     [eax + gif.Image.info.Left], 0
  750.         jnz     @f
  751.         cmp     [eax + gif.Image.info.Top], 0
  752.         jnz     @f
  753.         mov     cx, [eax + gif.Image.info.Width]
  754.         cmp     cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
  755.         jnz     @f
  756.         mov     cx, [eax + gif.Image.info.Height]
  757.         cmp     cx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
  758. @@:     retn
  759. endp
  760.  
  761. main_img equ img.decode.gif.main_img
  762. transparent_color equ img.decode.gif.transparent_color
  763. background_color equ img.decode.gif.background_color
  764. prev_num_colors equ img.decode.gif.prev_num_colors
  765. prev_palette equ img.decode.gif.prev_palette
  766. max_color equ img.decode.gif.max_color
  767. prev_img_data equ img.decode.gif.prev_img_data
  768. _data equ img.decode.gif._data
  769. aux_img_data equ img.decode.gif.aux_img_data
  770. aux_img_type equ img.decode.gif.aux_img_type
  771. aux_palette equ img.decode.gif.aux_palette
  772.  
  773. ;;================================================================================================;;
  774. proc img.decode.gif._.superimpose ;///////////////////////////////////////////////////////////////;;
  775. ;;------------------------------------------------------------------------------------------------;;
  776. ;? --- TBD ---                                                                                    ;;
  777. ;;------------------------------------------------------------------------------------------------;;
  778. ;> edx = image data                                                                               ;;
  779. ;;------------------------------------------------------------------------------------------------;;
  780. ;< --- TBD ---                                                                                    ;;
  781. ;;================================================================================================;;
  782.         mov     ebx, [main_img]
  783.         mov     eax, [edx + Image.Extended]
  784.         or      [transparent_color], -1         ; no transparent color
  785.         test    byte [eax + gif.Image.gce.Packed], 1
  786.         jz      @f
  787.         movzx   ecx, byte [eax + gif.Image.gce.ColorIndex]
  788.         mov     [transparent_color], ecx
  789.         cmp     edx, ebx
  790.         jnz     .has_transparency
  791.         shl     ecx, 2
  792.         add     ecx, [edx + Image.Palette]
  793.         mov     dword [background_color], 0xFFFFFF      ; white background
  794.         mov     dword [ecx], 0xFFFFFF
  795. ;       mov     esi, [_data]
  796. ;       test    [esi+gif.Header.lsd.Packed], gif.LSD.Packed.GlobalColorTableFlag
  797. ;       jz      @f
  798. ;       movzx   ecx, [esi+gif.Header.lsd.BackgroundColor]
  799. ;       push    ecx
  800. ;       shl     ecx, 2
  801. ;       add     ecx, [edx + Image.Palette]
  802. ;       mov     dword [ecx], 0xFFFFFF
  803. ;       pop     ecx
  804. ;       lea     ecx, [ecx*3]
  805. ;       add     esi, ecx
  806. ;       mov     byte [esi+sizeof.gif.Header+0], 0xFF
  807. ;       mov     byte [esi+sizeof.gif.Header+1], 0xFF
  808. ;       mov     byte [esi+sizeof.gif.Header+2], 0xFF
  809. @@:
  810.         call    img.decode.gif._.is_logical_screen
  811.         jnz     .has_transparency
  812. ; image is not transparent, so keep it as is
  813.         retn
  814.  
  815. .has_transparency:
  816. ; image has transparent areas, we must superimpose it on the previous
  817.         mov     ecx, [prev_num_colors]
  818.         cmp     ecx, 0x100
  819.         ja      .superimpose_on_rgb
  820. ; create common palette
  821.         sub     esp, 3FCh
  822.         push    eax
  823.         mov     edi, esp
  824.         push    ecx
  825.         mov     esi, [prev_palette]
  826.         rep     movsd
  827.         pop     ecx
  828.         mov     esi, [edx + Image.Palette]
  829.         xor     ebx, ebx
  830.         mov     edi, esp
  831.         sub     esp, 100h
  832. .create_palette_loop:
  833.         push    ecx
  834.         lodsd
  835.         cmp     ebx, [transparent_color]
  836.         jz      .nochange
  837.         cmp     ebx, ecx
  838.         jae     @f
  839.         cmp     eax, [edi+ebx*4]
  840.         jz      .nochange
  841. @@:
  842.         push    edi
  843.         repnz   scasd
  844.         pop     edi
  845.         jnz     .increase_palette
  846.         sub     ecx, [esp]
  847.         not     ecx     ; cl = index of new color in current palette
  848.         jmp     .palette_common
  849. .increase_palette:
  850.         mov     ecx, [esp]
  851.         test    ch, ch
  852.         jnz     .output_to_rgb
  853.         inc     dword [esp]
  854.         mov     [edi+ecx*4], eax
  855.         jmp     .palette_common
  856. .nochange:
  857.         mov     ecx, ebx
  858. .palette_common:
  859.         mov     [ebx+esp+4], cl
  860.         pop     ecx
  861.         inc     ebx
  862.         cmp     ebx, [max_color]
  863.         jbe     .create_palette_loop
  864.         mov     [max_color], ecx
  865. ; if image occupies only part of logical screen, allocate memory for full logical screen
  866.         mov     ebx, [main_img]
  867.         mov     eax, [edx + Image.Extended]
  868.         mov     esi, [edx + Image.Data]
  869.         call    img.decode.gif._.is_logical_screen
  870.         jz      @f
  871.         and     [edx + Image.Data], 0
  872.         push    edx
  873.         movzx   eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
  874.         push    eax
  875.         movzx   eax, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
  876.         stdcall img._.resize_data, edx, eax
  877.         pop     edx
  878.         test    eax, eax
  879.         jz      .palette_nomem
  880. @@:
  881. ; copy final palette to Image.Palette
  882.         push    esi esi
  883.         mov     esi, edi
  884.         mov     edi, [edx + Image.Palette]
  885.         mov     ecx, [max_color]
  886.         dec     [max_color]
  887.         rep     movsd
  888.         mov     esi, [prev_img_data]
  889.         mov     edi, [edx + Image.Data]
  890. ; do superimpose, [esp] -> source data, esi -> prev image data
  891. ;   (NULL if previous image is filled with background color), esp+8 -> correspondence between
  892. ;   used palette and final palette, edi -> destination data
  893.         mov     ebx, [edx + Image.Extended]
  894. ; first Top rows are copied from [prev_img_data] or filled with bgr
  895.         movzx   ecx, [ebx + gif.Image.info.Top]
  896.         cmp     ecx, [edx + Image.Height]
  897.         jb      @f
  898.         mov     ecx, [edx + Image.Height]
  899. @@:
  900.         push    ecx
  901.         imul    ecx, [edx + Image.Width]
  902.         call    .rep_movsb_or_stosb
  903.         pop     ecx
  904. ; convert rows
  905.         sub     ecx, [edx + Image.Height]
  906.         neg     ecx
  907.         push    ecx
  908.         cmp     cx, [ebx + gif.Image.info.Height]
  909.         jbe     @f
  910.         mov     cx, [ebx + gif.Image.info.Height]
  911. @@:
  912.         jecxz   .norows
  913. .convert_rows:
  914.         push    ecx
  915.         movzx   ecx, [ebx + gif.Image.info.Left]
  916.         cmp     ecx, [edx + Image.Width]
  917.         jb      @f
  918.         mov     ecx, [edx + Image.Width]
  919. @@:
  920.         push    ecx
  921.         call    .rep_movsb_or_stosb
  922.         pop     ecx
  923.         sub     ecx, [edx + Image.Width]
  924.         neg     ecx
  925.         push    ecx edx
  926.         mov     edx, [esp+16]   ; source data
  927.         cmp     cx, [ebx + gif.Image.info.Width]
  928.         jbe     @f
  929.         mov     cx, [ebx + gif.Image.info.Width]
  930. @@:
  931.         jecxz   .norowsi
  932. .rowsloop:
  933.         movzx   eax, byte [edx]
  934.         inc     edx
  935.         cmp     eax, [transparent_color]
  936.         jz      .rows_transparent
  937.         mov     al, [eax+esp+24]
  938.         stosb
  939.         call    .lodsb
  940.         jmp     @f
  941. .rows_transparent:
  942.         call    .lodsb
  943.         stosb
  944. @@:
  945.         loop    .rowsloop
  946. .norowsi:
  947.         pop     edx ecx
  948.         sub     cx, [ebx + gif.Image.info.Width]
  949.         jbe     @f
  950.         call    .rep_movsb_or_stosb
  951. @@:
  952.         movzx   eax, [ebx + gif.Image.info.Width]
  953.         add     [esp+8], eax
  954.         pop     ecx
  955.         loop    .convert_rows
  956. .norows:
  957.         pop     ecx
  958.         sub     cx, [ebx + gif.Image.info.Height]
  959.         jbe     @f
  960.         imul    ecx, [edx + Image.Width]
  961.         call    .rep_movsb_or_stosb
  962. @@:
  963. ; free old image data if we have allocated new copy
  964.         pop     esi esi
  965.         cmp     esi, [edx + Image.Data]
  966.         jz      @f
  967.         invoke  mem.free, esi
  968. @@:
  969. ; cleanup stack and return
  970.         add     esp, 500h
  971.         retn
  972. .palette_nomem:
  973.         mov     [edx + Image.Data], esi
  974.         jmp     @b
  975.  
  976. .output_to_rgb:
  977.         pop     ecx
  978.         add     esp, 500h
  979. ; compose two palette-based images to one RGB image
  980.         xor     esi, esi
  981.         xchg    esi, [edx + Image.Data]
  982.         push    esi
  983.         mov     ebx, [_data]
  984.         push    [edx + Image.Palette]
  985.         mov     byte [edx + Image.Type], Image.bpp24
  986.         push    edx
  987.         movzx   eax, [ebx + gif.Header.lsd.ScreenHeight]
  988.         push    eax
  989.         movzx   eax, [ebx + gif.Header.lsd.ScreenWidth]
  990.         stdcall img._.resize_data, edx, eax
  991.         pop     edx
  992.         test    eax, eax
  993.         jz      .convrgb_nomem
  994.         push    esi
  995.         mov     edi, [edx + Image.Data]
  996.         mov     esi, [prev_img_data]
  997.         mov     ebx, [edx + Image.Extended]
  998. ; first Top rows are copied from [prev_img_data] or filled with bgr
  999.         movzx   ecx, [ebx + gif.Image.info.Top]
  1000.         cmp     ecx, [edx + Image.Height]
  1001.         jb      @f
  1002.         mov     ecx, [edx + Image.Height]
  1003. @@:
  1004.         push    ecx
  1005.         imul    ecx, [edx + Image.Width]
  1006.         call    .convrgb_prev
  1007.         pop     ecx
  1008. ; convert rows
  1009.         sub     ecx, [edx + Image.Height]
  1010.         neg     ecx
  1011.         push    ecx
  1012.         cmp     cx, [ebx + gif.Image.info.Height]
  1013.         jbe     @f
  1014.         mov     cx, [ebx + gif.Image.info.Height]
  1015. @@:
  1016.         jecxz   .convrgb_norows
  1017. .convrgb_convert_rows:
  1018.         push    ecx
  1019.         movzx   ecx, [ebx + gif.Image.info.Left]
  1020.         cmp     ecx, [edx + Image.Width]
  1021.         jb      @f
  1022.         mov     ecx, [edx + Image.Width]
  1023. @@:
  1024.         push    ecx
  1025.         call    .convrgb_prev
  1026.         pop     ecx
  1027.         sub     ecx, [edx + Image.Width]
  1028.         neg     ecx
  1029.         push    ecx edx
  1030.         mov     edx, [esp+16]   ; source data
  1031.         cmp     cx, [ebx + gif.Image.info.Width]
  1032.         jbe     @f
  1033.         mov     cx, [ebx + gif.Image.info.Width]
  1034. @@:
  1035.         jecxz   .convrgb_norowsi
  1036. .convrgb_rowsloop:
  1037.         movzx   eax, byte [edx]
  1038.         inc     edx
  1039.         cmp     eax, [transparent_color]
  1040.         jz      .convrgb_rows_transparent
  1041.         shl     eax, 2
  1042.         add     eax, [esp+20]   ; source palette
  1043.         mov     eax, [eax]
  1044.         stosw
  1045.         shr     eax, 16
  1046.         stosb
  1047.         call    .convrgb_lodsb
  1048.         jmp     @f
  1049. .convrgb_rows_transparent:
  1050.         call    .convrgb_lodsb
  1051.         stosw
  1052.         shr     eax, 16
  1053.         stosb
  1054. @@:
  1055.         loop    .convrgb_rowsloop
  1056. .convrgb_norowsi:
  1057.         pop     edx ecx
  1058.         sub     cx, [ebx + gif.Image.info.Width]
  1059.         jbe     @f
  1060.         call    .convrgb_prev
  1061. @@:
  1062.         movzx   eax, [ebx + gif.Image.info.Width]
  1063.         add     [esp+8], eax
  1064.         pop     ecx
  1065.         loop    .convrgb_convert_rows
  1066. .convrgb_norows:
  1067.         pop     ecx
  1068.         sub     cx, [ebx + gif.Image.info.Height]
  1069.         jbe     @f
  1070.         imul    ecx, [edx + Image.Width]
  1071.         call    .convrgb_prev
  1072. @@:
  1073. ; free old image data
  1074.         pop     esi esi ;esi
  1075.         invoke  mem.free;, esi
  1076.         retn
  1077. .convrgb_nomem:
  1078.         pop     esi esi
  1079.         retn
  1080.  
  1081. .superimpose_on_rgb:
  1082. ; previous image is RGB, new image has transparent areas
  1083.         xor     esi, esi
  1084.         xchg    esi, [edx + Image.Data]
  1085.         push    esi
  1086.         mov     ebx, [_data]
  1087.         push    [edx + Image.Palette]
  1088.         mov     byte [edx + Image.Type], Image.bpp24
  1089.         push    edx
  1090.         movzx   eax, [ebx + gif.Header.lsd.ScreenHeight]
  1091.         push    eax
  1092.         movzx   eax, [ebx + gif.Header.lsd.ScreenWidth]
  1093.         stdcall img._.resize_data, edx, eax
  1094.         pop     edx
  1095.         test    eax, eax
  1096.         jz      .rgb_nomem
  1097.         push    esi
  1098.         mov     edi, [edx + Image.Data]
  1099.         mov     esi, [prev_img_data]
  1100.         mov     ebx, [edx + Image.Extended]
  1101. ; first Top rows are copied from [prev_img_data] or filled with bgr
  1102.         movzx   ecx, [ebx + gif.Image.info.Top]
  1103.         cmp     ecx, [edx + Image.Height]
  1104.         jb      @f
  1105.         mov     ecx, [edx + Image.Height]
  1106. @@:
  1107.         push    ecx
  1108.         lea     ecx, [ecx*3]
  1109.         imul    ecx, [edx + Image.Width]
  1110.         rep     movsb
  1111.         pop     ecx
  1112. ; convert rows
  1113.         sub     ecx, [edx + Image.Height]
  1114.         neg     ecx
  1115.         push    ecx
  1116.         cmp     cx, [ebx + gif.Image.info.Height]
  1117.         jbe     @f
  1118.         mov     cx, [ebx + gif.Image.info.Height]
  1119. @@:
  1120.         jecxz   .rgb_norows
  1121. .rgb_convert_rows:
  1122.         push    ecx
  1123.         movzx   ecx, [ebx + gif.Image.info.Left]
  1124.         cmp     ecx, [edx + Image.Width]
  1125.         jb      @f
  1126.         mov     ecx, [edx + Image.Width]
  1127. @@:
  1128.         push    ecx
  1129.         lea     ecx, [ecx*3]
  1130.         rep     movsb
  1131.         pop     ecx
  1132.         sub     ecx, [edx + Image.Width]
  1133.         neg     ecx
  1134.         push    ecx edx
  1135.         mov     edx, [esp+16]   ; source data
  1136.         cmp     cx, [ebx + gif.Image.info.Width]
  1137.         jbe     @f
  1138.         mov     cx, [ebx + gif.Image.info.Width]
  1139. @@:
  1140.         jecxz   .rgb_norowsi
  1141. .rgb_rowsloop:
  1142.         movzx   eax, byte [edx]
  1143.         inc     edx
  1144.         cmp     eax, [transparent_color]
  1145.         jz      .rgb_rows_transparent
  1146.         shl     eax, 2
  1147.         add     eax, [esp+20]   ; source palette
  1148.         mov     eax, [eax]
  1149.         stosw
  1150.         shr     eax, 16
  1151.         stosb
  1152.         add     esi, 3
  1153.         jmp     @f
  1154. .rgb_rows_transparent:
  1155.         movsb
  1156.         movsb
  1157.         movsb
  1158. @@:
  1159.         loop    .rgb_rowsloop
  1160. .rgb_norowsi:
  1161.         pop     edx ecx
  1162.         sub     cx, [ebx + gif.Image.info.Width]
  1163.         jbe     @f
  1164.         lea     ecx, [ecx*3]
  1165.         rep     movsb
  1166. @@:
  1167.         movzx   eax, [ebx + gif.Image.info.Width]
  1168.         add     [esp+8], eax
  1169.         pop     ecx
  1170.         loop    .rgb_convert_rows
  1171. .rgb_norows:
  1172.         pop     ecx
  1173.         sub     cx, [ebx + gif.Image.info.Height]
  1174.         jbe     @f
  1175.         imul    ecx, [edx + Image.Width]
  1176.         lea     ecx, [ecx*3]
  1177.         rep     movsb
  1178. @@:
  1179. ; free old image data
  1180.         pop     esi esi ;esi
  1181.         invoke  mem.free;, esi
  1182.         retn
  1183. .rgb_nomem:
  1184.         pop     esi esi
  1185.         retn
  1186.  
  1187. .lodsb:
  1188.         xor     eax, eax
  1189.         test    esi, esi
  1190.         jz      @f
  1191.         lodsb
  1192. @@:     retn
  1193.  
  1194. .rep_movsb_or_stosb:
  1195.         test    esi, esi
  1196.         jz      .rmos1
  1197.         rep     movsb
  1198.         jmp     .rmos2
  1199. .rmos1: xor     eax, eax        ; background index in final palette is 0 in bgr mode
  1200.         rep     stosb
  1201. .rmos2: retn
  1202.  
  1203. .convrgb_prev:
  1204.         jecxz   .convrgb_noprev
  1205.         test    esi, esi
  1206.         jz      .convrgb_prev_bgr
  1207. @@:
  1208.         xor     eax, eax
  1209.         lodsb
  1210.         shl     eax, 2
  1211.         add     eax, [prev_palette]
  1212.         mov     eax, [eax]
  1213.         stosw
  1214.         shr     eax, 16
  1215.         stosb
  1216.         loop    @b
  1217.         retn
  1218. .convrgb_prev_bgr:
  1219. @@:
  1220.         mov     eax, [background_color]
  1221.         stosw
  1222.         shr     eax, 16
  1223.         stosb
  1224.         loop    @b
  1225. .convrgb_noprev:
  1226.         retn
  1227. .convrgb_lodsb:
  1228.         xor     eax, eax
  1229.         test    esi, esi
  1230.         jz      @f
  1231.         lodsb
  1232.         shl     eax, 2
  1233.         add     eax, [prev_palette]
  1234.         mov     eax, [eax]
  1235.         retn
  1236. @@:     mov     eax, [background_color]
  1237.         retn
  1238.  
  1239. endp
  1240.  
  1241. ;;================================================================================================;;
  1242. proc img.decode.gif._.dispose ;///////////////////////////////////////////////////////////////////;;
  1243. ;;------------------------------------------------------------------------------------------------;;
  1244. ;? --- TBD ---                                                                                    ;;
  1245. ;;------------------------------------------------------------------------------------------------;;
  1246. ;> edx = image data                                                                               ;;
  1247. ;;------------------------------------------------------------------------------------------------;;
  1248. ;< --- TBD ---                                                                                    ;;
  1249. ;;================================================================================================;;
  1250.         mov     ebx, [edx + Image.Extended]
  1251.         mov     al, [ebx + gif.Image.gce.Packed]
  1252.         shr     al, 2
  1253.         and     al, 7
  1254.         cmp     al, 2
  1255.         jz      .background
  1256.         cmp     al, 3
  1257.         jz      .previous
  1258. ; don't dispose - set prev_img and related vars to current image
  1259.         mov     eax, [edx + Image.Data]
  1260.         mov     [prev_img_data], eax
  1261.         cmp     [edx + Image.Type], Image.bpp8
  1262.         jnz     @f
  1263.         mov     eax, [max_color]
  1264.         inc     eax
  1265.         mov     [prev_num_colors], eax
  1266.         mov     eax, [edx + Image.Palette]
  1267.         mov     [prev_palette], eax
  1268.         retn
  1269. @@:
  1270.         or      [prev_num_colors], -1
  1271.         and     [prev_palette], 0
  1272. .previous:
  1273.         retn
  1274. .background:
  1275.         cmp     [prev_img_data], 0
  1276.         jz      .bgr_full
  1277.         mov     ebx, [main_img]
  1278.         mov     eax, [edx + Image.Extended]
  1279.         call    img.decode.gif._.is_logical_screen
  1280.         jnz     @f
  1281. .bgr_full:
  1282.         xor     eax, eax
  1283.         mov     [prev_img_data], eax
  1284.         inc     eax
  1285.         mov     [prev_num_colors], eax
  1286.         lea     eax, [background_color]
  1287.         mov     [prev_palette], eax
  1288.         retn
  1289. @@:
  1290.         cmp     [prev_num_colors], 0x100
  1291.         ja      .rgb
  1292.         mov     eax, [background_color]
  1293.         mov     edi, [prev_palette]
  1294.         mov     ecx, [prev_num_colors]
  1295.         repnz   scasd
  1296.         jz      .palette_ok
  1297.         cmp     [prev_num_colors], 0x100
  1298.         jz      .convert_rgb
  1299.         push    1
  1300.         pop     eax
  1301.         stdcall img.decode.gif._.alloc_aux_img
  1302.         test    eax, eax
  1303.         jz      .previous
  1304.         mov     ecx, [prev_num_colors]
  1305.         mov     esi, [prev_palette]
  1306.         call    img.decode.gif._.alloc_aux_palette
  1307.         test    eax, eax
  1308.         jz      .previous
  1309.         mov     [prev_palette], eax
  1310.         mov     eax, [background_color]
  1311.         stosd
  1312.         mov     eax, [prev_num_colors]  ; eax = index of background color
  1313.         inc     [prev_num_colors]
  1314.         jmp     .bpp8_common
  1315. .palette_ok:
  1316.         push    1
  1317.         pop     eax
  1318.         stdcall img.decode.gif._.alloc_aux_img
  1319.         test    eax, eax
  1320.         jz      .previous
  1321.         sub     edi, [prev_palette]
  1322.         shr     edi, 2
  1323.         lea     eax, [edi-1]    ; eax = index of background color
  1324. .bpp8_common:
  1325.         push    eax
  1326.         mov     ebx, [_data]
  1327.         mov     esi, [prev_img_data]
  1328.         mov     edi, [aux_img_data]
  1329.         mov     [prev_img_data], edi
  1330.         cmp     esi, edi
  1331.         jz      @f
  1332.         movzx   ecx, [ebx + gif.Header.lsd.ScreenWidth]
  1333.         movzx   eax, [ebx + gif.Header.lsd.ScreenHeight]
  1334.         imul    ecx, eax
  1335.         push    edi
  1336.         rep     movsb
  1337.         pop     edi
  1338. @@:
  1339.         movzx   esi, [ebx + gif.Header.lsd.ScreenHeight]
  1340.         movzx   eax, [ebx + gif.Header.lsd.ScreenWidth]
  1341.         mov     edx, [edx + Image.Extended]
  1342.         movzx   ecx, [edx + gif.Image.info.Top]
  1343.         sub     esi, ecx
  1344.         jbe     .bpp8_ret
  1345.         imul    ecx, eax
  1346.         add     edi, ecx
  1347.         cmp     si, [edx + gif.Image.info.Height]
  1348.         jb      @f
  1349.         mov     si, [edx + gif.Image.info.Height]
  1350. @@:
  1351.         movzx   ecx, [edx + gif.Image.info.Left]
  1352.         sub     eax, ecx
  1353.         jbe     .bpp8_ret
  1354.         add     edi, ecx
  1355.         cmp     ax, [edx + gif.Image.info.Width]
  1356.         jb      @f
  1357.         mov     ax, [edx + gif.Image.info.Width]
  1358. @@:
  1359.         xchg    eax, ecx
  1360.         movzx   edx, [ebx + gif.Header.lsd.ScreenWidth]
  1361.         sub     edx, ecx
  1362.         pop     eax
  1363. @@:
  1364.         push    ecx
  1365.         rep     stosb
  1366.         pop     ecx
  1367.         add     edi, edx
  1368.         dec     esi
  1369.         jnz     @b
  1370.         push    eax
  1371. .bpp8_ret:
  1372.         pop     eax
  1373.         retn
  1374. .convert_rgb:
  1375.         push    3
  1376.         pop     eax
  1377.         stdcall img.decode.gif._.alloc_aux_img
  1378.         test    eax, eax
  1379.         jz      .previous
  1380.         or      [prev_num_colors], -1
  1381.         mov     ebx, [_data]
  1382.         mov     esi, [prev_img_data]
  1383.         mov     edi, [aux_img_data]
  1384.         mov     [prev_img_data], edi
  1385.         movzx   ecx, [ebx + gif.Header.lsd.ScreenWidth]
  1386.         movzx   eax, [ebx + gif.Header.lsd.ScreenHeight]
  1387.         imul    ecx, eax
  1388.         push    edx
  1389.         xor     edx, edx
  1390.         xchg    edx, [prev_palette]
  1391.         add     edi, ecx
  1392.         add     esi, ecx
  1393.         add     edi, ecx
  1394.         add     edi, ecx
  1395. @@:
  1396.         dec     esi
  1397.         movzx   eax, byte [esi]
  1398.         mov     eax, [eax*4+edx]
  1399.         sub     edi, 3
  1400.         mov     [edi], ax
  1401.         shr     eax, 16
  1402.         mov     [edi+2], al
  1403.         loop    @b
  1404.         pop     edx
  1405.         movzx   esi, [ebx + gif.Header.lsd.ScreenHeight]
  1406.         movzx   eax, [ebx + gif.Header.lsd.ScreenWidth]
  1407.         mov     edx, [edx + Image.Extended]
  1408.         movzx   ecx, [edx + gif.Image.info.Top]
  1409.         sub     esi, ecx
  1410.         jbe     .convert_rgb_ret
  1411.         imul    ecx, eax
  1412.         lea     ecx, [ecx*3]
  1413.         add     edi, ecx
  1414.         cmp     si, [edx + gif.Image.info.Height]
  1415.         jb      @f
  1416.         mov     si, [edx + gif.Image.info.Height]
  1417. @@:
  1418.         movzx   ecx, [edx + gif.Image.info.Left]
  1419.         sub     eax, ecx
  1420.         jbe     .convert_rgb_ret
  1421.         lea     ecx, [ecx*3]
  1422.         add     edi, ecx
  1423.         cmp     ax, [edx + gif.Image.info.Width]
  1424.         jb      @f
  1425.         mov     ax, [edx + gif.Image.info.Width]
  1426. @@:
  1427.         xchg    eax, ecx
  1428.         movzx   edx, [ebx + gif.Header.lsd.ScreenWidth]
  1429.         sub     edx, ecx
  1430.         mov     eax, [background_color]
  1431.         lea     edx, [edx*3]
  1432. .convert_rgb_loop:
  1433.         push    ecx
  1434. @@:
  1435.         stosw
  1436.         shr     eax, 16
  1437.         stosb
  1438.         loop    @b
  1439.         pop     ecx
  1440.         add     edi, edx
  1441.         dec     esi
  1442.         jnz     .convert_rgb_loop
  1443. .convert_rgb_ret:
  1444.         retn
  1445. .rgb:
  1446.         push    3
  1447.         pop     eax
  1448.         stdcall img.decode.gif._.alloc_aux_img
  1449.         test    eax, eax
  1450.         jz      .previous
  1451.         or      [prev_num_colors], -1
  1452.         and     [prev_palette], 0
  1453.         mov     ebx, [_data]
  1454.         mov     esi, [prev_img_data]
  1455.         mov     edi, [aux_img_data]
  1456.         mov     [prev_img_data], edi
  1457.         cmp     esi, edi
  1458.         jz      @f
  1459.         movzx   ecx, [ebx + gif.Header.lsd.ScreenHeight]
  1460.         push    ecx
  1461.         movzx   eax, [ebx + gif.Header.lsd.ScreenWidth]
  1462.         imul    ecx, eax
  1463.         lea     ecx, [ecx*3]
  1464.         push    edi
  1465.         rep     movsb
  1466.         pop     edi
  1467.         pop     esi
  1468.         mov     edx, [edx + Image.Extended]
  1469.         movzx   ecx, [edx + gif.Image.info.Top]
  1470.         sub     esi, ecx
  1471.         jbe     .rgb_ret
  1472.         imul    ecx, eax
  1473.         lea     ecx, [ecx*3]
  1474.         add     edi, ecx
  1475.         cmp     si, [edx + gif.Image.info.Height]
  1476.         jb      @f
  1477.         mov     si, [edx + gif.Image.info.Height]
  1478. @@:
  1479.         movzx   ecx, [edx + gif.Image.info.Left]
  1480.         sub     eax, ecx
  1481.         jbe     .rgb_ret
  1482.         lea     ecx, [ecx*3]
  1483.         add     edi, ecx
  1484.         cmp     ax, [edx + gif.Image.info.Width]
  1485.         jb      @f
  1486.         mov     ax, [edx + gif.Image.info.Width]
  1487. @@:
  1488.         xchg    eax, ecx
  1489.         movzx   edx, [ebx + gif.Header.lsd.ScreenWidth]
  1490.         sub     edx, ecx
  1491.         mov     eax, [background_color]
  1492.         lea     edx, [edx*3]
  1493. .rgb_loop:
  1494.         push    ecx
  1495. @@:
  1496.         stosw
  1497.         shr     eax, 16
  1498.         stosb
  1499.         loop    @b
  1500.         pop     ecx
  1501.         add     edi, edx
  1502.         dec     esi
  1503.         jnz     .rgb_loop
  1504. .rgb_ret:
  1505.         retn
  1506.  
  1507. endp
  1508.  
  1509. ;;================================================================================================;;
  1510. proc img.decode.gif._.alloc_aux_img ;/////////////////////////////////////////////////////////////;;
  1511. ;;------------------------------------------------------------------------------------------------;;
  1512. ;? Allocate auxiliary memory for previous image                                                   ;;
  1513. ;;------------------------------------------------------------------------------------------------;;
  1514. ;> eax = image type: 1 = bpp8, 3 = bpp24                                                          ;;
  1515. ;;------------------------------------------------------------------------------------------------;;
  1516. ;< eax = [aux_img_data]                                                                           ;;
  1517. ;;================================================================================================;;
  1518.         cmp     [aux_img_type], eax
  1519.         jae     @f
  1520.         push    edx eax
  1521.         movzx   ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenWidth]
  1522.         mul     ecx
  1523.         movzx   ecx, [ebx + sizeof.gif.Image + gif.LogicalScreenDescriptor.ScreenHeight]
  1524.         mul     ecx
  1525.         invoke  mem.realloc, [aux_img_data], eax
  1526.         pop     ecx edx
  1527.         test    eax, eax
  1528.         jz      @f
  1529.         mov     [aux_img_type], ecx
  1530.         mov     [aux_img_data], eax
  1531. @@:     retn
  1532.  
  1533. endp
  1534.  
  1535. ;;================================================================================================;;
  1536. proc img.decode.gif._.alloc_aux_palette ;/////////////////////////////////////////////////////////;;
  1537. ;;------------------------------------------------------------------------------------------------;;
  1538. ;? Allocate and fill aux_palette                                                                  ;;
  1539. ;;------------------------------------------------------------------------------------------------;;
  1540. ;> esi -> palette, ecx = palette size                                                             ;;
  1541. ;;------------------------------------------------------------------------------------------------;;
  1542. ;< [aux_palette] set                                                                              ;;
  1543. ;;================================================================================================;;
  1544.         mov     eax, [aux_palette]
  1545.         test    eax, eax
  1546.         jnz     @f
  1547.         push    edx ecx
  1548.         invoke  mem.alloc, 0x400
  1549.         pop     ecx edx
  1550.         test    eax, eax
  1551.         jz      .ret
  1552.         mov     [aux_palette], eax
  1553. @@:
  1554.         mov     edi, eax
  1555.         rep     movsd
  1556. .ret:
  1557.         retn
  1558.  
  1559. endp
  1560.  
  1561. restore main_img
  1562. restore transparent_color
  1563. restore background_color
  1564. restore prev_num_colors
  1565. restore prev_palette
  1566. restore max_color
  1567. restore prev_img_data
  1568. restore _data
  1569. restore aux_img_data
  1570. restore aux_img_type
  1571. restore aux_palette
  1572.  
  1573. ;;================================================================================================;;
  1574. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1575. ;;================================================================================================;;
  1576. ;! Below is private data you should never use directly from your code                             ;;
  1577. ;;================================================================================================;;
  1578. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1579. ;;================================================================================================;;
  1580.  
  1581.  
  1582. ;
  1583.