libimg: pcx: unpack scanlines, not color planes

git-svn-id: svn://kolibrios.org@3499 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Ivan Baravy 2013-05-10 12:28:39 +00:00
parent b3ade66ab3
commit a524093376
6 changed files with 507 additions and 130 deletions

View File

@ -45,6 +45,7 @@ include 'xcf/xcf.asm'
include 'tiff/tiff.asm'
include 'pnm/pnm.asm'
include 'wbmp/wbmp.asm'
include 'xbm/xbm.asm'
include 'scale.asm'
include 'convert.asm'
@ -1926,6 +1927,7 @@ img.formats_table:
.tiff dd LIBIMG_FORMAT_TIFF, img.is.tiff, img.decode.tiff, img.encode.tiff,0
.pnm dd LIBIMG_FORMAT_PNM, img.is.pnm, img.decode.pnm, img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8g) + (1 SHL Image.bpp24)
.wbmp dd LIBIMG_FORMAT_WBMP, img.is.wbmp, img.decode.wbmp, img.encode.wbmp,0
.xbm dd LIBIMG_FORMAT_XBM, img.is.xbm, img.decode.xbm, img.encode.xbm, 0
.z80 dd LIBIMG_FORMAT_Z80, img.is.z80, img.decode.z80, img.encode.z80, 0 ;this must be the last entry as there are no signatures in z80 screens at all
dd 0
@ -2161,7 +2163,7 @@ img._.get_scanline_len: ;///////////////////////////////////////////////////////
;;================================================================================================;;
align 4
type2bpp dd 8, 24, 32, 15, 16, 1, 9 ;,16
type2bpp dd 8, 24, 32, 15, 16, 1, 9;, 2, 4
img._.do_rgb.handlers:
dd img._.do_rgb.bpp8i
dd img._.do_rgb.bpp24

View File

@ -30,7 +30,8 @@ LIBIMG_FORMAT_XCF = 9
LIBIMG_FORMAT_TIFF = 10
LIBIMG_FORMAT_PNM = 11
LIBIMG_FORMAT_WBMP = 12
LIBIMG_FORMAT_Z80 = 13
LIBIMG_FORMAT_XBM = 13
LIBIMG_FORMAT_Z80 = 14
; scale type ; corresponding img.scale params
LIBIMG_SCALE_INTEGER = 1 ; scale factor ; reserved 0
@ -78,14 +79,14 @@ struct FormatsTableEntry
ends
struct Image
Checksum dd ? ; ((Width ROL 16) OR Height) XOR Data[0]
Checksum dd ? ; ((Width ROL 16) OR Height) XOR Data[0] ; ignored so far
Width dd ?
Height dd ?
Next dd ?
Previous dd ?
Type dd ? ; one of Image.bppN
Data dd ?
Palette dd ? ; used iff Type eq Image.bpp8 or Image.bpp1
Palette dd ? ; used iff Type eq Image.bpp1, Image.bpp2, Image.bpp4 or Image.bpp8i
Extended dd ?
Flags dd ? ; bitfield
Delay dd ? ; used iff Image.IsAnimated is set in Flags
@ -101,8 +102,8 @@ Image.bpp16 = 5
Image.bpp1 = 6
Image.bpp8g = 7 ; grayscale
Image.bpp8a = 8 ; grayscale with alpha channel; application layer only!!! kernel doesn't handle this image type, libimg can only create and destroy such images
;Image.bpp4 = 9
;Image.bpp2 = 10
;Image.bpp2 = 9
;Image.bpp4 = 10
; bits in Image.Flags
Image.IsAnimated = 1

View File

