Subversion Repositories Kolibri OS

Rev

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

  1. ;;================================================================================================;;
  2. ;;//// bmp.asm //// (c) mike.dld, 2007-2008, (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. ;; References:                                                                                    ;;
  21. ;;   1. "Microsoft Windows Bitmap File Format Summary"                                            ;;
  22. ;;      from "Encyclopedia of Graphics File Formats" by O'Reilly                                  ;;
  23. ;;      http://www.fileformat.info/format/bmp/                                                    ;;
  24. ;;                                                                                                ;;
  25. ;;================================================================================================;;
  26.  
  27.  
  28. include 'bmp.inc'
  29.  
  30. ;;================================================================================================;;
  31. ;;proc img.is.bmp _data, _length ;////////////////////////////////////////////////////////////////;;
  32. img.is.bmp:
  33. ;;------------------------------------------------------------------------------------------------;;
  34. ;? Determine if raw data could be decoded (is in BMP format)                                      ;;
  35. ;;------------------------------------------------------------------------------------------------;;
  36. ;> _data = raw data as read from file/stream                                                      ;;
  37. ;> _length = data length                                                                          ;;
  38. ;;------------------------------------------------------------------------------------------------;;
  39. ;< eax = false / true                                                                             ;;
  40. ;;================================================================================================;;
  41. ; test 1 (length of data): data must contain FileHeader and required fields from InfoHeader
  42.         cmp     dword [esp+8], sizeof.bmp.FileHeader + 12
  43.         jb      .nope
  44. ; test 2: signature
  45.         mov     eax, [esp+4]
  46.         cmp     word [eax], 'BM'
  47.         je      .yep
  48.  
  49.   .nope:
  50.         xor     eax, eax
  51.         ret     8
  52.  
  53.   .yep:
  54.         xor     eax, eax
  55.         inc     eax
  56.         ret     8
  57. ;endp
  58.  
  59. ;;================================================================================================;;
  60. proc img.decode.bmp _data, _length, _options ;////////////////////////////////////////////////////;;
  61. ;;------------------------------------------------------------------------------------------------;;
  62. ;? Decode data into image if it contains correctly formed raw data in BMP format                  ;;
  63. ;;------------------------------------------------------------------------------------------------;;
  64. ;> _data = raw data as read from file/stream                                                      ;;
  65. ;> _length = data length                                                                          ;;
  66. ;;------------------------------------------------------------------------------------------------;;
  67. ;< eax = 0 (error) or pointer to image                                                            ;;
  68. ;;================================================================================================;;
  69. locals
  70.   length_rest dd ?
  71.   img dd ?
  72.   bTopDown db ?
  73.   bIsIco db ?
  74. endl
  75. img.decode.bmp.length_rest equ length_rest
  76.         mov     [bIsIco], 0
  77. .common: ; common place for BMP and ICO
  78.  
  79.         push    ebx esi edi
  80.  
  81.         mov     ebx, [_data]
  82.         cmp     [bIsIco], 0
  83.         jnz     @f
  84.         add     ebx, sizeof.bmp.FileHeader
  85.         sub     [_length], sizeof.bmp.FileHeader
  86.    @@:
  87.  
  88.         mov     eax, [ebx + bmp.InfoHeader.Size]
  89. ; sanity check: file length must be greater than size of headers
  90.         cmp     [_length], eax
  91.         jbe     .error
  92.  
  93.         mov     [bTopDown], 0
  94.  
  95.         cmp     eax, 12         ; 0x0C
  96.         jz      .old1
  97.         cmp     eax, 40         ; 0x28
  98.         jz      .normal
  99.         cmp     eax, 56         ; 0x38
  100.         je      .normal
  101.         cmp     eax, 0x6C
  102.         je      .normal
  103.         cmp     eax, 0x7C
  104.         jnz     .error
  105. ; convert images with <= 8 bpp to 8bpp, other - to 32 bpp
  106. .normal:
  107.         m2m     eax, Image.bpp8
  108.         cmp     byte [ebx + 14], 8      ; bit count
  109.         jbe     @f
  110.         mov     al, Image.bpp32
  111. @@:
  112.         push    eax
  113.         mov     eax, [ebx + 8]  ;[ebx + bmp.InfoHeader.Height]
  114.         test    eax, eax
  115.         jns     @f
  116.         inc     [bTopDown]
  117.         neg     eax
  118. @@:
  119.         cmp     [bIsIco], 0     ; for icons Height is two times larger than image height
  120.         jz      @f
  121.         shr     eax, 1
  122. @@:
  123.         pushd   eax
  124.         pushd   [ebx + 4]       ;[ebx + bmp.InfoHeader.Width]
  125.         jmp     .create
  126. .old1:
  127.         m2m     eax, Image.bpp8
  128.         cmp     byte [ebx + 10], 8      ; bit count
  129.         jbe     @f
  130.         mov     al, Image.bpp32
  131. @@:
  132.         push    eax
  133.         movsx   eax, word [ebx + 6]     ;[ebx + bmp.InfoHeader.OldHeight]
  134.         test    eax, eax
  135.         jns     @f
  136.         inc     [bTopDown]
  137.         neg     eax
  138. @@:
  139.         cmp     [bIsIco], 0     ; for icons Height is two times larger than image height
  140.         jz      @f
  141.         shr     eax, 1
  142. @@:
  143.         push    eax
  144.         movzx   eax, word [ebx + 4]     ;[ebx + bmp.InfoHeader.OldWidth]
  145.         push    eax
  146. .create:
  147.         call    img.create
  148.  
  149.         or      eax, eax
  150.         jz      .error
  151.         mov     [img], eax
  152.         mov     edx, eax
  153.  
  154.         invoke  mem.alloc, sizeof.bmp.Image
  155.         or      eax, eax
  156.         jz      .error.free
  157.         mov     [edx + Image.Extended], eax
  158.         push    eax
  159.         mov     edi, eax
  160.         mov     ecx, sizeof.bmp.Image/4
  161.         xor     eax, eax
  162.         rep     stosd
  163.         pop     edi
  164.         push    edi
  165.         mov     esi, ebx
  166.         mov     ecx, [ebx]      ;[ebx + bmp.InfoHeader.Size]
  167.         cmp     ecx, 12
  168.         jz      .old2
  169.         rep     movsb
  170.         jmp     .decode
  171. .old2:
  172.         movsd   ; Size
  173.         movzx   eax, word [esi] ; OldWidth -> Width
  174.         stosd
  175.         movsx   eax, word [esi+2]       ; OldHeight -> Height
  176.         stosd
  177.         lodsd   ; skip OldWidth+OldHeight
  178.         movsd   ; Planes+BitCount
  179. .decode:
  180.  
  181.         pop     edi
  182.         cmp     [bIsIco], 0
  183.         jnz     @f
  184.         mov     edi, [_length]
  185.         add     edi, sizeof.bmp.FileHeader
  186.         mov     esi, [ebx - sizeof.bmp.FileHeader + bmp.FileHeader.OffBits]
  187.         jmp     .offset_calculated
  188. @@:
  189.         xor     esi, esi
  190.         mov     cl, byte [edi + bmp.Image.info.BitCount]
  191.         cmp     cl, 8
  192.         ja      @f
  193.         inc     esi
  194.         add     cl, 2
  195.         shl     esi, cl
  196. @@:
  197.         add     esi, [edi + bmp.Image.info.Size]
  198.         mov     edi, [_length]
  199. .offset_calculated:
  200.         sub     edi, esi
  201.         jbe     .error.free
  202.         add     esi, [_data]
  203.  
  204.         mov     eax, [edx + Image.Extended]
  205.         mov     eax, [eax + bmp.Image.info.Compression]
  206.         cmp     eax, bmp.BI_RGB
  207.         jne     @f
  208.         stdcall ._.rgb
  209.         jmp     .decoded
  210.     @@: cmp     eax, bmp.BI_RLE8
  211.         jne     @f
  212.         cmp     word [ebx + 14], 8 ;bmp.InfoHeader.BitCount
  213.         jnz     .error.free
  214.         stdcall ._.rle
  215.         jmp     .decoded
  216.     @@: cmp     eax, bmp.BI_RLE4
  217.         jne     @f
  218.         cmp     word [ebx + 14], 4
  219.         jnz     .error.free
  220.         stdcall ._.rle
  221.         jmp     .decoded
  222.     @@: cmp     eax, bmp.BI_BITFIELDS
  223.         jne     .error.free
  224.         stdcall ._.bitfields
  225.         jmp     .decoded
  226. ; BI_JPEG and BI_PNG constants are not valid values for BMP file,
  227. ; they are intended for WinAPI
  228. ;    @@: cmp    eax, bmp.BI_JPEG
  229. ;       jne     @f
  230. ;       stdcall ._.jpeg
  231. ;       jmp     .decoded
  232. ;    @@: cmp    eax, bmp.BI_PNG
  233. ;       jne     .error
  234. ;       stdcall ._.png
  235.  
  236.   .decoded:
  237.         or      eax, eax
  238.         jz      @f
  239.   .error.free:
  240.         stdcall img.destroy, [img]
  241.         jmp     .error
  242.  
  243.     @@:
  244.         cmp     [bTopDown], 0
  245.         jnz     @f
  246.         stdcall img.flip, [img], FLIP_VERTICAL
  247.     @@:
  248.         mov     eax, [img]
  249.         mov     ecx, [length_rest]      ; return length for ICO code
  250.         cmp     [bIsIco], 0
  251.         jz      @f
  252.         mov     [esp + 4], esi  ; return pointer to end-of-data for ICO code
  253.     @@:
  254.         pop     edi esi ebx
  255.         ret
  256.  
  257.   .error:
  258.         xor     eax, eax
  259.         pop     edi esi ebx
  260.         ret
  261. endp
  262.  
  263. ;;================================================================================================;;
  264. proc img.encode.bmp _img, _common, _specific ;////////////////////////////////////////////////////;;
  265. ;;------------------------------------------------------------------------------------------------;;
  266. ;? Encode image into raw data in BMP format                                                       ;;
  267. ;;------------------------------------------------------------------------------------------------;;
  268. ;> [_img]      = pointer to image                                                                 ;;
  269. ;> [_common]   = format independent options                                                       ;;
  270. ;> [_specific] = 0 / pointer to the structure of format specific options                          ;;
  271. ;;------------------------------------------------------------------------------------------------;;
  272. ;< eax = 0 / pointer to encoded data                                                              ;;
  273. ;< ecx = error code / the size of encoded data                                                    ;;
  274. ;;================================================================================================;;
  275. locals
  276.         bytes_per_scanline      rd 1
  277.         encoded_file            rd 1
  278.         encoded_file_size       rd 1
  279.         encoded_data_size       rd 1
  280. endl
  281.         mov     ebx, [_img]
  282.         mov     eax, [ebx + Image.Type]
  283.         cmp     eax, Image.bpp24
  284.         je      .bpp24
  285.         cmp     eax, Image.bpp32
  286.         je      .bpp32
  287.         mov     ecx, LIBIMG_ERROR_BIT_DEPTH
  288.         jmp     .error
  289.  
  290.   .bpp24:
  291.         mov     eax, [ebx + Image.Width]
  292.         call    img._.get_scanline_len
  293.         test    eax, 0x03
  294.         jz      @f
  295.         and     al, 0xfc
  296.         add     eax, 4
  297.     @@:
  298.         mov     [bytes_per_scanline], eax
  299.         imul    eax, [ebx + Image.Height]
  300.         mov     [encoded_data_size], eax
  301.         add     eax, 108 + 14
  302.         mov     [encoded_file_size], eax
  303.         stdcall [mem.alloc], eax
  304.         test    eax, eax
  305.         jz      .error
  306.         mov     [encoded_file], eax
  307.         mov     edi, eax
  308.  
  309.         mov     word[edi], 'BM'
  310.         add     edi, 2
  311.         mov     eax, [encoded_file_size]
  312.         stosd
  313.         xor     eax, eax
  314.         stosd
  315.         mov     eax, 108 + 14
  316.         stosd
  317.         mov     eax, 108
  318.         stosd
  319.         mov     eax, [ebx + Image.Width]
  320.         stosd
  321.         mov     eax, [ebx + Image.Height]
  322.         stosd
  323.         mov     ax, 1   ; Planes
  324.         stosw
  325.         mov     ax, 24  ; BitCount
  326.         stosw
  327.         mov     eax, bmp.BI_RGB
  328.         stosd
  329.         mov     eax, [encoded_data_size]
  330.         stosd
  331.         mov     eax, 0x00000B13
  332.         stosd
  333.         stosd
  334.         xor     eax, eax
  335.         stosd
  336.         stosd
  337.         mov     eax, 'BGRs'
  338.         stosd
  339.         xor     eax, eax
  340.         stosd
  341.         stosd
  342.         stosd
  343.         stosd
  344.         stosd
  345.         stosd
  346.         stosd
  347.         stosd
  348.         stosd
  349.         stosd
  350.         stosd
  351.         stosd
  352.         mov     eax, 2
  353.         stosd
  354.         xor     eax, eax
  355.         stosd
  356.         stosd
  357.         stosd
  358.  
  359.         mov     esi, [ebx + Image.Data]
  360.         mov     ecx, [ebx + Image.Width]
  361.         lea     ecx, [ecx*3]
  362.         mov     eax, [ebx + Image.Height]
  363.         mov     edx, [bytes_per_scanline]
  364.         sub     edx, ecx
  365.         mov     dh, cl
  366.         and     dh, 3
  367.         shr     ecx, 2
  368.         push    ecx
  369.         add     edi, [encoded_data_size]
  370.         sub     edi, [bytes_per_scanline]
  371.     @@:
  372.         pop     ecx
  373.         push    ecx
  374.         rep     movsd
  375.         mov     cl, dh
  376.         rep     movsb
  377.         mov     cl, dl
  378.         add     edi, ecx
  379.         sub     edi, [bytes_per_scanline]
  380.         sub     edi, [bytes_per_scanline]
  381.         dec     eax
  382.         jnz     @b
  383.         pop     ecx
  384.         mov     eax, [encoded_file]
  385.         mov     ecx, [encoded_file_size]
  386.         jmp     .quit
  387.  
  388.   .bpp32:
  389.         mov     eax, [ebx + Image.Width]
  390.         call    img._.get_scanline_len
  391.         mov     [bytes_per_scanline], eax
  392.         imul    eax, [ebx + Image.Height]
  393.         mov     [encoded_data_size], eax
  394.         add     eax, 0x7C + 14
  395.         mov     [encoded_file_size], eax
  396.         stdcall [mem.alloc], eax
  397.         test    eax, eax
  398.         jz      .error
  399.         mov     [encoded_file], eax
  400.         mov     edi, eax
  401.  
  402.         mov     word[edi], 'BM'
  403.         add     edi, 2
  404.         mov     eax, [encoded_file_size]
  405.         stosd
  406.         xor     eax, eax
  407.         stosd
  408.         mov     eax, 0x7C + 14
  409.         stosd
  410.         mov     eax, 0x7C
  411.         stosd
  412.         mov     eax, [ebx + Image.Width]
  413.         stosd
  414.         mov     eax, [ebx + Image.Height]
  415.         stosd
  416.         mov     ax, 1   ; Planes
  417.         stosw
  418.         mov     ax, 32  ; BitCount
  419.         stosw
  420.         mov     eax, 3  ; WTF? bmp.BI_RGB
  421.         stosd
  422.         mov     eax, [encoded_data_size]
  423.         stosd
  424.         mov     eax, 0x00000B13
  425.         stosd
  426.         stosd
  427.         xor     eax, eax
  428.         stosd
  429.         stosd
  430.         mov     eax, 0xFF000000
  431.         stosd
  432.         shr     eax, 8
  433.         stosd
  434.         shr     eax, 8
  435.         stosd
  436. ;       shr     eax, 8
  437.         xor     eax, eax
  438.         stosd
  439.         mov     eax, 'BGRs'
  440.         stosd
  441.         xor     eax, eax
  442.         stosd
  443.         stosd
  444.         stosd
  445.         stosd
  446.         stosd
  447.         stosd
  448.         stosd
  449.         stosd
  450.         stosd
  451.         stosd
  452.         stosd
  453.         stosd
  454.         mov     eax, 2
  455.         stosd
  456.         xor     eax, eax
  457.         stosd
  458.         stosd
  459.         stosd
  460.  
  461.         mov     esi, [ebx + Image.Data]
  462.         mov     ecx, [ebx + Image.Width]
  463.         mov     eax, [ebx + Image.Height]
  464.         add     edi, [encoded_data_size]
  465.         sub     edi, [bytes_per_scanline]
  466.         push    ecx
  467.   .next_line:
  468.         pop     ecx
  469.         push    ecx
  470.         push    eax
  471.     @@:
  472.         dec     ecx
  473.         js      @f
  474.         lodsd
  475.         rol     eax, 8
  476.         stosd
  477.         jmp     @b
  478.     @@:
  479.         sub     edi, [bytes_per_scanline]
  480.         sub     edi, [bytes_per_scanline]
  481.         pop     eax
  482.         dec     eax
  483.         jnz     .next_line
  484.         pop     ecx
  485.         mov     eax, [encoded_file]
  486.         mov     ecx, [encoded_file_size]
  487.         jmp     .quit
  488.  
  489.   .error:
  490.         xor     eax, eax
  491.   .quit:
  492.         ret
  493. endp
  494.  
  495.  
  496. ;;================================================================================================;;
  497. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  498. ;;================================================================================================;;
  499. ;! Below are private procs you should never call directly from your code                          ;;
  500. ;;================================================================================================;;
  501. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  502. ;;================================================================================================;;
  503.  
  504.  
  505. ;;================================================================================================;;
  506. proc img.decode.bmp._.rgb ;///////////////////////////////////////////////////////////////////////;;
  507. ;;------------------------------------------------------------------------------------------------;;
  508. ;? --- TBD ---                                                                                    ;;
  509. ;;------------------------------------------------------------------------------------------------;;
  510. ;> ebx = raw image data                                                                           ;;
  511. ;> edx = image data                                                                               ;;
  512. ;;------------------------------------------------------------------------------------------------;;
  513. ;< --- TBD ---                                                                                    ;;
  514. ;;================================================================================================;;
  515.         mov     ecx, [edx + Image.Extended]
  516.         mov     [ecx + bmp.Image.info.AlphaMask], 0
  517.  
  518.         movzx   eax, [ecx + bmp.Image.info.BitCount]
  519.         cmp     eax, 32
  520.         je      .32bpp
  521.         cmp     eax, 24
  522.         je      .24bpp
  523.         cmp     eax, 16
  524.         je      .16bpp
  525.         cmp     eax, 8
  526.         je      .8bpp
  527.         cmp     eax, 4
  528.         je      .4bpp
  529.         cmp     eax, 1
  530.         je      .1bpp
  531.         jmp     .error
  532.  
  533. ;;------------------------------------------------------------------------------------------------;;
  534.  
  535. img.decode.bmp._.rgb.32bpp:
  536.         mov     [ecx + bmp.Image.info.RedMask],   00000000111111110000000000000000b ; 8-0-0
  537.         mov     [ecx + bmp.Image.info.GreenMask], 00000000000000001111111100000000b ; 0-8-0
  538.         mov     [ecx + bmp.Image.info.BlueMask],  00000000000000000000000011111111b ; 0-0-8
  539.         stdcall img.decode.bmp._.bitfields
  540.         ret
  541.  
  542. ;;------------------------------------------------------------------------------------------------;;
  543.  
  544. img.decode.bmp._.rgb.24bpp:
  545.         mov     eax, [edx + Image.Width]
  546.         lea     eax, [eax*3 + 3]
  547.         and     eax, not 3
  548.         mov     ecx, [edx + Image.Height]
  549.         imul    eax, ecx
  550.         sub     edi, eax
  551.         jb      img.decode.bmp._.rgb.error
  552.         mov     [img.decode.bmp.length_rest], edi
  553.         mov     edi, [edx + Image.Data]
  554.  
  555.   .next_line:
  556.         push    ecx edx
  557.         mov     ecx, [edx + Image.Width]
  558.         xor     edx, edx
  559.  
  560.   .next_line_pixel:
  561.         movsd
  562.         dec     esi
  563.         inc     edx
  564.         dec     ecx
  565.         jnz     .next_line_pixel
  566.  
  567.         and     edx, 0x03
  568.         add     esi, edx
  569.         pop     edx ecx
  570.         dec     ecx
  571.         jnz     .next_line
  572.  
  573.         jmp     img.decode.bmp._.rgb.exit
  574.  
  575. ;;------------------------------------------------------------------------------------------------;;
  576.  
  577. img.decode.bmp._.rgb.16bpp:
  578.         mov     [ecx + bmp.Image.info.RedMask],   00000000000000000111110000000000b ; 5-0-0
  579.         mov     [ecx + bmp.Image.info.GreenMask], 00000000000000000000001111100000b ; 0-5-0
  580.         mov     [ecx + bmp.Image.info.BlueMask],  00000000000000000000000000011111b ; 0-0-5
  581.         stdcall img.decode.bmp._.bitfields
  582.         ret
  583.  
  584. ;;------------------------------------------------------------------------------------------------;;
  585.  
  586. img.decode.bmp._.rgb.8bpp:
  587.         mov     eax, [edx + Image.Width]
  588.         add     eax, 3
  589.         call    img.decode.bmp._.rgb.prepare_palette
  590.         jc      img.decode.bmp._.rgb.error
  591.  
  592.   .next_line:
  593.         push    ecx
  594.         mov     ecx, [edx + Image.Width]
  595.         mov     eax, ecx
  596.         neg     eax
  597.         and     eax, 3
  598.         rep     movsb
  599.         add     esi, eax
  600.         pop     ecx
  601.         dec     ecx
  602.         jnz     .next_line
  603.  
  604.         jmp     img.decode.bmp._.rgb.exit
  605.  
  606. ;;------------------------------------------------------------------------------------------------;;
  607.  
  608. img.decode.bmp._.rgb.4bpp:
  609.         mov     eax, [edx + Image.Width]
  610.         add     eax, 7
  611.         shr     eax, 1
  612.         call    img.decode.bmp._.rgb.prepare_palette
  613.         jc      img.decode.bmp._.rgb.error
  614.  
  615.   .next_line:
  616.         push    ecx edx
  617.         mov     ecx, [edx + Image.Width]
  618.  
  619.   .next_line_dword:
  620.         push    ecx
  621.         lodsd
  622.         bswap   eax
  623.         xchg    edx, eax
  624.         mov     ecx, 32 / 4
  625.  
  626.   .next_pixel:
  627.         rol     edx, 4
  628.         mov     al, dl
  629.         and     al, 0x0000000F
  630.         stosb
  631.         dec     dword[esp]
  632.         jz      @f
  633.         dec     ecx
  634.         jnz     .next_pixel
  635.  
  636.     @@: pop     ecx
  637.         or      ecx, ecx
  638.         jnz     .next_line_dword
  639.  
  640.         pop     edx ecx
  641.         dec     ecx
  642.         jnz     .next_line
  643.  
  644.         jmp     img.decode.bmp._.rgb.exit
  645.  
  646. ;;------------------------------------------------------------------------------------------------;;
  647.  
  648. img.decode.bmp._.rgb.1bpp:
  649.         mov     eax, [edx + Image.Width]
  650.         add     eax, 31
  651.         shr     eax, 3
  652.         call    img.decode.bmp._.rgb.prepare_palette
  653.         jc      img.decode.bmp._.rgb.error
  654.  
  655.   .next_line:
  656.         push    ecx edx
  657.         mov     ecx, [edx + Image.Width]
  658.  
  659.   .next_line_dword:
  660.         push    ecx
  661.         lodsd
  662.         bswap   eax
  663.         xchg    edx, eax
  664.         mov     ecx, 32 / 1
  665.  
  666.   .next_pixel:
  667.         rol     edx, 1
  668.         mov     al, dl
  669.         and     al, 0x00000001
  670.         stosb
  671.         dec     dword[esp]
  672.         jz      @f
  673.         dec     ecx
  674.         jnz     .next_pixel
  675.  
  676.     @@: pop     ecx
  677.         or      ecx, ecx
  678.         jnz     .next_line_dword
  679.  
  680.         pop     edx ecx
  681.         dec     ecx
  682.         jnz     .next_line
  683.  
  684.         jmp     img.decode.bmp._.rgb.exit
  685.  
  686. ;;------------------------------------------------------------------------------------------------;;
  687.  
  688.   img.decode.bmp._.rgb.exit:
  689.         xor     eax, eax
  690.         ret
  691.  
  692.   img.decode.bmp._.rgb.error:
  693.         or      eax, -1
  694.         ret
  695.  
  696. img.decode.bmp._.rgb.prepare_palette:
  697.         and     eax, not 3
  698.         mov     ecx, [edx + Image.Height]
  699.         imul    eax, ecx
  700.         sub     edi, eax
  701.         jb      .ret
  702.         mov     [img.decode.bmp.length_rest], edi
  703.         push    esi
  704.         sub     esi, ebx
  705.         jc      .ret.pop
  706.         sub     esi, [ebx + bmp.InfoHeader.Size]
  707.         jc      .ret.pop
  708.         mov     eax, esi
  709.         mov     edi, [edx + Image.Palette]
  710.         push    ecx
  711.         mov     ecx, 256
  712.         mov     esi, [ebx + bmp.InfoHeader.Size]
  713.         cmp     esi, 12
  714.         jz      .old
  715.         shr     eax, 2
  716.         add     esi, ebx
  717.         cmp     ecx, eax
  718.         jb      @f
  719.         mov     ecx, eax
  720. @@:
  721.         rep     movsd
  722.         jmp     .common
  723. .old:
  724.         add     esi, ebx
  725. @@:
  726.         movsd
  727.         dec     esi
  728.         sub     eax, 3
  729.         jbe     @f
  730.         sub     ecx, 1
  731.         jnz     @b
  732. @@:
  733. .common:
  734.         pop     ecx
  735.         mov     edi, [edx + Image.Data]
  736.         clc
  737. .ret.pop:
  738.         pop     esi
  739. .ret:
  740.         ret
  741. endp
  742.  
  743. ;;================================================================================================;;
  744. proc img.decode.bmp._.rle ;///////////////////////////////////////////////////////////////////////;;
  745. ;;------------------------------------------------------------------------------------------------;;
  746. ;? --- TBD ---                                                                                    ;;
  747. ;;------------------------------------------------------------------------------------------------;;
  748. ;> ebx = raw image data                                                                           ;;
  749. ;> edx = image data                                                                               ;;
  750. ;;------------------------------------------------------------------------------------------------;;
  751. ;< --- TBD ---                                                                                    ;;
  752. ;;================================================================================================;;
  753. locals
  754.   scanline_len  dd ?
  755.   marker_x      dd ?
  756.   marker_y      dd ?
  757.   abs_mode_addr dd ?
  758.   enc_mode_addr dd ?
  759.   height        dd ?
  760. endl
  761.  
  762.         mov     [abs_mode_addr], .absolute_mode.rle8
  763.         mov     [enc_mode_addr], .encoded_mode.rle8
  764.         cmp     [ebx + bmp.InfoHeader.Compression], bmp.BI_RLE4
  765.         jne     @f
  766.         mov     [abs_mode_addr], .absolute_mode.rle4
  767.         mov     [enc_mode_addr], .encoded_mode.rle4
  768.     @@:
  769.  
  770.         push    edi
  771.         xor     eax, eax        ; do not check file size in .prepare_palette
  772.         push    ebp
  773.         mov     ebp, [ebp]      ; set parent stack frame
  774.         call    img.decode.bmp._.rgb.prepare_palette
  775.         pop     ebp
  776.         pop     ecx     ; ecx = rest bytes in file
  777.         jc      .error
  778.  
  779.         mov     eax, [edx + Image.Width]
  780.         mov     [scanline_len], eax
  781.         mov     eax, [edx + Image.Height]
  782.         mov     [height], eax
  783.         xor     eax, eax
  784.         mov     [marker_x], eax
  785.         mov     [marker_y], eax
  786.         mov     edi, [edx + Image.Data]
  787.  
  788.   .next_run:
  789.         sub     ecx, 1
  790.         jc      .eof
  791.         xor     eax, eax
  792.         lodsb
  793.         or      al, al
  794.         jz      .escape_mode
  795.         jmp     [enc_mode_addr]
  796.  
  797.   .escape_mode:
  798.         sub     ecx, 1
  799.         jc      .eof
  800.         lodsb
  801.         cmp     al, 0
  802.         je      .end_of_scanline
  803.         cmp     al, 1
  804.         je      .exit
  805.         cmp     al, 2
  806.         je      .offset_marker
  807.         jmp     [abs_mode_addr]
  808.  
  809.   .end_of_scanline: ; 0
  810.         sub     edi, [marker_x]
  811.         add     edi, [scanline_len]
  812.         mov     [marker_x], 0
  813.         mov     eax, [marker_y]
  814.         inc     eax
  815.         mov     [marker_y], eax
  816.         cmp     eax, [height]
  817.         jb      .next_run
  818.         jmp     .exit
  819.  
  820.   .offset_marker: ; 2: dx, dy
  821.         sub     ecx, 2
  822.         jc      .eof
  823.         lodsb
  824.         mov     edx, [marker_x]
  825.         add     edx, eax
  826.         cmp     edx, [scanline_len]
  827.         jae     .exit
  828.         mov     [marker_x], edx
  829.         add     edi, eax
  830.         lodsb
  831.         mov     edx, [marker_y]
  832.         add     edx, eax
  833.         cmp     edx, [height]
  834.         jae     .exit
  835.         mov     [marker_y], edx
  836.         imul    eax, [scanline_len]
  837.         add     edi, eax
  838.         jmp     .next_run
  839.  
  840.   .encoded_mode.rle8: ; N: b1 * N
  841.         call    .fix_marker
  842.         sub     ecx, 1
  843.         jc      .eof
  844.         lodsb
  845.         push    ecx
  846.         mov     ecx, edx
  847.         rep     stosb
  848.         pop     ecx
  849.         jmp     .check_eoi
  850.  
  851.   .absolute_mode.rle8: ; N: b1 .. bN
  852.         call    .fix_marker
  853.         cmp     ecx, edx
  854.         jae     @f
  855.         mov     edx, ecx
  856.     @@:
  857.         push    ecx
  858.         mov     ecx, edx
  859.         rep     movsb
  860.         pop     ecx
  861.         sub     ecx, edx
  862.         jz      .eof
  863.         test    edx, 1
  864.         jz      .check_eoi
  865.         sub     ecx, 1
  866.         jc      .eof
  867.         inc     esi
  868.   .check_eoi:
  869.         mov     eax, [marker_y]
  870.         cmp     eax, [height]
  871.         jb      .next_run
  872.         jmp     .exit
  873.  
  874.   .encoded_mode.rle4: ; N: b1 * N
  875.         call    .fix_marker
  876.         sub     ecx, 1
  877.         jc      .eof
  878.         movzx   eax, byte [esi]
  879.         inc     esi
  880.         push    ecx
  881.         mov     ecx, eax
  882.         and     eax, 0xF
  883.         shr     ecx, 4
  884.     @@:
  885.         dec     edx
  886.         js      @f
  887.         mov     [edi], cl
  888.         dec     edx
  889.         js      @f
  890.         mov     [edi+1], al
  891.         add     edi, 2
  892.         jmp     @b
  893.     @@:
  894.         pop     ecx
  895.         jmp     .check_eoi
  896.  
  897.   .absolute_mode.rle4: ; N: b1 .. bN
  898.         call    .fix_marker
  899.         lea     eax, [edx+1]
  900.         shr     eax, 1
  901.         cmp     ecx, eax
  902.         jbe     @f
  903.         lea     edx, [ecx*2]
  904.     @@:
  905.         push    ecx edx
  906.     @@: dec     edx
  907.         js      @f
  908.         lodsb
  909.         mov     cl, al
  910.         shr     al, 4
  911.         and     cl, 0xF
  912.         stosb
  913.         dec     edx
  914.         js      @f
  915.         mov     [edi], cl
  916.         inc     edi
  917.         jmp     @b
  918.     @@: pop     eax ecx
  919.         and     eax, 0x03
  920.         jp      .check_eoi
  921.         sub     ecx, 1
  922.         jc      .eof
  923.         inc     esi
  924.         jmp     .check_eoi
  925.  
  926.   .fix_marker:
  927.         mov     edx, eax
  928.         add     eax, [marker_x]
  929.         mov     [marker_x], eax
  930.     @@:
  931.         sub     eax, [scanline_len]
  932.         jle     @f
  933.         mov     [marker_x], eax
  934.         push    eax
  935.         mov     eax, [marker_y]
  936.         inc     eax
  937.         mov     [marker_y], eax
  938.         cmp     eax, [height]
  939.         pop     eax
  940.         jb      @b
  941.         sub     edx, eax
  942.     @@:
  943.         retn
  944.  
  945.   .exit:
  946.   .eof:
  947.         xor     eax, eax
  948.         ret
  949.  
  950.   .error:
  951.         or      eax, -1
  952.         ret
  953. endp
  954.  
  955. ;;================================================================================================;;
  956. proc img.decode.bmp._.bitfields ;/////////////////////////////////////////////////////////////////;;
  957. ;;------------------------------------------------------------------------------------------------;;
  958. ;? --- TBD ---                                                                                    ;;
  959. ;;------------------------------------------------------------------------------------------------;;
  960. ;> ebx = raw image data                                                                           ;;
  961. ;> edx = image data                                                                               ;;
  962. ;;------------------------------------------------------------------------------------------------;;
  963. ;< --- TBD ---                                                                                    ;;
  964. ;;================================================================================================;;
  965. locals
  966.   shift   bmp.RgbByteQuad
  967.   unshift bmp.RgbByteQuad
  968.   mask    bmp.RgbQuad
  969.   delta   dd ?
  970. endl
  971.  
  972.         mov     [delta], 4
  973.         mov     eax, [edx + Image.Extended]
  974.         cmp     [eax + bmp.Image.info.BitCount], 32
  975.         je      @f
  976.         cmp     [eax + bmp.Image.info.BitCount], 16
  977.         jne     .error
  978.         mov     [delta], 2
  979.     @@:
  980.         mov     ecx, [edx + Image.Width]
  981.         imul    ecx, [edx + Image.Height]
  982.         imul    ecx, [delta]
  983.         sub     edi, ecx
  984.         jb      .error
  985.         mov     ecx, [ebp]      ; use parent stack frame
  986.         mov     [ecx + img.decode.bmp.length_rest - ebp], edi   ; !
  987.  
  988.         push    esi
  989.         mov     esi, eax
  990.  
  991.         mov     ecx, [esi + bmp.Image.info.RedMask]
  992.         call    .calc_shift
  993.         mov     [shift.Red], al
  994.         mov     [mask.Red], ecx
  995.         call    .calc_unshift
  996.         mov     [unshift.Red], al
  997.         mov     ecx, [esi + bmp.Image.info.GreenMask]
  998.         call    .calc_shift
  999.         mov     [shift.Green], al
  1000.         mov     [unshift.Green], al
  1001.         mov     [mask.Green], ecx
  1002.         call    .calc_unshift
  1003.         mov     [unshift.Green], al
  1004.         mov     ecx, [esi + bmp.Image.info.BlueMask]
  1005.         call    .calc_shift
  1006.         mov     [shift.Blue], al
  1007.         mov     [unshift.Blue], al
  1008.         mov     [mask.Blue], ecx
  1009.         call    .calc_unshift
  1010.         mov     [unshift.Blue], al
  1011.         mov     ecx, [esi + bmp.Image.info.AlphaMask]
  1012.         call    .calc_shift
  1013.         mov     [shift.Alpha], al
  1014.         mov     [unshift.Alpha], al
  1015.         mov     [mask.Alpha], ecx
  1016.         call    .calc_unshift
  1017.         mov     [unshift.Alpha], al
  1018.  
  1019.         mov     edi, [edx + Image.Data]
  1020.         pop     esi
  1021.  
  1022. ;;------------------------------------------------------------------------------------------------;;
  1023.  
  1024.         mov     ecx, [edx + Image.Height]
  1025.  
  1026.   .next_line:
  1027.         push    ecx
  1028.         mov     ecx, [edx + Image.Width]
  1029.        
  1030.   .next_pixel:
  1031.         push    ecx
  1032.  
  1033.         mov     eax, [esi]
  1034.         mov     cl, [shift.Blue]
  1035.         shr     eax, cl
  1036.         and     eax, [mask.Blue]
  1037.         mov     cl, [unshift.Blue]
  1038.         shl     eax, cl
  1039.         stosb
  1040.  
  1041.         mov     eax, [esi]
  1042.         mov     cl, [shift.Green]
  1043.         shr     eax, cl
  1044.         and     eax, [mask.Green]
  1045.         mov     cl, [unshift.Green]
  1046.         shl     eax, cl
  1047.         stosb
  1048.  
  1049.         mov     eax, [esi]
  1050.         mov     cl, [shift.Red]
  1051.         shr     eax, cl
  1052.         and     eax, [mask.Red]
  1053.         mov     cl, [unshift.Red]
  1054.         shl     eax, cl
  1055.         stosb
  1056.  
  1057.         mov     eax, [esi]
  1058.         mov     cl, [shift.Alpha]
  1059.         shr     eax, cl
  1060.         and     eax, [mask.Alpha]
  1061.         mov     cl, [unshift.Alpha]
  1062.         shl     eax, cl
  1063.         stosb
  1064.  
  1065.         add     esi, [delta]
  1066.  
  1067.         pop     ecx
  1068.         dec     ecx
  1069.         jnz     .next_pixel
  1070.  
  1071.         pop     ecx
  1072.         dec     ecx
  1073.         jnz     .next_line
  1074.  
  1075. ;;------------------------------------------------------------------------------------------------;;
  1076.  
  1077.   .exit:
  1078.         xor     eax, eax
  1079.         pop     edi
  1080.         ret
  1081.  
  1082.   .error:
  1083.         or      eax, -1
  1084.         pop     edi
  1085.         ret
  1086.        
  1087. .calc_shift:
  1088.         xor     eax, eax
  1089.         or      ecx, ecx
  1090.         jnz     @f
  1091.         retn
  1092.     @@: test    ecx, 1
  1093.         jnz     @f
  1094.    .zz: shr     ecx, 1
  1095.         inc     eax
  1096.         jmp     @b
  1097.     @@: test    ecx, 0100000000b
  1098.         jnz     .zz
  1099.         retn
  1100. .calc_unshift:
  1101.         xor     eax, eax
  1102.         or      ecx, ecx
  1103.         jnz     @f
  1104.         retn
  1105.     @@: test    ecx, 1
  1106.         jz      @f
  1107.         shr     ecx, 1
  1108.         inc     eax
  1109.         jmp     @b
  1110.     @@: sub     eax, 8
  1111.         neg     eax
  1112.         retn
  1113. endp
  1114.  
  1115. if 0
  1116. ;;================================================================================================;;
  1117. proc img.decode.bmp._.jpeg ;//////////////////////////////////////////////////////////////////////;;
  1118. ;;------------------------------------------------------------------------------------------------;;
  1119. ;? --- TBD ---                                                                                    ;;
  1120. ;;------------------------------------------------------------------------------------------------;;
  1121. ;> ebx = raw image data                                                                           ;;
  1122. ;> edx = image data                                                                               ;;
  1123. ;;------------------------------------------------------------------------------------------------;;
  1124. ;< --- TBD ---                                                                                    ;;
  1125. ;;================================================================================================;;
  1126.         xor     eax, eax
  1127.         ret
  1128. endp
  1129.  
  1130. ;;================================================================================================;;
  1131. proc img.decode.bmp._.png ;///////////////////////////////////////////////////////////////////////;;
  1132. ;;------------------------------------------------------------------------------------------------;;
  1133. ;? --- TBD ---                                                                                    ;;
  1134. ;;------------------------------------------------------------------------------------------------;;
  1135. ;> ebx = raw image data                                                                           ;;
  1136. ;> edx = image data                                                                               ;;
  1137. ;;------------------------------------------------------------------------------------------------;;
  1138. ;< --- TBD ---                                                                                    ;;
  1139. ;;================================================================================================;;
  1140.         xor     eax, eax
  1141.         ret
  1142. endp
  1143. end if
  1144.  
  1145. ;;================================================================================================;;
  1146. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1147. ;;================================================================================================;;
  1148. ;! Below is private data you should never use directly from your code                             ;;
  1149. ;;================================================================================================;;
  1150. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1151. ;;================================================================================================;;
  1152.  
  1153.  
  1154. ;
  1155.