;;================================================================================================;; ;;//// tga.asm //// (c) Nable, 2007-2008 /////////////////////////////////////////////////////////;; ;;================================================================================================;; ;; ;; ;; This file is part of Common development libraries (Libs-Dev). ;; ;; ;; ;; Libs-Dev is free software: you can redistribute it and/or modify it under the terms of the GNU ;; ;; Lesser General Public License as published by the Free Software Foundation, either version 2.1 ;; ;; of the License, or (at your option) any later version. ;; ;; ;; ;; Libs-Dev is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ;; ;; even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; ;; Lesser General Public License for more details. ;; ;; ;; ;; You should have received a copy of the GNU Lesser General Public License along with Libs-Dev. ;; ;; If not, see . ;; ;; ;; ;;================================================================================================;; ;; ;; ;; References: ;; ;; 1. Hiview 1.2 by Mohammad A. REZAEI ;; ;; ;; ;;================================================================================================;; include 'tga.inc' ;;================================================================================================;; proc img.is.tga _data, _length ;//////////////////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; ;? Determine if raw data could be decoded (is in Targa format) ;; ;;------------------------------------------------------------------------------------------------;; ;> _data = raw data as read from file/stream ;; ;> _length = data length ;; ;;------------------------------------------------------------------------------------------------;; ;< eax = false / true ;; ;;================================================================================================;; cmp [_length], 18 jbe .nope mov eax, [_data] push ebx mov ebx,[eax+1] ;bl=cmatype,bh=subtype cmp bl,1 ;cmatype is in [0..1] ja .nope cmp bh,11 ;subtype is in [1..3] (non-rle) or in [9..11] (rle) ja .nope cmp bh,9 jae .cont1 cmp bh,3 ja .nope .cont1: ;continue testing mov ebx,[eax+16] ;bl=bpp, bh=flags //image descriptor test ebx,111b ;bpp must be 8, 15, 16, 24 or 32 jnz .maybe15 shr bl,3 cmp bl,4 ja .nope jmp .cont2 .maybe15: cmp bl,15 jne .nope .cont2: ;continue testing test bh,tga.flags.interlace_type ;deinterlacing is not supported yet jnz .nope cmp byte[eax+7],24 ;test palette bpp - only 24 and 32 are supported je .yep cmp byte[eax+7],32 ;test palette bpp - only 24 and 32 are supported je .yep .nope: xor eax, eax pop ebx ret .yep: xor eax, eax inc eax pop ebx ret endp ;;================================================================================================;; proc img.decode.tga _data, _length, _options ;////////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; ;? Decode data into image if it contains correctly formed raw data in Targa format ;; ;;------------------------------------------------------------------------------------------------;; ;> _data = raw data as read from file/stream ;; ;> _length = data length ;; ;;------------------------------------------------------------------------------------------------;; ;< eax = 0 (error) or pointer to image ;; ;;================================================================================================;; locals IMGwidth dd ? IMGheight dd ? IMGbpp dd ? DupPixelCount dd ? TgaBlockCount dd ? endl pushad cld ;paranoia and [DupPixelCount],0 ;prepare variables and [TgaBlockCount],0 ;prepare variables mov eax,[_data] movzx esi,byte[eax] lea esi,[esi+eax+18] ;skip comment and header mov ebx,[eax+12] movzx ecx,bx ;ecx=width shr ebx,16 ;ebx=height mov [IMGwidth],ecx mov [IMGheight],ebx movzx edx,byte[eax+16] cmp edx,16 jnz @f dec edx ;16bpp tga images are really 15bpp ARGB @@: sub edx, 16 - Image.bpp16 ; 15 -> Image.bpp15, 16 -> Image.bpp16 mov [IMGbpp],edx stdcall img.create,ecx,ebx,edx mov [esp+28],eax ;save return value test eax,eax ;failed to allocate? jz .locret ;then exit cmp edx,8 jne .palette_parsed mov edi,[eax+Image.Palette] mov ecx,[_data] cmp byte[ecx+2],3 ;we also have grayscale subtype jz .write_grayscale_palette ;that don't hold palette in file cmp byte[ecx+2],11 jz .write_grayscale_palette mov dh,[ecx+7] ;size of colormap entries in bits movzx ecx,word[ecx+5] ;number of colormap entries cmp dh,24 jz .skip_24bpp_palette ;test if colormap entries are 24bpp rep movsd ;else they are 32 bpp jmp .palette_parsed .write_grayscale_palette: push eax mov ecx,0x100 xor eax,eax @@: stosd add eax,0x010101 loop @b pop eax jmp .palette_parsed .skip_24bpp_palette: push eax @@: lodsd dec esi and eax,0xFFFFFF ; bswap eax ; shr eax,8 stosd loop @b pop eax .palette_parsed: mov edi,[eax+Image.Data] imul ebx,[IMGwidth] ;ebx=width*height mov edx,[IMGbpp] add edx,7 shr edx,3 ;edx=bytes per pixel mov dh,dl ;dh=dl=bytes per pixel mov eax,[_data] cmp byte[eax+2],9 jb .not_an_rle .tga_read_rle_pixel: cmp [DupPixelCount],0 ;Duplicate previously read pixel? jg .duplicate_previously_read_pixel dec [TgaBlockCount] ;Decrement pixels remaining in block jns .read_non_rle_pixel xor eax,eax lodsb test al,al ;Start of duplicate-pixel block? jns .2 and al,0x7f mov [DupPixelCount],eax ;Number of duplications after this one and [TgaBlockCount],0 ;Then read new block header jmp .read_non_rle_pixel .2: mov dword[TgaBlockCount],eax .read_non_rle_pixel: xor eax,eax mov dl,dh @@: shl eax,8 lodsb dec dl jnz @b cmp dh,3 jne .put_pixel bswap eax shr eax,8 jmp .put_pixel .duplicate_previously_read_pixel: dec [DupPixelCount] .put_pixel: mov dl,dh push eax @@: stosb shr eax,8 dec dl jnz @b pop eax dec ebx jnz .tga_read_rle_pixel jmp .locret .not_an_rle: movzx edx,dl ;dh contains bpp too (for decoding needs) imul edx,ebx mov ecx,edx rep movsb ;just copy the image .locret: popad ret endp ;;================================================================================================;; proc img.encode.tga _img, _p_length, _options ;///////////////////////////////////////////////////;; ;;------------------------------------------------------------------------------------------------;; ;? Encode image into raw data in Targa format ;; ;;------------------------------------------------------------------------------------------------;; ;> _img = pointer to image ;; ;;------------------------------------------------------------------------------------------------;; ;< eax = 0 (error) or pointer to encoded data ;; ;< _p_length = encoded data length ;; ;;================================================================================================;; xor eax, eax ret endp ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;================================================================================================;; ;! Below are private procs you should never call directly from your code ;; ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;================================================================================================;; ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;================================================================================================;; ;! Below is private data you should never use directly from your code ;; ;;================================================================================================;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;================================================================================================;; ;