@ -1,5 +1,5 @@
;;================================================================================================;;
;;//// pcx.asm //// (c) dunkaist, 2010,2012 //////////////////////////////////////////////////////;;
;;//// pcx.asm //// (c) dunkaist, 2010,2012-2013 /////////////////////////////////////////////////;;
;;================================================================================================;;
;; ;;
;; This file is part of Common development libraries (Libs-Dev). ;;
@ -30,33 +30,27 @@ proc img.is.pcx _data, _length ;////////////////////////////////////////////////
;< eax = false / true ;;
;;================================================================================================;;
push ecx edi
push edi
xor eax, eax
mov edi, [_data]
cmp byte[edi + pcx_header.magic_number], 0x0A
jne .is_not_pcx
cmp byte[edi + pcx_header.version], 5
jne .is_not_pcx
cmp byte[edi + pcx_header.encoding], 1
mov ecx, [edi]
shl ecx, 8
cmp ecx, 0x01050a00
jne .is_not_pcx
cmp byte[edi + pcx_header.reserved], 0
jne .is_not_pcx
add edi, pcx_header.filler
xor al, al
mov ecx, 58
cld
repe scasb
test ecx, ecx
jnz .is_not_pcx
mov ecx, 58/2
repe scasw
jne .is_not_pcx
.is_pcx:
inc eax
.is_not_pcx:
pop edi ecx
pop edi
ret
endp
@ -72,12 +66,13 @@ proc img.decode.pcx _data, _length, _options ;//////////////////////////////////
;< eax = 0 (error) or pointer to image ;;
;;================================================================================================;;
locals
nplanes rd 1
xsize rd 1
ysize rd 1
bpl rd 1
total_bpl rd 1
num_planes rd 1
width rd 1
height rd 1
bp_plane rd 1
bp_scanline rd 1
line_begin rd 1
cur_scanline rd 1
retvalue rd 1 ; 0 (error) or pointer to image
endl
@ -85,21 +80,21 @@ endl
mov esi, [_data]
movzx eax, byte[esi + pcx_header.nplanes]
mov [nplanes], eax
mov [num_planes], eax
movzx ebx, word[esi + pcx_header.bpl]
mov [bpl], ebx
mov [bp_plane], ebx
imul eax, ebx
mov [total_bpl], eax
mov [bp_scanline], eax
movzx eax, word[esi + pcx_header.xmax]
sub ax, word[esi + pcx_header.xmin]
inc eax
mov [xsize], eax
mov [width], eax
movzx ebx, word[esi + pcx_header.ymax]
sub bx, word[esi + pcx_header.ymin]
inc ebx
mov [ysize], ebx
mov [height], ebx
cmp [esi + pcx_header.bpp], 1
jz .monochrome
@ -108,56 +103,36 @@ endl
.24bit:
stdcall img.create, [bp_plane], 1, Image.bpp24
mov [cur_scanline], eax
test eax, eax
jz .quit
stdcall img.create, eax, ebx, Image.bpp24
stdcall img.create, [width], [height], Image.bpp24
mov [retvalue], eax
test eax, eax
jz .quit
mov esi, [_data]
add esi, 128 ; skip header
mov edi, [eax + Image.Data]
add edi, 2
mov [line_begin], edi
add esi, sizeof.pcx_header
mov edx, [eax + Image.Data]
.24bit.scanline:
mov ebx, [total_bpl]
.24bit.color_line:
mov edx, [bpl]
.24bit.next_byte:
mov edi, [cur_scanline]
mov ebx, [bp_scanline]
@@:
call pcx._.get_byte
sub edx, ecx
@@:
mov [edi], al
add edi, [nplanes]
dec ecx
jnz @b
test edx, edx
jnz .24bit.next_byte
.24bit.end_color_line:
test ebx, ebx
jz .24bit.end_full_line
dec [line_begin]
mov edi, [line_begin]
jmp .24bit.color_line
.24bit.end_full_line:
dec [ysize]
jz .quit
add edi, 2
bt [xsize], 0
jnc @f
sub edi, 3
@@:
mov [line_begin], edi
jmp .24bit.scanline
rep stosb
test ebx, ebx
jnz @b
stdcall pcx._.scanline_unpack, [width], [cur_scanline], [num_planes]
dec [height]
jnz .24bit.scanline
jmp .quit
.indexed:
stdcall img.create, eax, ebx, Image.bpp8i
stdcall img.create, [width], [height], Image.bpp8i
mov [retvalue], eax
test eax, eax
jz .quit
@ -165,42 +140,40 @@ endl
mov ebx, eax
mov esi, [_data]
add esi, [_length]
sub esi, 768
sub esi, 256*3 ; rgb triplets
mov edi, [eax + Image.Palette]
mov ecx, 256
xor eax, eax
mov eax, 0x0000ff00
@@:
lodsw
xchg al, ah
shl eax, 8
lodsb
stosd
mov al, [esi + 0]
mov [edi + 2], ax
mov al, [esi + 1]
mov [edi + 1], al
mov al, [esi + 2]
mov [edi + 0], al
add esi, 3
add edi, 4
dec ecx
jnz @b
mov esi, [_data]
add esi, 128
add esi, sizeof.pcx_header
mov edi, [ebx + Image.Data]
.indexed.line:
mov ebx, [total_bpl]
.indexed.next_byte:
call pcx._.get_byte
.indexed.scanline:
mov ebx, [bp_scanline]
@@:
stosb
dec ecx
jnz @b
call pcx._.get_byte
rep stosb
test ebx, ebx
jnz .indexed.next_byte
dec [ysize]
jnz .indexed.line
jnz @b
dec [height]
jnz .indexed.scanline
jmp .quit
.monochrome:
stdcall img.create, eax, ebx, Image.bpp1
stdcall img.create, [width], [height], Image.bpp1
mov [retvalue], eax
test eax, eax
jz .quit
@ -210,25 +183,20 @@ endl
mov [edi + 4], dword 0xffffffff
mov esi, [_data]
add esi, 128
add esi, sizeof.pcx_header
mov edi, [eax + Image.Data]
.monochrome.line:
mov ebx, [total_bpl]
.monochrome.next_byte:
call pcx._.get_byte
.monochrome.scanline:
mov ebx, [bp_scanline]
@@:
stosb
dec ecx
jnz @b
call pcx._.get_byte
rep stosb
test ebx, ebx
jnz .monochrome.next_byte
dec [ysize]
jnz .monochrome.line
jnz @b
dec [height]
jnz .monochrome.scanline
; jmp .quit
.quit:
popa
mov eax, [retvalue]
@ -262,20 +230,47 @@ endp
;;================================================================================================;;
proc pcx._.get_byte
xor ecx, ecx
mov ecx, 1
xor eax, eax
lodsb
cmp al, 0xC0
setb cl
jb .done
and al, 0x3F
mov cl, al
cmp eax, 0xc0
jb @f
and eax, 0x3f
mov ecx, eax
lodsb
.done:
@@:
sub ebx, ecx
ret
endp
proc pcx._.scanline_unpack _width, _scanline, _num_planes
push esi
mov esi, [_scanline]
mov ebx, [_num_planes]
dec ebx
.plane:
mov ecx, [_width]
mov edi, edx
add edi, ebx
@@:
mov al, [esi]
mov [edi], al
add esi, 1
add edi, [_num_planes]
dec ecx
jnz @b
bt dword[_width], 0
adc esi, 0
dec ebx
jns .plane
mov edx, edi
pop esi
ret
endp
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;

