Subversion Repositories Kolibri OS

Rev

Rev 1102 | Rev 2733 | 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 = 29*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. .bits_per_pixel dd      ?
  66. .size_rest      dd      ?
  67. .cur_chunk_ptr  dd      ?
  68. .cur_chunk_size dd      ?
  69. .allocated      dd      ?
  70. .paeth_a        dd      ?
  71. .paeth_b        dd      ?
  72. .paeth_c        dd      ?
  73. .paeth_pa       dd      ?
  74. .paeth_pb       dd      ?
  75. .paeth_pc       dd      ?
  76. .i              dd      ?
  77. .j              dd      ?
  78. ; variables to handle interlace
  79. .row_distance   dd      ?       ; diff between two consecutives rows in destination
  80. .col_distance   dd      ?       ; summand for moving to next row in source
  81. .row_increment  dd      ?
  82. .col_increment  dd      ?
  83. .block_height   dd      ?
  84. .block_width    dd      ?
  85. .interlace      db      ?       ; 0 if not interlaced, 1 if interlaced
  86. .row_increment_shift db ?
  87. .col_increment_shift db ?
  88. .shift          db      ?       ; shift for current src byte
  89. .starting_row   dd      ?
  90. .starting_col   dd      ?
  91. .idat_read      dd      ?
  92.         rb      1Ch
  93. .image          dd      ?
  94.         rd      1
  95. .data           dd      ?
  96. .length         dd      ?
  97. .options        dd      ?
  98. end virtual
  99.         push    eax     ; .idat_read = 0
  100.         push    eax     ; .starting_col = 0
  101.         push    eax     ; .starting_row = 0
  102.         push    eax     ; .col_increment_shift, .row_increment_shift
  103.         inc     eax
  104.         push    eax     ; .block_width
  105.         push    eax     ; .block_height
  106.         push    eax     ; .col_increment
  107.         push    eax     ; .row_increment
  108.         sub     esp, .localsize-32
  109. ; load deflate unpacker, if not yet
  110. ; acquire mutex
  111. @@:
  112.         push    1
  113.         pop     eax
  114.         xchg    [deflate_loader_mutex], eax     ; 'xchg' has an implicit 'lock' prefix
  115.         test    eax, eax
  116.         jz      @f
  117.         mcall   5, 1
  118.         jmp     @b
  119. @@:
  120.         cmp     [deflate_unpack2], __deflate_unpack2_import_name__
  121.         jnz     .deflate_loaded
  122. ; do loading
  123.         invoke  dll.load, @IMPORT
  124.         test    eax, eax
  125.         jz      .deflate_loaded
  126.         add     esp, .localsize
  127.         popad
  128.         mov     [deflate_loader_mutex], eax
  129.         ret     12
  130. .deflate_loaded:
  131. ; release mutex
  132.         mov     [deflate_loader_mutex], 0
  133. ; ok, continue
  134.         mov     esi, [.data]            ; esi -> data
  135.         mov     ecx, [.length]          ; ecx = length
  136. ; the signature has been already checked in img.is.png
  137.         lodsd
  138.         lodsd
  139.         sub     ecx, 8
  140.         xor     ebx, ebx        ; no image allocated
  141. .chunks_loop:
  142.         sub     ecx, 12
  143.         jc      .eof
  144.         lodsd   ; chunk length
  145.         bswap   eax
  146.         sub     ecx, eax
  147.         jc      .eof
  148.         push    ecx     ; save length of data rest
  149.         xchg    eax, ecx        ; ecx = size of data in the chunk
  150.         lodsd   ; chunk type
  151.         cmp     eax, 'IHDR'
  152.         jz      .ihdr
  153.         cmp     eax, 'IDAT'
  154.         jz      .idat
  155.         cmp     eax, 'IEND'
  156.         jz      .iend
  157.         cmp     eax, 'PLTE'
  158.         jz      .palette
  159. ; unrecognized chunk, ignore
  160.         lea     esi, [esi+ecx+4]
  161.         pop     ecx
  162.         jmp     .chunks_loop
  163. ; IHDR chunk
  164. .ihdr:
  165.         cmp     ecx, 13
  166.         jnz     .invalid_chunk
  167.         cmp     [.image], 0
  168.         jnz     .invalid_chunk
  169. ; read image characteristics
  170.         lodsd
  171.         bswap   eax
  172.         mov     [.width], eax
  173.         lodsd
  174.         bswap   eax
  175.         mov     [.height], eax
  176.         xor     eax, eax
  177.         lea     ebx, [eax+1]
  178.         lodsb
  179.         cmp     al, 16
  180.         ja      .invalid_chunk
  181.         test    al, al
  182.         jz      .invalid_chunk
  183.         lea     edx, [eax-1]
  184.         test    al, dl
  185.         jnz     .invalid_chunk
  186.         mov     [.bit_depth], eax
  187.         lodsb
  188.         test    al, not 7
  189.         jnz     .invalid_chunk
  190.         mov     [.color_type], eax
  191.         lodsb
  192.         test    al, al
  193.         jnz     .invalid_chunk  ; only compression method 0 is defined
  194.         lodsb
  195.         test    al, al
  196.         jnz     .invalid_chunk  ; only filtering method 0 is defined
  197.         lodsb
  198.         cmp     al, 1
  199.         ja      .invalid_chunk  ; only interlacing methods 0 and 1 are defined
  200.         mov     [.interlace], al
  201. ; check for correctness and calculate bytes_per_pixel and scanline_len
  202.         mov     eax, [.bit_depth]
  203.         mov     edx, [.color_type]
  204.         dec     edx
  205.         js      .grayscale1
  206.         dec     edx
  207.         jz      .rgb1
  208.         dec     edx
  209.         jz      .palette1
  210.         dec     edx
  211.         jz      .grayscale_alpha1
  212.         dec     edx
  213.         dec     edx
  214.         jnz     .invalid_chunk
  215. .rgb_alpha1:
  216.         inc     ebx
  217. .rgb1:
  218.         inc     ebx
  219. .grayscale_alpha1:
  220.         inc     ebx
  221.         cmp     al, 8
  222.         jb      .invalid_chunk
  223.         jmp     @f
  224. .palette1:
  225.         cmp     al, 8
  226.         ja      .invalid_chunk
  227. .grayscale1:
  228. @@:
  229.         mul     ebx
  230.         mov     [.bits_per_pixel], eax
  231.         add     eax, 7
  232.         shr     eax, 3
  233.         mov     [.bytes_per_pixel], eax
  234. ; allocate image
  235.         push    Image.bpp24
  236.         pop     eax
  237.         cmp     [.color_type], 2
  238.         jz      @f
  239.         mov     al, Image.bpp32
  240.         cmp     [.color_type], 6
  241.         jz      @f
  242.         mov     al, Image.bpp8
  243. @@:
  244.         stdcall img.create, [.width], [.height], eax
  245.         test    eax, eax
  246.         jz      .invalid_chunk
  247.         mov     [.image], eax
  248.         jmp     .next_chunk
  249. .invalid_chunk:
  250. .iend:
  251.         pop     ecx
  252. .eof:
  253.         add     esp, .localsize
  254.         popad
  255.         ret     12
  256. ; PLTE chunk
  257. .palette:
  258.         mov     eax, [.image]
  259.         test    eax, eax
  260.         jz      .invalid_chunk
  261.         cmp     [.color_type], 3
  262.         jz      .copy_palette
  263. .ignore_chunk:
  264.         add     esi, ecx
  265. .next_chunk:
  266.         lodsd
  267.         pop     ecx
  268.         jmp     .chunks_loop
  269. .copy_palette:
  270.         mov     edi, [eax + Image.Palette]
  271.         xor     eax, eax
  272.         cmp     ecx, 256*3
  273.         ja      .next_chunk
  274. @@:
  275.         sub     ecx, 3
  276.         jz      @f
  277.         js      .invalid_chunk
  278.         lodsd
  279.         dec     esi
  280.         bswap   eax
  281.         shr     eax, 8
  282.         stosd
  283.         jmp     @b
  284. @@:
  285.         lodsd
  286.         dec     esi
  287.         bswap   eax
  288.         shr     eax, 8
  289.         stosd
  290.         jmp     .next_chunk
  291. .idat:
  292.         jecxz   .next_chunk
  293.         cmp     [.idat_read], 0
  294.         jnz     @f
  295.         lodsb
  296.         inc     [.idat_read]
  297.         and     al, 0xF
  298.         cmp     al, 8
  299.         jnz     .invalid_chunk
  300.         dec     ecx
  301.         jz      .next_chunk
  302. @@:
  303.         cmp     [.idat_read], 1
  304.         jnz     @f
  305.         lodsb
  306.         inc     [.idat_read]
  307.         test    al, 20h
  308.         jnz     .invalid_chunk
  309.         dec     ecx
  310.         jz      .next_chunk
  311. @@:
  312.         mov     [.cur_chunk_ptr], esi
  313.         mov     [.cur_chunk_size], ecx
  314.         pop     [.length]
  315.         push    eax
  316.         push    esp
  317.         push    ebp
  318.         push    .deflate_callback
  319.         call    [deflate_unpack2]
  320.         pop     ecx
  321.         test    eax, eax
  322.         jz      .invalid_chunk
  323. ; convert PNG unpacked data to RAW data
  324.         mov     esi, eax
  325.         mov     [.allocated], eax
  326.         mov     [.size_rest], ecx
  327. ; unfilter and deinterlace
  328. ; .interlace_pass, .starting_row and .starting_col have been already set to 0
  329. ; .block_width, .block_height, .col_increment, .row_increment were set
  330. ; to values for non-interlaced images; correct if necessary
  331.         cmp     [.interlace], 0
  332.         jz      .deinterlace_loop
  333.         push    8
  334.         pop     eax
  335.         mov     [.row_increment], eax
  336.         mov     [.col_increment], eax
  337.         mov     [.block_height], eax
  338.         mov     [.block_width], eax
  339.         mov     [.row_increment_shift], 3
  340.         mov     [.col_increment_shift], 3
  341. .deinterlace_loop:
  342.         mov     edx, [.height]
  343.         cmp     edx, [.starting_row]
  344.         jbe     .deinterlace_next
  345.         mov     ebx, [.width]
  346.         sub     ebx, [.starting_col]
  347.         jbe     .deinterlace_next
  348.         mov     cl, [.col_increment_shift]
  349.         add     ebx, [.col_increment]
  350.         dec     ebx
  351.         shr     ebx, cl
  352.         mov     eax, [.bits_per_pixel]
  353.         imul    eax, ebx
  354.         add     eax, 7
  355.         shr     eax, 3
  356.         mov     [.scanline_len], eax
  357.         shl     ebx, cl
  358.         mov     [.col_distance], ebx
  359. ; Unfilter
  360.         mov     ecx, [.size_rest]
  361.         push    esi
  362. .unfilter_loop_e:
  363.         mov     ebx, [.scanline_len]
  364.         sub     ecx, 1
  365.         jc      .unfilter_abort
  366.         sub     ecx, ebx
  367.         jc      .unfilter_abort
  368.         movzx   eax, byte [esi]
  369.         add     esi, 1
  370.         cmp     eax, 4
  371.         ja      .next_scanline
  372.         jmp     dword [@f + eax*4]
  373. align 4
  374. @@:
  375.         dd      .unfilter_none
  376.         dd      .unfilter_sub
  377.         dd      .unfilter_up
  378.         dd      .unfilter_average
  379.         dd      .unfilter_paeth
  380. .unfilter_sub:
  381.         mov     edi, [.bytes_per_pixel]
  382.         add     esi, edi
  383.         sub     ebx, edi
  384.         jbe     .next_scanline
  385.         neg     edi
  386. @@:
  387.         mov     al, [esi+edi]
  388.         add     [esi], al
  389.         add     esi, 1
  390.         sub     ebx, 1
  391.         jnz     @b
  392.         jmp     .next_scanline
  393. .unfilter_up:
  394.         cmp     edx, [.height]
  395.         jz      .unfilter_none
  396.         lea     edi, [ebx+1]
  397.         neg     edi
  398. @@:
  399.         mov     al, [esi+edi]
  400.         add     [esi], al
  401.         add     esi, 1
  402.         sub     ebx, 1
  403.         jnz     @b
  404.         jmp     .next_scanline
  405. .unfilter_average:
  406.         mov     edi, [.bytes_per_pixel]
  407.         cmp     edx, [.height]
  408.         jz      .unfilter_average_firstline
  409.         push    edx
  410.         lea     edx, [ebx+1]
  411.         neg     edx
  412.         sub     ebx, edi
  413. @@:
  414.         mov     al, [esi+edx]
  415.         shr     al, 1
  416.         add     [esi], al
  417.         add     esi, 1
  418.         sub     edi, 1
  419.         jnz     @b
  420.         mov     edi, [.bytes_per_pixel]
  421.         neg     edi
  422.         test    ebx, ebx
  423.         jz      .unfilter_average_done
  424. @@:
  425.         mov     al, [esi+edx]
  426.         add     al, [esi+edi]
  427.         rcr     al, 1
  428.         add     [esi], al
  429.         add     esi, 1
  430.         sub     ebx, 1
  431.         jnz     @b
  432. .unfilter_average_done:
  433.         pop     edx
  434.         jmp     .next_scanline
  435. .unfilter_average_firstline:
  436.         mov     edi, [.bytes_per_pixel]
  437.         add     esi, edi
  438.         sub     ebx, edi
  439.         jbe     .next_scanline
  440.         neg     edi
  441. @@:
  442.         mov     al, [esi+edi]
  443.         shr     al, 1
  444.         add     [esi], al
  445.         add     esi, 1
  446.         sub     ebx, 1
  447.         jnz     @b
  448.         jmp     .unfilter_none
  449. .unfilter_paeth:
  450.         cmp     edx, [.height]
  451.         jz      .unfilter_sub
  452.         push    edx
  453.         lea     edx, [ebx+1]
  454.         mov     edi, [.bytes_per_pixel]
  455.         neg     edx
  456.         sub     ebx, edi
  457. @@:
  458.         mov     al, [esi+edx]
  459.         add     [esi], al
  460.         add     esi, 1
  461.         sub     edi, 1
  462.         jnz     @b
  463.         mov     edi, [.bytes_per_pixel]
  464.         neg     edi
  465.         test    ebx, ebx
  466.         jz      .unfilter_paeth_done
  467.         push    ecx
  468. @@:
  469.         push    ebx
  470. ; PaethPredictor(Raw(x-bpp) = a, Prior(x) = b, Prior(x-bpp) = c)
  471.         movzx   eax, byte [esi+edi]
  472.         mov     [.paeth_a], eax
  473.         movzx   ecx, byte [esi+edx]
  474.         add     edi, edx
  475.         mov     [.paeth_b], ecx
  476.         add     ecx, eax
  477.         movzx   eax, byte [esi+edi]
  478.         mov     [.paeth_c], eax
  479.         sub     ecx, eax        ; ecx = a + b - c = p
  480. ; calculate pa = abs(p-a), pb = abs(p-b), pc = abs(p-c)
  481.         mov     ebx, ecx
  482.         sub     ebx, eax        ; ebx = p - c
  483.         cmp     ebx, 80000000h
  484.         sbb     eax, eax        ; eax = (p < c) ? 0 : 0xFFFFFFF
  485.         not     eax             ; eax = (p < c) ? 0xFFFFFFFF : 0
  486.         and     eax, ebx        ; eax = (p < c) ? p - c : 0
  487.         sub     ebx, eax
  488.         sub     ebx, eax        ; ebx = abs(p-c)
  489.         mov     [.paeth_pc], ebx
  490.         mov     ebx, ecx
  491.         sub     ebx, [.paeth_a]
  492.         cmp     ebx, 80000000h
  493.         sbb     eax, eax
  494.         not     eax
  495.         and     eax, ebx
  496.         sub     ebx, eax
  497.         sub     ebx, eax
  498.         mov     [.paeth_pa], ebx
  499.         mov     ebx, ecx
  500.         sub     ebx, [.paeth_b]
  501.         cmp     ebx, 80000000h
  502.         sbb     eax, eax
  503.         not     eax
  504.         and     eax, ebx
  505.         sub     ebx, eax
  506.         sub     ebx, eax
  507.         ;mov    [.paeth_pb], ebx
  508. ; select closest value
  509.         push    edx
  510.         mov     edx, [.paeth_b]
  511.         sub     edx, [.paeth_a]
  512.         sub     ebx, [.paeth_pa]
  513.         sbb     ecx, ecx        ; ecx = (pa > pb) ? 0xFFFFFFFF : 0
  514.         sbb     eax, eax        ; eax = (pa > pb) ? 0xFFFFFFFF : 0
  515.         and     ecx, ebx        ; ecx = (pa > pb) ? pb - pa : 0
  516.         and     eax, edx        ; eax = (pa > pb) ? b - a : 0
  517.         add     ecx, [.paeth_pa]        ; ecx = (pa > pb) ? pb : pa = min(pa,pb)
  518.         add     eax, [.paeth_a]         ; eax = (pa > pb) ? b : a
  519.         mov     edx, [.paeth_c]
  520.         sub     edx, eax
  521.         sub     [.paeth_pc], ecx
  522.         sbb     ebx, ebx        ; ebx = (min(pa,pb) <= pc) ? 0 : 0xFFFFFFFF
  523.         and     ebx, edx        ; ebx = (min(pa,pb) <= pc) ? 0 : c - eax
  524.         add     eax, ebx
  525.         pop     edx
  526.         add     [esi], al
  527.         pop     ebx
  528.         sub     edi, edx
  529.         add     esi, 1
  530.         sub     ebx, 1
  531.         jnz     @b
  532.         pop     ecx
  533. .unfilter_paeth_done:
  534.         pop     edx
  535.         jmp     .next_scanline
  536. .unfilter_none:
  537.         add     esi, ebx
  538. .next_scanline:
  539.         sub     edx, [.row_increment]
  540.         jc      .unfilter_done
  541.         cmp     edx, [.starting_row]
  542.         jbe     .unfilter_done
  543.         jmp     .unfilter_loop_e
  544. .unfilter_abort:
  545.         xor     ecx, ecx
  546. .unfilter_done:
  547. ; unfiltering done, now convert to raw data
  548. ; with deinterlacing if needed
  549.         pop     esi
  550.         mov     ebx, [.image]
  551.         mov     eax, [.width]
  552.         call    img._.get_scanline_len
  553.         mov     [.row_distance], eax
  554.         mov     eax, [.row_increment]
  555.         mul     [.width]
  556.         sub     eax, [.col_distance]
  557.         call    img._.get_scanline_len
  558.         mov     [.col_distance], eax
  559.         mov     edi, [ebx + Image.Data]
  560.         mov     eax, [.starting_row]
  561.         mul     [.width]
  562.         add     eax, [.starting_col]
  563.         call    img._.get_scanline_len
  564.         add     edi, eax
  565.         mov     eax, ebx
  566.         mov     ebx, [.size_rest]
  567.         mov     [.size_rest], ecx
  568.         mov     edx, [.height]
  569.         sub     edx, [.starting_row]
  570.         mov     [.j], edx
  571.         cmp     [.color_type], 0
  572.         jz      .grayscale2
  573.         cmp     [.color_type], 2
  574.         jz      .rgb2
  575.         cmp     [.color_type], 3
  576.         jz      .palette2
  577.         cmp     [.color_type], 4
  578.         jz      .grayscale_alpha2
  579. .rgb_alpha2:
  580.         cmp     [.bit_depth], 16
  581.         jz      .rgb_alpha2_16bit
  582. .rgb_alpha2.next:
  583.         sub     ebx, 1
  584.         jc      .convert_done
  585.         add     esi, 1
  586.         sub     ebx, [.scanline_len]
  587.         jc      .convert_done
  588.         mov     ecx, [.width]
  589.         sub     ecx, [.starting_col]
  590.         mov     [.i], ecx
  591. .rgb_alpha2.extloop:
  592.  
  593. macro init_block
  594. {
  595.         push    ebx
  596.         mov     eax, [.col_increment]
  597.         mov     edx, [.j]
  598.         cmp     edx, [.block_height]
  599.         jb      @f
  600.         mov     edx, [.block_height]
  601. @@:
  602.         mov     ebx, [.i]
  603.         cmp     ebx, [.block_width]
  604.         jb      @f
  605.         mov     ebx, [.block_width]
  606. @@:
  607. }
  608.  
  609.         init_block
  610.         lea     eax, [edi+eax*4]
  611.         push    eax
  612. .rgb_alpha2.innloop1:
  613.         push    edi
  614.         mov     ecx, ebx
  615. .rgb_alpha2.innloop2:
  616.         mov     al, [esi+2]
  617.         mov     [edi], al
  618.         mov     al, [esi+1]
  619.         mov     [edi+1], al
  620.         mov     al, [esi]
  621.         mov     [edi+2], al
  622.         mov     al, [esi+3]
  623.         mov     [edi+3], al
  624.         add     edi, 4
  625.         dec     ecx
  626.         jnz     .rgb_alpha2.innloop2
  627.         pop     edi
  628.         add     edi, [.row_distance]
  629.         dec     edx
  630.         jnz     .rgb_alpha2.innloop1
  631.         pop     edi ebx
  632.         add     esi, 4
  633.         mov     eax, [.col_increment]
  634.         sub     [.i], eax
  635.         ja      .rgb_alpha2.extloop
  636.         add     edi, [.col_distance]
  637.         mov     eax, [.row_increment]
  638.         sub     [.j], eax
  639.         ja      .rgb_alpha2.next
  640.         jmp     .convert_done
  641. .rgb_alpha2_16bit:
  642.         sub     ebx, 1
  643.         jc      .convert_done
  644.         add     esi, 1
  645.         sub     ebx, [.scanline_len]
  646.         jc      .convert_done
  647.         mov     ecx, [.width]
  648.         sub     ecx, [.starting_col]
  649.         mov     [.i], ecx
  650. .rgb_alpha2_16bit.loop:
  651.         init_block
  652.         lea     eax, [edi+eax*4]
  653.         push    eax
  654.  
  655. ; convert 16 bit sample to 8 bit sample
  656. macro convert_16_to_8
  657. {
  658. local .l1,.l2
  659.         xor     ah, 0x80
  660.         js      .l1
  661.         cmp     al, ah
  662.         adc     al, 0
  663.         jmp     .l2
  664. .l1:
  665.         cmp     ah, al
  666.         sbb     al, 0
  667. .l2:
  668. }
  669.  
  670. .rgb_alpha2_16bit.innloop1:
  671.         push    edi
  672.         mov     ecx, ebx
  673. .rgb_alpha2_16bit.innloop2:
  674.         mov     ax, [esi+4]
  675.         convert_16_to_8
  676.         mov     [edi], al
  677.         mov     ax, [esi+2]
  678.         convert_16_to_8
  679.         mov     [edi+1], al
  680.         mov     ax, [esi]
  681.         convert_16_to_8
  682.         mov     [edi+2], al
  683.         ;mov    ax, [esi+6]
  684.         ;convert_16_to_8
  685.         ;mov    [edi+3], al
  686.         add     edi, 4
  687.         dec     ecx
  688.         jnz     .rgb_alpha2_16bit.innloop2
  689.         pop     edi
  690.         add     edi, [.row_distance]
  691.         dec     edx
  692.         jnz     .rgb_alpha2_16bit.innloop1
  693.         pop     edi ebx
  694.         add     esi, 8
  695.         mov     eax, [.col_increment]
  696.         sub     [.i], eax
  697.         ja      .rgb_alpha2_16bit.loop
  698.         add     edi, [.col_distance]
  699.         mov     eax, [.row_increment]
  700.         sub     [.j], eax
  701.         ja      .rgb_alpha2_16bit
  702.         jmp     .convert_done
  703. .grayscale2:
  704.         call    .create_grayscale_palette
  705.         cmp     [.bit_depth], 16
  706.         jz      .grayscale2_16bit
  707. .palette2:
  708.         cmp     [.bit_depth], 1
  709.         jz      .palette2_1bit
  710.         cmp     [.bit_depth], 2
  711.         jz      .palette2_2bit
  712.         cmp     [.bit_depth], 4
  713.         jz      .palette2_4bit
  714. .palette2_8bit:
  715.         sub     ebx, 1
  716.         jc      .convert_done
  717.         add     esi, 1
  718.         sub     ebx, [.scanline_len]
  719.         jc      .convert_done
  720.         mov     ecx, [.width]
  721.         sub     ecx, [.starting_col]
  722.         mov     [.i], ecx
  723. .palette2_8bit.extloop:
  724.         init_block
  725.         add     eax, edi
  726.         push    eax
  727.         mov     al, [esi]
  728.         inc     esi
  729. macro block_byte_innerloop extloop
  730. {
  731. local .l1
  732. .l1:
  733.         mov     ecx, ebx
  734.         rep     stosb
  735.         sub     edi, ebx
  736.         add     edi, [.row_distance]
  737.         dec     edx
  738.         jnz     .l1
  739.         pop     edi ebx
  740.         mov     eax, [.col_increment]
  741.         sub     [.i], eax
  742.         ja      extloop
  743.         add     edi, [.col_distance]
  744.         mov     eax, [.row_increment]
  745.         sub     [.j], eax
  746. }
  747.         block_byte_innerloop .palette2_8bit.extloop
  748.         ja      .palette2_8bit
  749.         jmp     .convert_done
  750. .palette2_4bit:
  751.         sub     ebx, 1
  752.         jc      .convert_done
  753.         add     esi, 1
  754.         sub     ebx, [.scanline_len]
  755.         jc      .convert_done
  756.         mov     ecx, [.width]
  757.         sub     ecx, [.starting_col]
  758.         mov     [.i], ecx
  759.         mov     [.shift], 0
  760. .palette2_4bit.extloop:
  761.         init_block
  762.         add     eax, edi
  763.         push    eax
  764.         xor     [.shift], 1
  765.         jz      .palette2_4bit.shifted
  766.         mov     al, [esi]
  767.         inc     esi
  768.         shr     al, 4
  769.         jmp     @f
  770. .palette2_4bit.shifted:
  771.         mov     al, [esi-1]
  772.         and     al, 0xF
  773. @@:
  774.         block_byte_innerloop .palette2_4bit.extloop
  775.         ja      .palette2_4bit
  776.         jmp     .convert_done
  777. .palette2_2bit:
  778.         sub     ebx, 1
  779.         jc      .convert_done
  780.         add     esi, 1
  781.         sub     ebx, [.scanline_len]
  782.         jc      .convert_done
  783.         mov     ecx, [.width]
  784.         sub     ecx, [.starting_col]
  785.         mov     [.i], ecx
  786.         mov     [.shift], 0
  787. .palette2_2bit.extloop:
  788.         init_block
  789.         add     eax, edi
  790.         push    eax
  791.         mov     cl, [.shift]
  792.         sub     cl, 2
  793.         jns     .palette2_2bit.shifted
  794.         mov     cl, 6
  795.         mov     al, [esi]
  796.         inc     esi
  797.         shr     al, cl
  798.         jmp     @f
  799. .palette2_2bit.shifted:
  800.         mov     al, [esi-1]
  801.         shr     al, cl
  802.         and     al, 3
  803. @@:
  804.         mov     [.shift], cl
  805.         block_byte_innerloop .palette2_2bit.extloop
  806.         ja      .palette2_2bit
  807.         jmp     .convert_done
  808. .palette2_1bit:
  809.         sub     ebx, 1
  810.         jc      .convert_done
  811.         add     esi, 1
  812.         sub     ebx, [.scanline_len]
  813.         jc      .convert_done
  814.         mov     ecx, [.width]
  815.         sub     ecx, [.starting_col]
  816.         mov     [.i], ecx
  817.         mov     [.shift], 0
  818. .palette2_1bit.extloop:
  819.         init_block
  820.         add     eax, edi
  821.         push    eax
  822.         mov     cl, [.shift]
  823.         dec     cl
  824.         jns     .palette2_1bit.shifted
  825.         mov     cl, 7
  826.         mov     al, [esi]
  827.         inc     esi
  828.         shr     al, cl
  829.         jmp     @f
  830. .palette2_1bit.shifted:
  831.         mov     al, [esi-1]
  832.         shr     al, cl
  833.         and     al, 1
  834. @@:
  835.         mov     [.shift], cl
  836.         block_byte_innerloop .palette2_1bit.extloop
  837.         ja      .palette2_1bit
  838.         jmp     .convert_done
  839. .grayscale2_16bit:
  840.         sub     ebx, 1
  841.         jc      .convert_done
  842.         add     esi, 1
  843.         sub     ebx, [.scanline_len]
  844.         jc      .convert_done
  845.         mov     ecx, [.width]
  846.         sub     ecx, [.starting_col]
  847.         mov     [.i], ecx
  848. .grayscale2_16bit.extloop:
  849.         init_block
  850.         add     eax, edi
  851.         push    eax
  852.         mov     ax, [esi]
  853.         add     esi, 2
  854.         convert_16_to_8
  855.         block_byte_innerloop .grayscale2_16bit.extloop
  856.         ja      .grayscale2_16bit
  857.         jmp     .convert_done
  858. .rgb2:
  859.         cmp     [.bit_depth], 16
  860.         jz      .rgb2_16bit
  861. .rgb2.next:
  862.         sub     ebx, 1
  863.         jc      .convert_done
  864.         add     esi, 1
  865.         sub     ebx, [.scanline_len]
  866.         jc      .convert_done
  867.         mov     ecx, [.width]
  868.         sub     ecx, [.starting_col]
  869.         mov     [.i], ecx
  870. .rgb2.extloop:
  871.         init_block
  872.         lea     eax, [eax*3]
  873.         add     eax, edi
  874.         push    eax
  875. .rgb2.innloop1:
  876.         push    edi
  877.         mov     ecx, ebx
  878. .rgb2.innloop2:
  879.         mov     al, [esi+2]
  880.         mov     [edi], al
  881.         mov     al, [esi+1]
  882.         mov     [edi+1], al
  883.         mov     al, [esi]
  884.         mov     [edi+2], al
  885.         add     edi, 3
  886.         dec     ecx
  887.         jnz     .rgb2.innloop2
  888.         pop     edi
  889.         add     edi, [.row_distance]
  890.         dec     edx
  891.         jnz     .rgb2.innloop1
  892.         pop     edi ebx
  893.         add     esi, 3
  894.         mov     eax, [.col_increment]
  895.         sub     [.i], eax
  896.         ja      .rgb2.extloop
  897.         add     edi, [.col_distance]
  898.         mov     eax, [.row_increment]
  899.         sub     [.j], eax
  900.         ja      .rgb2.next
  901.         jmp     .convert_done
  902. .rgb2_16bit:
  903.         sub     ebx, 1
  904.         jc      .convert_done
  905.         add     esi, 1
  906.         sub     ebx, [.scanline_len]
  907.         jc      .convert_done
  908.         mov     ecx, [.width]
  909.         sub     ecx, [.starting_col]
  910.         mov     [.i], ecx
  911. .rgb2_16bit.extloop:
  912.         init_block
  913.         lea     eax, [eax*3]
  914.         add     eax, edi
  915.         push    eax
  916. .rgb2_16bit.innloop1:
  917.         push    edi
  918.         mov     ecx, ebx
  919. .rgb2_16bit.innloop2:
  920.         mov     ax, [esi+4]
  921.         convert_16_to_8
  922.         mov     [edi], al
  923.         mov     ax, [esi+2]
  924.         convert_16_to_8
  925.         mov     [edi+1], al
  926.         mov     ax, [esi]
  927.         convert_16_to_8
  928.         mov     [edi+2], al
  929.         add     edi, 3
  930.         dec     ecx
  931.         jnz     .rgb2_16bit.innloop2
  932.         pop     edi
  933.         add     edi, [.row_distance]
  934.         dec     edx
  935.         jnz     .rgb2_16bit.innloop1
  936.         pop     edi ebx
  937.         add     esi, 6
  938.         mov     eax, [.col_increment]
  939.         sub     [.i], eax
  940.         ja      .rgb2_16bit.extloop
  941.         add     edi, [.col_distance]
  942.         mov     eax, [.row_increment]
  943.         sub     [.j], eax
  944.         ja      .rgb2_16bit
  945.         jmp     .convert_done
  946. .grayscale_alpha2:
  947.         call    .create_grayscale_palette
  948.         cmp     [.bit_depth], 16
  949.         jz      .grayscale_alpha2_16bit
  950. .grayscale_alpha2.next:
  951.         sub     ebx, 1
  952.         jc      .convert_done
  953.         add     esi, 1
  954.         sub     ebx, [.scanline_len]
  955.         jc      .convert_done
  956.         mov     ecx, [.width]
  957.         sub     ecx, [.starting_col]
  958.         mov     [.i], ecx
  959. .grayscale_alpha2.extloop:
  960.         init_block
  961.         add     eax, edi
  962.         push    eax
  963.         mov     al, [esi]
  964.         add     esi, 2
  965.         block_byte_innerloop .grayscale_alpha2.extloop
  966.         ja      .grayscale_alpha2.next
  967.         jmp     .convert_done
  968. .grayscale_alpha2_16bit:
  969.         sub     ebx, 1
  970.         jc      .convert_done
  971.         add     esi, 1
  972.         sub     ebx, [.scanline_len]
  973.         jc      .convert_done
  974.         mov     ecx, [.width]
  975.         sub     ecx, [.starting_col]
  976.         mov     [.i], ecx
  977. .grayscale_alpha2_16bit.extloop:
  978.         init_block
  979.         add     eax, edi
  980.         push    eax
  981.         mov     ax, [esi]
  982.         add     esi, 4
  983.         convert_16_to_8
  984.         block_byte_innerloop .grayscale_alpha2_16bit.extloop
  985.         ja      .grayscale_alpha2_16bit
  986. .convert_done:
  987. ; next interlace pass
  988. .deinterlace_next:
  989.         mov     eax, [.block_width]
  990.         cmp     eax, [.block_height]
  991.         jz      .deinterlace_dec_width
  992.         mov     [.block_height], eax
  993.         mov     [.col_increment], eax
  994.         dec     [.col_increment_shift]
  995.         mov     [.starting_row], eax
  996.         and     [.starting_col], 0
  997.         jmp     .deinterlace_loop
  998. .deinterlace_dec_width:
  999.         shr     eax, 1
  1000.         jz      .deinterlace_done
  1001.         mov     [.block_width], eax
  1002.         mov     [.starting_col], eax
  1003.         add     eax, eax
  1004.         and     [.starting_row], 0
  1005.         mov     [.row_increment], eax
  1006.         bsf     eax, eax
  1007.         mov     [.row_increment_shift], al
  1008.         jmp     .deinterlace_loop
  1009. .deinterlace_done:
  1010.         mcall   68, 13, [.allocated]
  1011.         mov     esi, [.cur_chunk_ptr]
  1012.         add     esi, [.cur_chunk_size]
  1013.         push    [.length]
  1014.         jmp     .next_chunk
  1015.  
  1016. .deflate_callback:
  1017.         mov     ebp, [esp+4]
  1018.         mov     ebx, [esp+8]
  1019.         xor     eax, eax
  1020.         mov     esi, [.cur_chunk_size]
  1021.         mov     [ebx], esi
  1022.         test    esi, esi
  1023.         jz      .deflate_callback.ret
  1024.         mov     eax, [.cur_chunk_ptr]
  1025.         mov     ecx, [.length]
  1026.         add     esi, eax
  1027.         mov     [.cur_chunk_ptr], esi
  1028.         and     [.cur_chunk_size], 0
  1029. @@:
  1030.         sub     ecx, 12
  1031.         jb      .deflate_callback.ret
  1032.         cmp     dword [esi+4+4], 'IDAT'
  1033.         jnz     .deflate_callback.ret
  1034.         mov     edx, [esi+4]
  1035.         bswap   edx
  1036.         sub     ecx, edx
  1037.         jb      .deflate_callback.ret
  1038.         add     esi, 4+8
  1039.         test    edx, edx
  1040.         jz      @b
  1041.         mov     [.cur_chunk_size], edx
  1042.         mov     [.cur_chunk_ptr], esi
  1043.         mov     [.length], ecx
  1044. .deflate_callback.ret:
  1045.         ret     8
  1046.  
  1047. .create_grayscale_palette:
  1048.         push    edi edx
  1049.         mov     edi, [eax + Image.Palette]
  1050.         mov     ecx, [.bit_depth]
  1051.         cmp     cl, 16
  1052.         jnz     @f
  1053.         mov     cl, 8
  1054. @@:
  1055.         push    1
  1056.         pop     eax
  1057.         shl     eax, cl
  1058.         xchg    eax, ecx
  1059.         mov     edx, 0x010101
  1060.         cmp     al, 8
  1061.         jz      .graypal_common
  1062.         mov     edx, 0x111111
  1063.         cmp     al, 4
  1064.         jz      .graypal_common
  1065.         mov     edx, 0x555555
  1066.         cmp     al, 2
  1067.         jz      .graypal_common
  1068.         mov     edx, 0xFFFFFF
  1069. .graypal_common:
  1070.         xor     eax, eax
  1071. @@:
  1072.         stosd
  1073.         add     eax, edx
  1074.         loop    @b
  1075.         pop     edx edi
  1076.         ret
  1077. ;endp
  1078.  
  1079. img.encode.png:
  1080.         xor     eax, eax
  1081.         ret     12
  1082.