Subversion Repositories Kolibri OS

Rev

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