View File

@ -193,21 +193,25 @@ endl
push esi ; fixme!!
mov ecx, [edx + Image.Type]
dec ecx
jz .bpp8i
dec ecx
jz .bpp24
dec ecx
jz .bpp32
dec ecx
dec ecx ; tiff doesn't handle 15bpp images
jz .bpp16
dec ecx
jz .bpp1
dec ecx
jz .bpp8g
dec ecx
jz .bpp8a
cmp ecx, Image.bpp8i
je .bpp8i
cmp ecx, Image.bpp24
je .bpp24
cmp ecx, Image.bpp32
je .bpp32
cmp ecx, Image.bpp16
je .bpp16
cmp ecx, Image.bpp1
je .bpp1
cmp ecx, Image.bpp8g
je .bpp8g
cmp ecx, Image.bpp8a
je .bpp8a
; cmp ecx, Image.bpp2
; je .bpp2
; cmp ecx, Image.bpp4
; je .bpp4
jmp .quit
;error report!!
.bpp1:
@ -224,6 +228,9 @@ endl
mov [edi + 4], dword 0x00000000
jmp .common
.bpp2:
jmp .common
.bpp4:
jmp .common
@ -351,6 +358,9 @@ endl
.decoded:
cmp [ebx + tiff_extra.planar_configuration], TIFF.PLANAR.PLANAR
jne .post.rgb_bgr
stdcall tiff._.planar_to_separate, [retvalue]
.post.rgb_bgr:
cmp [ebx + tiff_extra.samples_per_pixel], 3
jne .post.rgba_bgra
@ -617,6 +627,21 @@ proc tiff._.parse_IFDE _data, _endianness
mov [ebx + tiff_extra.strip_byte_counts], eax
jmp .quit
.tag_11c: ; Planar configuration
cmp ax, TIFF.IFDE_TYPE.SHORT
jne @f
lodsd
xor eax, eax
lodsw_
mov [ebx + tiff_extra.planar_configuration], eax
;debug_print 'planar_configuration: '
;debug_print_dec eax
;newline
lodsw
@@:
jmp .quit
.tag_13d: ; Predictor
cmp ax, TIFF.IFDE_TYPE.SHORT
jne @f
@ -710,17 +735,16 @@ endp
proc tiff._.decompress.packbits _image
push ebx ecx edx esi
push edx
mov edx, ecx
.decode:
lodsb
dec edx
cmp al, 0x7f
jbe .different
cmp al, 0x80
jne .identical
jb .different
jg .identical
test edx, edx
jz .quit
jmp .decode
@ -745,7 +769,7 @@ proc tiff._.decompress.packbits _image
jnz .decode
.quit:
pop esi edx ecx ebx
pop edx
ret
endp
@ -1167,6 +1191,75 @@ proc tiff._.pack_8a _img
ret
endp
proc tiff._.planar_to_separate _img
locals
pixels rd 1
tmp_image rd 1
channels rd 1
channel_padding rd 1
endl
pushad
mov ebx, [_img]
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
mov [pixels], ecx
cmp [ebx + Image.Type], Image.bpp24
je .bpp24
cmp [ebx + Image.Type], Image.bpp32
je .bpp32
; cmp [ebx + Image.Type], Image.bpp4
; je .bpp4
jmp .quit
.bpp24:
mov [channels], 3
mov [channel_padding], 2
lea eax, [ecx*3]
jmp .proceed
.bpp32:
mov [channels], 4
mov [channel_padding], 3
shl eax, 2
jmp .proceed
.bpp4:
mov [channels], 3
mov [channel_padding], 2
shr eax, 1
jmp .proceed
.proceed:
invoke mem.alloc, eax
test eax, eax
jz .quit
mov [tmp_image], eax
.channel:
mov esi, [ebx + Image.Data]
mov edi, [tmp_image]
mov ecx, [pixels]
mov eax, [channel_padding]
inc eax
sub eax, [channels]
add edi, eax
mov eax, [channels]
dec eax
imul eax, [pixels]
add esi, eax
@@:
lodsb
stosb
add edi, [channel_padding]
dec ecx
jnz @b
dec [channels]
jnz .channel
.quit:
mov eax, [tmp_image]
xchg [ebx + Image.Data], eax
invoke mem.free, eax
popad
ret
endp
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
@ -1184,6 +1277,7 @@ tiff.IFDE_tag_table.begin:
.tag_115: dd 0x0115, tiff._.parse_IFDE.tag_115 ; samples per pixel
.tag_116: dd 0x0116, tiff._.parse_IFDE.tag_116 ; rows per strip
.tag_117: dd 0x0117, tiff._.parse_IFDE.tag_117 ; strip byte counts
.tag_11c: dd 0x011c, tiff._.parse_IFDE.tag_11c ; planar configuration
.tag_13d: dd 0x013d, tiff._.parse_IFDE.tag_13d ; predictor
.tag_140: dd 0x0140, tiff._.parse_IFDE.tag_140 ; color map
.tag_152: dd 0x0152, tiff._.parse_IFDE.tag_152 ; extra samples

