Subversion Repositories Kolibri OS

Rev

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