Subversion Repositories Kolibri OS

Rev

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

  1. ;;================================================================================================;;
  2. ;;//// png.asm //// (c) diamond, 2009 ////////////////////////////////////////////////////////////;;
  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. ;;proc img.is.png _data, _length ;////////////////////////////////////////////////////////////////;;
  22. img.is.png:
  23. ;;------------------------------------------------------------------------------------------------;;
  24. ;? Determine if raw data could be decoded (is in PNG format)                                      ;;
  25. ;;------------------------------------------------------------------------------------------------;;
  26. ;> _data = raw data as read from file/stream                                                      ;;
  27. ;> _length = data length                                                                          ;;
  28. ;;------------------------------------------------------------------------------------------------;;
  29. ;< eax = false / true                                                                             ;;
  30. ;;================================================================================================;;
  31. ; test 1 (length of data)
  32.         cmp     dword [esp+8], 8
  33.         jb      .nope
  34. ; test 2: signature
  35.         mov     eax, [esp+4]
  36.         cmp     dword [eax], 0x474E5089
  37.         jne     .nope
  38.         cmp     dword [eax+4], 0x0A1A0A0D
  39.         je      .yep
  40.  
  41.   .nope:
  42.         xor     eax, eax
  43.         ret     8
  44.  
  45.   .yep:
  46.         xor     eax, eax
  47.         inc     eax
  48.         ret     8
  49. ;endp
  50.  
  51. ;;================================================================================================;;
  52. ;;proc img.decode.png _data, _length, _options ;//////////////////////////////////////////////////;;
  53. img.decode.png:
  54.         xor     eax, eax        ; .image = 0
  55.         pushad
  56.         mov     ebp, esp
  57. .localsize = 15*4
  58. virtual at ebp - .localsize
  59. .width          dd      ?
  60. .height         dd      ?
  61. .bit_depth      dd      ?
  62. .color_type     dd      ?
  63. .bytes_per_pixel dd     ?
  64. .scanline_len   dd      ?
  65. .cur_chunk_ptr  dd      ?
  66. .cur_chunk_size dd      ?
  67. .paeth_a        dd      ?
  68. .paeth_b        dd      ?
  69. .paeth_c        dd      ?
  70. .paeth_pa       dd      ?
  71. .paeth_pb       dd      ?
  72. .paeth_pc       dd      ?
  73. .idat_read      dd      ?
  74.         rb      1Ch
  75. .image          dd      ?
  76.         rd      1
  77. .data           dd      ?
  78. .length         dd      ?
  79. .options        dd      ?
  80. end virtual
  81.         push    0       ; .idat_read = 0
  82.         sub     esp, .localsize-4
  83. ; load deflate unpacker, if not yet
  84. ; acquire mutex
  85. @@:
  86.         push    1
  87.         pop     eax
  88.         xchg    [deflate_loader_mutex], eax     ; 'xchg' has an implicit 'lock' prefix
  89.         test    eax, eax
  90.         jz      @f
  91.         mcall   5, 1
  92.         jmp     @b
  93. @@:
  94.         cmp     [deflate_unpack2], __deflate_unpack2_import_name__
  95.         jnz     .deflate_loaded
  96. ; do loading
  97.         invoke  dll.load, @IMPORT
  98.         test    eax, eax
  99.         jz      .deflate_loaded
  100.         add     esp, .localsize
  101.         popad
  102.         mov     [deflate_loader_mutex], eax
  103.         ret     12
  104. .deflate_loaded:
  105. ; release mutex
  106.         mov     [deflate_loader_mutex], 0
  107. ; ok, continue
  108.         mov     esi, [.data]            ; esi -> data
  109.         mov     ecx, [.length]          ; ecx = length
  110. ; the signature has been already checked in img.is.png
  111.         lodsd
  112.         lodsd
  113.         sub     ecx, 8
  114.         xor     ebx, ebx        ; no image allocated
  115. .chunks_loop:
  116.         sub     ecx, 12
  117.         jc      .eof
  118.         lodsd   ; chunk length
  119.         bswap   eax
  120.         sub     ecx, eax
  121.         jc      .eof
  122.         push    ecx     ; save length of data rest
  123.         xchg    eax, ecx        ; ecx = size of data in the chunk
  124.         lodsd   ; chunk type
  125.         cmp     eax, 'IHDR'
  126.         jz      .ihdr
  127.         cmp     eax, 'IDAT'
  128.         jz      .idat
  129.         cmp     eax, 'IEND'
  130.         jz      .iend
  131.         cmp     eax, 'PLTE'
  132.         jz      .palette
  133. ; unrecognized chunk, ignore
  134.         lea     esi, [esi+ecx+4]
  135.         pop     ecx
  136.         jmp     .chunks_loop
  137. ; IHDR chunk
  138. .ihdr:
  139.         cmp     ecx, 13
  140.         jnz     .invalid_chunk
  141.         cmp     [.image], 0
  142.         jnz     .invalid_chunk
  143. ; read image characteristics
  144.         lodsd
  145.         bswap   eax
  146.         mov     [.width], eax
  147.         lodsd
  148.         bswap   eax
  149.         mov     [.height], eax
  150.         xor     eax, eax
  151.         lea     ebx, [eax+1]
  152.         lodsb
  153.         cmp     al, 16
  154.         ja      .invalid_chunk
  155.         test    al, al
  156.         jz      .invalid_chunk
  157.         lea     edx, [eax-1]
  158.         test    al, dl
  159.         jnz     .invalid_chunk
  160.         mov     [.bit_depth], eax
  161.         lodsb
  162.         test    al, not 7
  163.         jnz     .invalid_chunk
  164.         mov     [.color_type], eax
  165.         lodsb
  166.         test    al, al
  167.         jnz     .invalid_chunk  ; only compression method 0 is defined
  168.         lodsb
  169.         test    al, al
  170.         jnz     .invalid_chunk  ; only filtering method 0 is defined
  171.         lodsb
  172.         test    al, al
  173.         jnz     .invalid_chunk  ; progressive PNGs are not supported yet
  174. ; check for correctness and calculate bytes_per_pixel and scanline_len
  175.         mov     eax, [.bit_depth]
  176.         mov     edx, [.color_type]
  177.         dec     edx
  178.         js      .grayscale1
  179.         dec     edx
  180.         jz      .rgb1
  181.         dec     edx
  182.         jz      .palette1
  183.         dec     edx
  184.         jz      .grayscale_alpha1
  185.         dec     edx
  186.         dec     edx
  187.         jnz     .invalid_chunk
  188. .rgb_alpha1:
  189.         inc     ebx
  190. .rgb1:
  191.         inc     ebx
  192. .grayscale_alpha1:
  193.         inc     ebx
  194.         cmp     al, 8
  195.         jb      .invalid_chunk
  196.         jmp     @f
  197. .palette1:
  198.         cmp     al, 8
  199.         ja      .invalid_chunk
  200. .grayscale1:
  201. @@:
  202.         mul     ebx
  203.         push    eax
  204.         add     eax, 7
  205.         shr     eax, 3
  206.         mov     [.bytes_per_pixel], eax
  207.         pop     eax
  208.         mul     [.width]
  209.         add     eax, 7
  210.         shr     eax, 3
  211.         mov     [.scanline_len], eax
  212. ; allocate image
  213.         push    Image.bpp24
  214.         pop     eax
  215.         cmp     [.color_type], 2
  216.         jz      @f
  217.         mov     al, Image.bpp32
  218.         cmp     [.color_type], 6
  219.         jz      @f
  220.         mov     al, Image.bpp8
  221. @@:
  222.         stdcall img.create, [.width], [.height], eax
  223.         test    eax, eax
  224.         jz      .invalid_chunk
  225.         mov     [.image], eax
  226.         jmp     .next_chunk
  227. .invalid_chunk:
  228. .iend:
  229.         pop     ecx
  230. .eof:
  231.         add     esp, .localsize
  232.         popad
  233.         ret     12
  234. ; PLTE chunk
  235. .palette:
  236.         mov     eax, [.image]
  237.         test    eax, eax
  238.         jz      .invalid_chunk
  239.         cmp     [.color_type], 3
  240.         jz      .copy_palette
  241. .ignore_chunk:
  242.         add     esi, ecx
  243. .next_chunk:
  244.         lodsd
  245.         pop     ecx
  246.         jmp     .chunks_loop
  247. .copy_palette:
  248.         mov     edi, [eax + Image.Palette]
  249.         xor     eax, eax
  250.         cmp     ecx, 256*3
  251.         ja      .next_chunk
  252. @@:
  253.         sub     ecx, 3
  254.         jz      @f
  255.         js      .invalid_chunk
  256.         lodsd
  257.         dec     esi
  258.         bswap   eax
  259.         shr     eax, 8
  260.         stosd
  261.         jmp     @b
  262. @@:
  263.         lodsd
  264.         dec     esi
  265.         bswap   eax
  266.         shr     eax, 8
  267.         stosd
  268.         jmp     .next_chunk
  269. .idat:
  270.         jecxz   .next_chunk
  271.         cmp     [.idat_read], 0
  272.         jnz     @f
  273.         lodsb
  274.         inc     [.idat_read]
  275.         and     al, 0xF
  276.         cmp     al, 8
  277.         jnz     .invalid_chunk
  278.         dec     ecx
  279.         jz      .next_chunk
  280. @@:
  281.         cmp     [.idat_read], 1
  282.         jnz     @f
  283.         lodsb
  284.         inc     [.idat_read]
  285.         test    al, 20h
  286.         jnz     .invalid_chunk
  287.         dec     ecx
  288.         jz      .next_chunk
  289. @@:
  290.         mov     [.cur_chunk_ptr], esi
  291.         mov     [.cur_chunk_size], ecx
  292.         pop     [.length]
  293.         push    eax
  294.         push    esp
  295.         push    ebp
  296.         push    .deflate_callback
  297.         call    [deflate_unpack2]
  298.         pop     ecx
  299.         test    eax, eax
  300.         jz      .invalid_chunk
  301. ; convert PNG unpacked data to RAW data
  302.         mov     esi, eax
  303.         push    eax ecx
  304. ; unfilter
  305.         mov     edx, [.height]
  306. .unfilter_loop_e:
  307.         mov     ebx, [.scanline_len]
  308.         sub     ecx, 1
  309.         jc      .unfilter_done
  310.         sub     ecx, ebx
  311.         jc      .unfilter_done
  312.         movzx   eax, byte [esi]
  313.         add     esi, 1
  314.         cmp     eax, 4
  315.         ja      .next_scanline
  316.         jmp     dword [@f + eax*4]
  317. align 4
  318. @@:
  319.         dd      .unfilter_none
  320.         dd      .unfilter_sub
  321.         dd      .unfilter_up
  322.         dd      .unfilter_average
  323.         dd      .unfilter_paeth
  324. .unfilter_sub:
  325.         mov     edi, [.bytes_per_pixel]
  326.         add     esi, edi
  327.         sub     ebx, edi
  328.         jbe     .next_scanline
  329.         neg     edi
  330. @@:
  331.         mov     al, [esi+edi]
  332.         add     [esi], al
  333.         add     esi, 1
  334.         sub     ebx, 1
  335.         jnz     @b
  336.         jmp     .next_scanline
  337. .unfilter_up:
  338.         cmp     edx, [.height]
  339.         jz      .unfilter_none
  340.         lea     edi, [ebx+1]
  341.         neg     edi
  342. @@:
  343.         mov     al, [esi+edi]
  344.         add     [esi], al
  345.         add     esi, 1
  346.         sub     ebx, 1
  347.         jnz     @b
  348.         jmp     .next_scanline
  349. .unfilter_average:
  350.         mov     edi, [.bytes_per_pixel]
  351.         cmp     edx, [.height]
  352.         jz      .unfilter_average_firstline
  353.         push    edx
  354.         lea     edx, [ebx+1]
  355.         neg     edx
  356.         sub     ebx, edi
  357. @@:
  358.         mov     al, [esi+edx]
  359.         shr     al, 1
  360.         add     [esi], al
  361.         add     esi, 1
  362.         sub     edi, 1
  363.         jnz     @b
  364.         mov     edi, [.bytes_per_pixel]
  365.         neg     edi
  366.         test    ebx, ebx
  367.         jz      .unfilter_average_done
  368. @@:
  369.         mov     al, [esi+edx]
  370.         add     al, [esi+edi]
  371.         rcr     al, 1
  372.         add     [esi], al
  373.         add     esi, 1
  374.         sub     ebx, 1
  375.         jnz     @b
  376. .unfilter_average_done:
  377.         pop     edx
  378.         jmp     .next_scanline
  379. .unfilter_average_firstline:
  380.         mov     edi, [.bytes_per_pixel]
  381.         add     esi, edi
  382.         sub     ebx, edi
  383.         jbe     .next_scanline
  384.         neg     edi
  385. @@:
  386.         mov     al, [esi+edi]
  387.         shr     al, 1
  388.         add     [esi], al
  389.         add     esi, 1
  390.         sub     ebx, 1
  391.         jnz     @b
  392.         jmp     .unfilter_none
  393. .unfilter_paeth:
  394.         cmp     edx, [.height]
  395.         jz      .unfilter_sub
  396.         push    edx
  397.         lea     edx, [ebx+1]
  398.         mov     edi, [.bytes_per_pixel]
  399.         neg     edx
  400.         sub     ebx, edi
  401. @@:
  402.         mov     al, [esi+edx]
  403.         add     [esi], al
  404.         add     esi, 1
  405.         sub     edi, 1
  406.         jnz     @b
  407.         mov     edi, [.bytes_per_pixel]
  408.         neg     edi
  409.         test    ebx, ebx
  410.         jz      .unfilter_paeth_done
  411.         push    ecx
  412. @@:
  413.         push    ebx
  414. ; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
  415.         movzx   eax, byte [esi+edi]
  416.         mov     [.paeth_a], eax
  417.         movzx   ecx, byte [esi+edx]
  418.         add     edi, edx
  419.         mov     [.paeth_b], ecx
  420.         add     ecx, eax
  421.         movzx   eax, byte [esi+edi]
  422.         mov     [.paeth_c], eax
  423.         sub     ecx, eax        ; ecx = a + b - c = p
  424. ; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
  425.         mov     ebx, ecx
  426.         sub     ebx, eax        ; ebx = p - c
  427.         cmp     ebx, 80000000h
  428.         sbb     eax, eax        ; eax = (p < c) ? 0 : 0xFFFFFFF
  429.         not     eax             ; eax = (p < c) ? 0xFFFFFFFF : 0
  430.         and     eax, ebx        ; eax = (p < c) ? p - c : 0
  431.         sub     ebx, eax
  432.         sub     ebx, eax        ; ebx = abs(p-c)
  433.         mov     [.paeth_pc], ebx
  434.         mov     ebx, ecx
  435.         sub     ebx, [.paeth_a]
  436.         cmp     ebx, 80000000h
  437.         sbb     eax, eax
  438.         not     eax
  439.         and     eax, ebx
  440.         sub     ebx, eax
  441.         sub     ebx, eax
  442.         mov     [.paeth_pa], ebx
  443.         mov     ebx, ecx
  444.         sub     ebx, [.paeth_b]
  445.         cmp     ebx, 80000000h
  446.         sbb     eax, eax
  447.         not     eax
  448.         and     eax, ebx
  449.         sub     ebx, eax
  450.         sub     ebx, eax
  451.         ;mov    [.paeth_pb], ebx
  452. ; select closest value
  453.         push    edx
  454.         mov     edx, [.paeth_b]
  455.         sub     edx, [.paeth_a]
  456.         sub     ebx, [.paeth_pa]
  457.         sbb     ecx, ecx        ; ecx = (pa > pb) ? 0xFFFFFFFF : 0
  458.         sbb     eax, eax        ; eax = (pa > pb) ? 0xFFFFFFFF : 0
  459.         and     ecx, ebx        ; ecx = (pa > pb) ? pb - pa : 0
  460.         and     eax, edx        ; eax = (pa > pb) ? b - a : 0
  461.         add     ecx, [.paeth_pa]        ; ecx = (pa > pb) ? pb : pa = min(pa,pb)
  462.         add     eax, [.paeth_a]         ; eax = (pa > pb) ? b : a
  463.         mov     edx, [.paeth_c]
  464.         sub     edx, eax
  465.         sub     [.paeth_pc], ecx
  466.         sbb     ebx, ebx        ; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
  467.         and     ebx, edx        ; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
  468.         add     eax, ebx
  469.         pop     edx
  470.         add     [esi], al
  471.         pop     ebx
  472.         sub     edi, edx
  473.         add     esi, 1
  474.         sub     ebx, 1
  475.         jnz     @b
  476.         pop     ecx
  477. .unfilter_paeth_done:
  478.         pop     edx
  479.         jmp     .next_scanline
  480. .unfilter_none:
  481.         add     esi, ebx
  482. .next_scanline:
  483.         sub     edx, 1
  484.         jnz     .unfilter_loop_e
  485. .unfilter_done:
  486. ; unfiltering done, now convert to raw data
  487.         pop     ebx esi
  488.         push    esi
  489.         mov     edx, [.height]
  490.         mov     eax, [.image]
  491.         mov     edi, [eax + Image.Data]
  492.         cmp     [.color_type], 0
  493.         jz      .grayscale2
  494.         cmp     [.color_type], 2
  495.         jz      .rgb2
  496.         cmp     [.color_type], 3
  497.         jz      .palette2
  498.         cmp     [.color_type], 4
  499.         jz      .grayscale_alpha2
  500. .rgb_alpha2:
  501.         cmp     [.bit_depth], 16
  502.         jz      .rgb_alpha2_16bit
  503. .rgb_alpha2.next:
  504.         mov     ecx, [.scanline_len]
  505.         sub     ebx, 1
  506.         jc      .convert_done
  507.         add     esi, 1
  508.         sub     ebx, ecx
  509.         jc      .convert_done
  510. @@:
  511.         mov     al, [esi+2]
  512.         mov     [edi], al
  513.         mov     al, [esi+1]
  514.         mov     [edi+1], al
  515.         mov     al, [esi]
  516.         mov     [edi+2], al
  517.         mov     al, [esi+3]
  518.         mov     [edi+3], al
  519.         add     esi, 4
  520.         add     edi, 4
  521.         sub     ecx, 4
  522.         jnz     @b
  523.         sub     edx, 1
  524.         jnz     .rgb_alpha2.next
  525.         jmp     .convert_done
  526. .rgb_alpha2_16bit:
  527.         mov     ecx, [.scanline_len]
  528.         sub     ebx, 1
  529.         jc      .convert_done
  530.         add     esi, 1
  531.         sub     ebx, ecx
  532.         jc      .convert_done
  533. .rgb_alpha2.loop:
  534.  
  535. ; convert 16 bit sample to 8 bit sample
  536. macro convert_16_to_8
  537. {
  538. local .l1,.l2
  539.         xor     ah, 0x80
  540.         js      .l1
  541.         cmp     al, ah
  542.         adc     al, 0
  543.         jmp     .l2
  544. .l1:
  545.         cmp     ah, al
  546.         sbb     al, 0
  547. .l2:
  548. }
  549.  
  550.         mov     ax, [esi+4]
  551.         convert_16_to_8
  552.         mov     [edi], al
  553.         mov     ax, [esi+2]
  554.         convert_16_to_8
  555.         mov     [edi+1], al
  556.         mov     ax, [esi]
  557.         convert_16_to_8
  558.         mov     [edi+2], al
  559.         ;mov    ax, [esi+6]
  560.         ;convert_16_to_8
  561.         ;mov    [edi+3], al
  562.         add     esi, 8
  563.         add     edi, 4
  564.         sub     ecx, 8
  565.         jnz     .rgb_alpha2.loop
  566.         sub     edx, 1
  567.         jnz     .rgb_alpha2_16bit
  568.         jmp     .convert_done
  569. .grayscale2:
  570.         push    edi edx
  571.         mov     edi, [eax + Image.Palette]
  572.         mov     ecx, [.bit_depth]
  573.         cmp     cl, 16
  574.         jnz     @f
  575.         mov     cl, 8
  576. @@:
  577.         push    1
  578.         pop     eax
  579.         shl     eax, cl
  580.         xchg    eax, ecx
  581.         mov     edx, 0x010101
  582.         cmp     al, 8
  583.         jz      .graypal_common
  584.         mov     edx, 0x111111
  585.         cmp     al, 4
  586.         jz      .graypal_common
  587.         mov     edx, 0x555555
  588.         cmp     al, 2
  589.         jz      .graypal_common
  590.         mov     edx, 0xFFFFFF
  591. .graypal_common:
  592.         xor     eax, eax
  593. @@:
  594.         stosd
  595.         add     eax, edx
  596.         loop    @b
  597.         pop     edx edi
  598.         cmp     [.bit_depth], 16
  599.         jz      .grayscale2_16bit
  600. .palette2:
  601.         cmp     [.bit_depth], 1
  602.         jz      .palette2_1bit
  603.         cmp     [.bit_depth], 2
  604.         jz      .palette2_2bit
  605.         cmp     [.bit_depth], 4
  606.         jz      .palette2_4bit
  607. .palette2_8bit:
  608.         mov     ecx, [.scanline_len]
  609.         sub     ebx, 1
  610.         jc      .convert_done
  611.         add     esi, 1
  612.         sub     ebx, ecx
  613.         jc      .convert_done
  614.         push    ecx
  615.         shr     ecx, 2
  616.         rep     movsd
  617.         pop     ecx
  618.         and     ecx, 3
  619.         rep     movsb
  620.         sub     edx, 1
  621.         jnz     .palette2_8bit
  622.         jmp     .convert_done
  623. .palette2_4bit:
  624.         sub     ebx, 1
  625.         jc      .convert_done
  626.         add     esi, 1
  627.         sub     ebx, [.scanline_len]
  628.         jc      .convert_done
  629.         push    edx
  630.         mov     ecx, [.width]
  631. @@:
  632.         mov     al, [esi]
  633.         add     esi, 1
  634.         mov     dl, al
  635.         shr     al, 4
  636.         and     dl, 0xF
  637.         mov     [edi], al
  638.         sub     ecx, 1
  639.         jz      @f
  640.         mov     [edi+1], dl
  641.         add     edi, 2
  642.         sub     ecx, 1
  643.         jnz     @b
  644.         sub     edi, 1
  645. @@:
  646.         pop     edx
  647.         add     edi, 1
  648.         sub     edx, 1
  649.         jnz     .palette2_4bit
  650.         jmp     .convert_done
  651. .palette2_2bit:
  652.         sub     ebx, 1
  653.         jc      .convert_done
  654.         add     esi, 1
  655.         sub     ebx, [.scanline_len]
  656.         jc      .convert_done
  657.         push    edx
  658.         mov     ecx, [.width]
  659. @@:
  660.         mov     al, [esi]
  661.         add     esi, 1
  662.         mov     dl, al
  663.         shr     al, 6
  664.         and     dl, not 11000000b
  665.         mov     [edi], al
  666.         add     edi, 1
  667.         sub     ecx, 1
  668.         jz      @f
  669.         mov     al, dl
  670.         shr     dl, 4
  671.         and     al, not 00110000b
  672.         mov     [edi], dl
  673.         add     edi, 1
  674.         sub     ecx, 1
  675.         jz      @f
  676.         mov     dl, al
  677.         shr     al, 2
  678.         and     dl, not 00001100b
  679.         mov     [edi], al
  680.         add     edi, 1
  681.         sub     ecx, 1
  682.         jz      @f
  683.         mov     [edi], dl
  684.         add     edi, 1
  685.         sub     ecx, 1
  686.         jnz     @b
  687. @@:
  688.         pop     edx
  689.         sub     edx, 1
  690.         jnz     .palette2_2bit
  691.         jmp     .convert_done
  692. .palette2_1bit:
  693.         sub     ebx, 1
  694.         jc      .convert_done
  695.         add     esi, 1
  696.         sub     ebx, [.scanline_len]
  697.         jc      .convert_done
  698.         push    edx
  699.         mov     ecx, [.width]
  700. @@:
  701.         mov     al, [esi]
  702.         add     esi, 1
  703. repeat 3
  704.         mov     dl, al
  705.         shr     al, 9-%*2
  706.         and     dl, not (1 shl (9-%*2))
  707.         mov     [edi], al
  708.         add     edi, 1
  709.         sub     ecx, 1
  710.         jz      @f
  711.         mov     al, dl
  712.         shr     dl, 8-%*2
  713.         and     al, not (1 shl (8-%*2))
  714.         mov     [edi], dl
  715.         add     edi, 1
  716.         sub     ecx, 1
  717.         jz      @f
  718. end repeat
  719.         mov     dl, al
  720.         shr     al, 1
  721.         and     dl, not (1 shl 1)
  722.         mov     [edi], al
  723.         add     edi, 1
  724.         sub     ecx, 1
  725.         jz      @f
  726.         mov     [edi], dl
  727.         add     edi, 1
  728.         sub     ecx, 1
  729.         jnz     @b
  730. @@:
  731.         pop     edx
  732.         sub     edx, 1
  733.         jnz     .palette2_1bit
  734.         jmp     .convert_done
  735. .grayscale2_16bit:
  736.         mov     ecx, [.scanline_len]
  737.         sub     ebx, 1
  738.         jc      .convert_done
  739.         add     esi, 1
  740.         sub     ebx, ecx
  741.         jc      .convert_done
  742. @@:
  743.         mov     ax, [esi]
  744.         add     esi, 2
  745.         convert_16_to_8
  746.         mov     [edi], al
  747.         add     edi, 1
  748.         sub     ecx, 2
  749.         jnz     @b
  750.         sub     edx, 1
  751.         jnz     .grayscale2_16bit
  752.         jmp     .convert_done
  753. .rgb2:
  754.         cmp     [.bit_depth], 16
  755.         jz      .rgb2_16bit
  756. .rgb2.next:
  757.         mov     ecx, [.scanline_len]
  758.         sub     ebx, 1
  759.         jc      .convert_done
  760.         add     esi, 1
  761.         sub     ebx, ecx
  762.         jc      .convert_done
  763. @@:
  764.         mov     al, [esi+2]
  765.         mov     [edi], al
  766.         mov     al, [esi+1]
  767.         mov     [edi+1], al
  768.         mov     al, [esi]
  769.         mov     [edi+2], al
  770.         add     esi, 3
  771.         add     edi, 3
  772.         sub     ecx, 3
  773.         jnz     @b
  774.         sub     edx, 1
  775.         jnz     .rgb2.next
  776.         jmp     .convert_done
  777. .rgb2_16bit:
  778.         mov     ecx, [.scanline_len]
  779.         sub     ebx, 1
  780.         jc      .convert_done
  781.         add     esi, 1
  782.         sub     ebx, ecx
  783.         jc      .convert_done
  784. .rgb2.loop:
  785.         mov     ax, [esi+4]
  786.         convert_16_to_8
  787.         mov     [edi], al
  788.         mov     ax, [esi+2]
  789.         convert_16_to_8
  790.         mov     [edi+1], al
  791.         mov     ax, [esi]
  792.         convert_16_to_8
  793.         mov     [edi+2], al
  794.         add     esi, 6
  795.         add     edi, 3
  796.         sub     ecx, 6
  797.         jnz     .rgb2.loop
  798.         sub     edx, 1
  799.         jnz     .rgb2_16bit
  800.         jmp     .convert_done
  801. .grayscale_alpha2:
  802.         cmp     [.bit_depth], 16
  803.         jz      .grayscale_alpha2_16bit
  804. .grayscale_alpha2.next:
  805.         mov     ecx, [.scanline_len]
  806.         sub     ebx, 1
  807.         jc      .convert_done
  808.         add     esi, 1
  809.         sub     ebx, ecx
  810.         jc      .convert_done
  811. @@:
  812.         mov     al, [esi]
  813.         mov     [edi], al
  814.         add     esi, 2
  815.         add     edi, 1
  816.         sub     ecx, 2
  817.         jnz     @b
  818.         sub     edx, 1
  819.         jnz     .grayscale_alpha2.next
  820.         jmp     .convert_done
  821. .grayscale_alpha2_16bit:
  822.         mov     ecx, [.scanline_len]
  823.         sub     ebx, 1
  824.         jc      .convert_done
  825.         add     esi, 1
  826.         sub     ebx, ecx
  827.         jc      .convert_done
  828. @@:
  829.         mov     ax, [esi]
  830.         add     esi, 4
  831.         convert_16_to_8
  832.         mov     [edi], al
  833.         add     edi, 1
  834.         sub     ecx, 4
  835.         jnz     @b
  836.         sub     edx, 1
  837.         jnz     .grayscale_alpha2_16bit
  838. .convert_done:
  839.         pop     ecx
  840.         mcall   68, 13
  841.         mov     esi, [.cur_chunk_ptr]
  842.         add     esi, [.cur_chunk_size]
  843.         push    [.length]
  844.         jmp     .next_chunk
  845.  
  846. .deflate_callback:
  847.         mov     ebp, [esp+4]
  848.         mov     ebx, [esp+8]
  849.         xor     eax, eax
  850.         mov     esi, [.cur_chunk_size]
  851.         mov     [ebx], esi
  852.         test    esi, esi
  853.         jz      .deflate_callback.ret
  854.         mov     eax, [.cur_chunk_ptr]
  855.         mov     ecx, [.length]
  856.         add     esi, eax
  857.         mov     [.cur_chunk_ptr], esi
  858.         and     [.cur_chunk_size], 0
  859. @@:
  860.         sub     ecx, 12
  861.         jb      .deflate_callback.ret
  862.         cmp     dword [esi+4+4], 'IDAT'
  863.         jnz     .deflate_callback.ret
  864.         mov     edx, [esi+4]
  865.         bswap   edx
  866.         sub     ecx, edx
  867.         jb      .deflate_callback.ret
  868.         add     esi, 4+8
  869.         test    edx, edx
  870.         jz      @b
  871.         mov     [.cur_chunk_size], edx
  872.         mov     [.cur_chunk_ptr], esi
  873.         mov     [.length], ecx
  874. .deflate_callback.ret:
  875.         ret     8
  876. ;endp
  877.  
  878. img.encode.png:
  879.         xor     eax, eax
  880.         ret     12
  881.