View File

@ -23,6 +23,7 @@ struct tiff_header
first_IFD rd 1
ends
struct tiff_extra
image_width rd 1 ; SHORT or LONG
image_height rd 1 ; SHORT or LONG
@ -38,6 +39,7 @@ struct tiff_extra
strip_byte_counts_length rd 1
palette rd 1 ; SHORT
palette_size rd 1 ; in colors, not samples
planar_configuration rd 1 ; SHORT
extra_samples rd 1 ; pointer to array of SHORTs
extra_samples_number rd 1
predictor rd 1 ; SHORT
@ -87,6 +89,9 @@ TIFF.PHOTOMETRIC.CMYK = 5
TIFF.PHOTOMETRIC.YCbCr = 6
TIFF.PHOTOMETRIC.CIELAB = 8
TIFF.PLANAR.CHUNKY = 1
TIFF.PLANAR.PLANAR = 2
macro lodsw_
{

View File

@ -0,0 +1,280 @@
;;================================================================================================;;
;;//// xbm.asm //// (c) dunkaist, 2013 ///////////////////////////////////////////////////////////;;
;;================================================================================================;;
;; ;;
;; 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 <http://www.gnu.org/licenses/>. ;;
;; ;;
;;================================================================================================;;
;;================================================================================================;;
proc img.is.xbm _data, _length ;//////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Determine if raw data could be decoded (is in xbm format) ;;
;;------------------------------------------------------------------------------------------------;;
;> _data = raw data as read from file/stream ;;
;> _length = data length ;;
;;------------------------------------------------------------------------------------------------;;
;< eax = false / true ;;
;;================================================================================================;;
push ebx ecx esi edi
xor eax, eax
mov edi, [_data]
mov ecx, 4 ; BOM
mov al, '#'
repne scasb
jne .is_not_xbm
dec edi
mov esi, str_define
mov ecx, str_define.size
repe cmpsb
jne .is_not_xbm
mov esi, edi
call xbm._.skip_whitespace
mov edx, esi
call xbm._.wait_whitespace
mov ebx, esi
sub ebx, edx
sub ebx, 5
cmp word[esi - 6], '_w'
jne .is_not_xbm
cmp dword[esi - 4], 'idth'
jne .is_not_xbm
call xbm._.skip_whitespace
call xbm._.wait_whitespace
call xbm._.skip_whitespace
mov edi, str_define
mov ecx, str_define.size
repe cmpsb
jne .is_not_xbm
call xbm._.skip_whitespace
mov edi, edx
mov ecx, ebx
repe cmpsb
jne .is_not_xbm
cmp dword[esi], 'heig'
jne .is_not_xbm
cmp word[esi + 4], 'ht'
jne .is_not_xbm
.is_xbm:
pop edi esi ecx ebx
xor eax, eax
inc eax
ret
.is_not_xbm:
pop edi esi ecx ebx
xor eax, eax
ret
endp
;;================================================================================================;;
proc img.decode.xbm _data, _length, _options ;////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Decode data into image if it contains correctly formed raw data in xbm format ;;
;;------------------------------------------------------------------------------------------------;;
;> _data = raw data as read from file/stream ;;
;> _length = data length ;;
;;------------------------------------------------------------------------------------------------;;
;< eax = 0 (error) or pointer to image ;;
;;================================================================================================;;
locals
width rd 1
height rd 1
counter rd 1
retvalue rd 1 ; 0 (error) or pointer to image
endl
pusha
mov esi, [_data]
add esi, 5
call xbm._.wait_whitespace
call xbm._.skip_whitespace
call xbm._.wait_whitespace
call xbm._.skip_whitespace
call xbm._.read_number
mov [width], eax
call xbm._.skip_whitespace
call xbm._.wait_whitespace
call xbm._.skip_whitespace
call xbm._.wait_whitespace
call xbm._.skip_whitespace
call xbm._.read_number
mov [height], eax
stdcall img.create, [width], [height], Image.bpp1
test eax, eax
jz .quit
mov [retvalue], eax
mov edi, [_data]
mov ecx, [_length]
mov eax, '{'
repne scasb
mov esi, edi
mov ebx, [retvalue]
mov eax, [ebx + Image.Palette]
mov dword[eax], 0xffffffff
mov dword[eax + 4], 0xff000000
mov ecx, [ebx + Image.Width]
add ecx, 7
shr ecx, 3
imul ecx, [ebx + Image.Height]
mov [counter], ecx
mov edi, [ebx + Image.Data]
@@:
call xbm._.skip_whitespace
call xbm._.read_number
mov cl, al
and eax, 0x0f
mov al, byte[reverse_bits + eax]
shl eax, 4
mov edx, eax
mov al, cl
shr eax, 4
mov al, byte[reverse_bits + eax]
or eax, edx
mov byte[edi], al
add edi, 1
sub [counter], 1
jnz @b
.quit:
popa
mov eax, [retvalue]
ret
endp
;;================================================================================================;;
proc img.encode.xbm _img, _common, _specific ;////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Encode image into raw data in xbm format ;;
;;------------------------------------------------------------------------------------------------;;
;> [_img] = pointer to image ;;
;> [_common] = format independent options ;;
;> [_specific] = 0 / pointer to the structure of format specific options ;;
;;------------------------------------------------------------------------------------------------;;
;< eax = 0 / pointer to encoded data ;;
;< ecx = error code / the size of encoded data ;;
;;================================================================================================;;
xor eax, eax
ret
endp
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
;! Below are private procs you should never call directly from your code ;;
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
proc xbm._.skip_whitespace
.next_byte:
movzx eax, byte[esi]
cmp eax, 0x20
jne @f
add esi, 1
jmp .next_byte
@@:
cmp eax, 0x09
jne @f
add esi, 1
jmp .next_byte
@@:
cmp eax, 0x0a
jne @f
add esi, 1
jmp .next_byte
@@:
ret
endp
proc xbm._.wait_whitespace
@@:
movzx eax, byte[esi]
cmp eax, 0x20
je @f
cmp eax, 0x09
je @f
cmp eax, 0x0a
je @f
add esi, 1
jmp @b
@@:
ret
endp
proc xbm._.read_number
xor eax, eax
mov ecx, eax
mov al, byte[esi]
add esi, 1
sub al, 0x30
test al, al
jz .octal_or_hex
.decimal:
mov ebx, 10
imul ecx, ebx
add ecx, eax
mov al, byte[esi]
add esi, 1
sub al, 0x30
cmp al, 10
jb .decimal
jmp .done
.octal_or_hex:
mov al, byte[esi]
add esi, 1
sub al, 0x30
cmp al, 'x' - 0x30
je .hex
.octal:
jmp .done
.hex:
mov al, byte[esi]
add esi, 1
sub al, 0x30
jc .done
cmp al, 9
jna @f
sub al, 0x30 - 9
jc .done
cmp al, 15
ja .done
@@:
shl ecx, 4
add ecx, eax
jmp .hex
.done:
mov eax, ecx
ret
endp
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
;! Below is private data you should never use directly from your code ;;
;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;;
reverse_bits db 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
sz str_define , '#define'
sz str__width , '_width'
sz str__height , '_height'