0,0 → 1,1573 |
;;================================================================================================;; |
;;//// xcf.asm //// (c) dunkaist, 2011 ///////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;; ;; |
;; 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/>. ;; |
;; ;; |
;;================================================================================================;; |
;; ;; |
;; References: ;; |
;; 1. "SPECIFICATION OF THE XCF FILE FORMAT" ;; |
;; by Henning Makholm ;; |
;; http://svn.gnome.org/viewvc/gimp/trunk/devel-docs/xcf.txt?view=markup ;; |
;; 2. "Layer Modes" ;; |
;; from docs.gimp.org ;; |
;; http://docs.gimp.org/en/gimp-concepts-layer-modes.html ;; |
;; ;; |
;;================================================================================================;; |
include 'xcf.inc' |
;include '../../../../system/board/trunk/debug.inc' |
|
COMPOSITE_MODE equ MMX |
|
MAX_LAYERS equ 255 |
|
DEBUG_STANDARD equ TRUE |
DEBUG_FBOUNDS equ FALSE |
|
;;================================================================================================;; |
proc img.is.xcf _data, _length ;//////////////////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Determine if raw data could be decoded (is in xcf format) ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = false / true ;; |
;;================================================================================================;; |
|
push edi |
xor eax, eax |
|
mov edi, [_data] |
|
cmp dword[edi+xcf_header.magic_string], 'gimp' |
jne .is_not_xcf |
cmp dword[edi+xcf_header.magic_string+4], ' xcf' |
jne .is_not_xcf |
|
cmp [edi+xcf_header.version], 'file' |
je @f |
cmp [edi+xcf_header.version], 'v001' |
je @f |
cmp [edi+xcf_header.version], 'v002' |
je @f |
jmp .is_not_xcf |
@@: |
|
cmp byte[edi+xcf_header.reserved], 0 |
jne .is_not_xcf |
|
.is_xcf: |
inc eax |
|
.is_not_xcf: |
pop edi |
ret |
|
endp |
|
;;================================================================================================;; |
proc img.decode.xcf _data, _length, _options ;////////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Decode data into image if it contains correctly formed raw data in xcf format ;; |
;;------------------------------------------------------------------------------------------------;; |
;> _data = raw data as read from file/stream ;; |
;> _length = data length ;; |
;;------------------------------------------------------------------------------------------------;; |
;< eax = 0 (error) or pointer to image ;; |
;;================================================================================================;; |
locals |
count rd 1 |
retvalue rd 1 ; 0 (error) or pointer to image |
endl |
|
push ebx esi edi |
|
mov esi, [_data] |
add esi, xcf_header.width |
|
lodsd |
bswap eax |
mov ebx, eax |
lodsd |
bswap eax |
mov edx, eax |
|
lodsd |
bswap eax |
test eax, eax |
jz .process_rgb |
dec eax |
jz .process_grayscale |
dec eax |
jz .process_indexed |
jmp .error |
|
|
.process_rgb: |
|
stdcall img.create, ebx, edx, Image.bpp32 |
mov [retvalue], eax |
test eax, eax |
jz .error |
|
mov ebx, eax |
|
mov edx, XCF_BASETYPE_RGB |
|
jmp .common_process |
|
.process_grayscale: |
|
stdcall img.create, ebx, edx, Image.bpp8 |
mov [retvalue], eax |
test eax, eax |
jz .error |
|
mov ebx, eax |
|
mov eax, [ebx + Image.Width] |
imul [ebx + Image.Height] |
shl eax, 1 |
mov [ebx+Image.Palette], eax |
add eax, 256*4 |
invoke mem.realloc, [ebx + Image.Data], eax |
mov [ebx + Image.Data], eax |
add [ebx + Image.Palette], eax |
|
mov edi, [ebx+Image.Palette] |
mov eax, 0xff000000 |
@@: stosd |
add eax, 0x00010101 |
jnc @b |
|
mov edx, XCF_BASETYPE_GRAY |
|
jmp .common_process |
|
|
.process_indexed: |
|
stdcall img.create, ebx, edx, Image.bpp8 |
mov [retvalue], eax |
test eax, eax |
jz .error |
|
mov ebx, eax |
|
mov eax, [ebx + Image.Width] |
imul [ebx + Image.Height] |
shl eax, 1 |
mov [ebx+Image.Palette], eax |
add eax, 256*4 |
invoke mem.realloc, [ebx + Image.Data], eax |
mov [ebx + Image.Data], eax |
add [ebx + Image.Palette], eax |
|
mov edx, XCF_BASETYPE_INDEXED |
; jmp .common_process |
|
.common_process: |
|
invoke mem.alloc, sizeof.xcf_ext |
or eax, eax |
jz .error |
mov [ebx+Image.Extended], eax |
mov [eax+xcf_ext.opacity], 0xffffffff |
mov [eax+xcf_ext.type], edx |
|
stdcall parse_properties, ebx |
|
mov edi, esi |
mov eax, 0 |
mov ecx, MAX_LAYERS |
mov [count], MAX_LAYERS-1 |
repne scasd |
sub [count], ecx |
mov esi, edi |
mov ecx, 0 |
|
.still: sub esi, 8 |
lodsd |
bswap eax |
|
push ecx |
stdcall decode_layer, eax, [_data] |
pop ecx |
test eax, eax |
jz @f |
push ecx |
stdcall merge_down, eax, [retvalue], ecx |
pop ecx |
add ecx, 1 |
@@: dec [count] |
jnz .still |
; jmp .quit |
|
|
cmp [ebx+Image.Type], Image.bpp8 |
jne .quit |
stdcall pack_8a, ebx |
jmp .quit |
|
.error: mov [retvalue], 0 |
.quit: pop edi esi ebx |
mov eax, [retvalue] |
ret |
endp |
|
|
|
;;================================================================================================;; |
proc img.encode.xcf _img, _p_length, _options ;///////////////////////////////////////////////////;; |
;;------------------------------------------------------------------------------------------------;; |
;? Encode image into raw data in xcf 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 ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
proc parse_properties _img |
|
mov ebx, [_img] |
.begin: |
lodsd |
bswap eax |
|
mov ecx, (xcf_prop_table_end-xcf_prop_table_begin)/8 |
mov edi, xcf_prop_table_begin |
|
.still: |
cmp eax, [edi] |
jne @f |
jmp dword[edi+4] |
@@: |
add edi, 8 |
dec ecx |
jnz .still |
lodsd ; skip |
bswap eax ; uninteresting |
add esi, eax ; property |
jmp .begin |
|
parse_prop_00: ; PROP_END |
lodsd |
ret |
|
parse_prop_01: ; PROP_COLORMAP |
lodsd |
mov ecx, [ebx+Image.Extended] |
cmp [ecx+xcf_ext.type], XCF_BASETYPE_INDEXED |
je @f |
bswap eax |
add esi, eax |
jmp parse_properties.begin |
@@: |
lodsd |
bswap eax |
mov ecx, eax |
mov edi, [ebx+Image.Palette] |
|
@@: lodsd |
sub esi, 1 |
bswap eax |
shr eax, 8 |
or eax, 0xff000000 |
stosd |
dec ecx |
jnz @b |
jmp parse_properties.begin |
|
parse_prop_06: ; PROP_OPACITY |
lodsd |
lodsd |
bswap eax |
mov ecx, [ebx+Image.Extended] |
mov [ecx+xcf_ext.opacity], eax |
jmp parse_properties.begin |
|
parse_prop_07: ; PROP_MODE |
lodsd |
lodsd |
bswap eax |
mov ecx, [ebx+Image.Extended] |
mov [ecx+xcf_ext.layer_mode], eax |
jmp parse_properties.begin |
|
parse_prop_08: ; PROP_VISIBLE |
lodsd |
lodsd |
bswap eax |
mov ecx, [ebx+Image.Extended] |
mov [ecx+xcf_ext.visible], eax |
jmp parse_properties.begin |
|
parse_prop_11: ; PROP_APPLY_MASK |
lodsd |
lodsd |
bswap eax |
mov ecx, [ebx+Image.Extended] |
mov [ecx+xcf_ext.apply_mask], eax |
jmp parse_properties.begin |
|
parse_prop_15: ; PROP_OFFSETS |
lodsd |
lodsd |
mov ecx, [ebx+Image.Extended] |
bswap eax |
mov [ecx+xcf_ext.offset_x], eax |
lodsd |
bswap eax |
mov [ecx+xcf_ext.offset_y], eax |
jmp parse_properties.begin |
endp |
|
|
proc decode_channel _channel_begin, _data |
locals |
channel_width rd 1 |
channel_height rd 1 |
planes_todo rd 1 |
total_bpl rd 1 |
endl |
|
push ebx esi edi |
mov esi, [_channel_begin] |
add esi, [_data] |
lodsd |
bswap eax |
mov [channel_width], eax |
mov [total_bpl], eax |
lodsd |
bswap eax |
mov [channel_height], eax |
lodsd |
bswap eax |
add esi, eax |
|
stdcall img.create, [channel_width], [channel_height], Image.bpp8 |
mov ebx, eax |
test ebx, ebx |
jz .quit |
invoke mem.alloc, sizeof.xcf_ext |
or eax, eax |
jz .error |
mov [ebx+Image.Extended], eax |
|
stdcall parse_properties, ebx |
|
lodsd |
bswap eax |
mov esi, eax |
add esi, [_data] |
lodsd |
lodsd |
lodsd |
bswap eax |
mov [planes_todo], eax |
lodsd |
bswap eax |
mov esi, eax |
add esi, [_data] |
lodsd |
lodsd |
|
mov edi, [ebx+Image.Data] |
mov ecx, 0 |
@@: lodsd |
test eax, eax |
jz .quit |
bswap eax |
add eax, [_data] |
stdcall decode_tile, eax, [channel_width], [channel_height], [total_bpl], [planes_todo], 1 |
add ecx, 1 |
jmp @b |
|
.error: stdcall img.destroy, ebx |
mov ebx, 0 |
.quit: mov eax, ebx |
pop edi esi ebx |
ret |
endp |
|
|
proc decode_layer _layer_begin, _data |
locals |
layer_width rd 1 |
layer_height rd 1 |
planes_todo rd 1 |
total_bpl rd 1 |
color_step rd 1 |
endl |
|
push ebx esi edi |
mov esi, [_layer_begin] |
add esi, [_data] |
lodsd |
bswap eax |
mov [layer_width], eax |
mov [total_bpl], eax |
shl [total_bpl], 1 |
lodsd |
bswap eax |
mov [layer_height], eax |
lodsd |
bswap eax |
mov edx, Image.bpp16 |
mov [color_step], 1 |
cmp eax, 2 |
jge @f |
mov [color_step], 3 |
mov edx, Image.bpp32 |
shl [total_bpl], 1 |
@@: stdcall img.create, [layer_width], [layer_height], edx |
mov ebx, eax |
test ebx, ebx |
jz .quit |
invoke mem.alloc, sizeof.xcf_ext |
or eax, eax |
jz .error |
mov [ebx+Image.Extended], eax |
|
lodsd |
bswap eax |
add esi, eax |
stdcall parse_properties, ebx |
mov edx, [ebx+Image.Extended] |
or [edx+xcf_ext.visible], 0 |
jz .unvisible |
|
lodsd |
bswap eax |
push esi |
mov esi, eax |
add esi, [_data] |
lodsd |
lodsd |
lodsd |
bswap eax |
mov [planes_todo], eax |
; mov ecx, [ebx+Image.Extended] |
; mov [ecx+xcf_ext.planes], eax |
lodsd |
bswap eax |
mov esi, eax |
add esi, [_data] |
lodsd |
lodsd |
|
mov edi, [ebx+Image.Data] |
mov ecx, 0 |
@@: lodsd |
test eax, eax |
jz @f |
bswap eax |
add eax, [_data] |
stdcall decode_tile, eax, [layer_width], [layer_height], [total_bpl], [planes_todo], 0 |
add ecx, 1 |
jmp @b |
@@: |
|
stdcall apply_opacity, ebx, [color_step] |
|
pop esi |
lodsd |
bswap eax |
test eax, eax |
jz .quit |
|
stdcall decode_channel, eax, [_data] |
test eax, eax |
jz .error |
|
mov edx, [ebx+Image.Extended] |
cmp [edx+xcf_ext.apply_mask], 0 |
je .quit |
|
stdcall apply_alpha_mask, ebx, eax, [color_step] |
jmp .quit |
|
.unvisible: |
.error: stdcall img.destroy, ebx |
mov ebx, 0 |
.quit: mov eax, ebx |
pop edi esi ebx |
ret |
endp |
|
|
proc decode_tile _tile_data, _width, _height, _total_bpl, _bytes_pp, _is_channel |
locals |
tile_x rd 1 |
tile_y rd 1 |
tile_width rd 1 |
tile_height rd 1 |
planes_todo rd 1 |
color_step rd 1 |
endl |
|
push ebx ecx edx esi edi |
pushd [_bytes_pp] |
popd [planes_todo] |
|
cmp [_is_channel], 1 |
je @f |
test [_bytes_pp], 0x01 |
jz @f |
add [_bytes_pp], 1 |
@@: |
mov ebx, [_bytes_pp] |
sub ebx, 1 |
mov [color_step], ebx |
|
mov esi, [_tile_data] |
mov eax, ecx |
mov ebx, [_width] |
dec ebx |
shr ebx, 6 |
inc ebx |
mov edx, 0 |
div bx |
mov [tile_x], edx |
mov [tile_y], eax |
|
mov [tile_width], 64 |
mov ebx, [_width] |
test ebx, 0x0000003F |
jz @f |
dec ebx |
shr ebx, 6 |
cmp ebx, [tile_x] |
jne @f |
mov ebx, [_width] |
and ebx, 0x0000003F |
mov [tile_width], ebx |
@@: |
|
mov [tile_height], 64 |
mov ebx, [_height] |
test ebx, 0x0000003F |
jz @f |
dec ebx |
shr ebx, 6 |
cmp ebx, [tile_y] |
jne @f |
mov ebx, [_height] |
and ebx, 0x0000003F |
mov [tile_height], ebx |
@@: |
|
|
mov eax, [_total_bpl] |
shl eax, 6 |
mul [tile_y] |
add edi, eax |
|
mov eax, [tile_x] |
shl eax, 6 |
imul eax, [_bytes_pp] |
add edi, eax |
|
cmp [_is_channel], 1 |
jne @f |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
jmp .quit |
@@: |
mov eax, [planes_todo] |
dec eax |
jz .p1 |
dec eax |
jz .p2 |
dec eax |
jz .p3 |
jmp .p4 |
.p1: |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
add edi, 1 |
stdcall fill_color, [tile_width], [tile_height], [_total_bpl], [_bytes_pp], [color_step] |
jmp .quit |
.p2: |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
add edi, 1 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
jmp .quit |
.p3: |
add edi, 2 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
sub edi, 1 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
sub edi, 1 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
add edi, 3 |
stdcall fill_color, [tile_width], [tile_height], [_total_bpl], [_bytes_pp], [color_step] |
jmp .quit |
.p4: |
add edi, 2 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
sub edi, 1 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
sub edi, 1 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
add edi, 3 |
stdcall decode_color, [tile_width], [tile_height], [color_step], [_total_bpl], [_bytes_pp] |
; jmp .quit |
|
.quit: pop edi esi edx ecx ebx |
ret |
endp |
|
|
proc fill_color _tile_width, _tile_height, _total_bpl, _bytes_pp, _color_step |
push ebx |
mov edx, [_color_step] |
mov ebx, [_total_bpl] |
mov eax, [_bytes_pp] |
mul byte[_tile_width] |
sub ebx, eax |
|
mov ch, byte[_tile_height] |
mov al, 0xff |
.still: mov cl, byte[_tile_width] |
@@: stosb |
add edi, edx |
dec cl |
jnz @b |
add edi, ebx |
dec ch |
jnz .still |
pop ebx |
ret |
endp |
|
|
proc decode_color _tile_width, _tile_height, _color_step, _total_bpl, _bytes_pp |
locals |
level_width rd 1 |
level_height rd 1 |
line_step rd 1 ; [_total_bpl]-[_tile_width]*[_bytes_pp] |
endl |
|
push edi |
|
mov ebx, [_total_bpl] |
movzx eax, byte[_bytes_pp] |
mul byte[_tile_width] |
sub ebx, eax |
mov [line_step], ebx |
mov ebx, [_tile_height] |
mov edx, [_tile_width] |
|
.decode:lodsb |
cmp al, 127 |
je .long_identical |
jb .short_identical |
test al, 0x7f |
jz .long_different |
jmp .short_different |
|
.short_identical: |
movzx ecx, al |
add ecx, 1 |
lodsb |
jmp .step1 |
.long_identical: |
mov ecx, 0 |
lodsw |
mov cx, ax |
xchg cl, ch |
lodsb |
.step1: cmp cx, dx |
je .step2 |
jl .step3 |
xchg cx, dx |
sub dx, cx |
sub bx, 1 |
@@: stosb |
add edi, [_color_step] |
loop @b |
mov cx, dx |
mov edx, [_tile_width] |
add edi, [line_step] |
jmp .step1 |
|
.step2: |
@@: stosb |
add edi, [_color_step] |
loop @b |
mov edx, [_tile_width] |
add edi, [line_step] |
dec bx |
jz .quit |
jmp .decode |
.step3: sub dx, cx |
@@: stosb |
add edi, [_color_step] |
loop @b |
jmp .decode |
|
|
.short_different: |
movzx ecx, al |
neg cx |
add cx, 256 |
jmp .step4 |
.long_different: |
mov ecx, 0 |
lodsb |
mov ch, al |
lodsb |
mov cl, al |
.step4: cmp cx, dx |
je .step5 |
jl .step6 |
xchg cx, dx |
sub dx, cx |
sub bx, 1 |
@@: movsb |
add edi, [_color_step] |
loop @b |
mov cx, dx |
mov edx, [_tile_width] |
add edi, [line_step] |
jmp .step4 |
|
.step5: |
@@: movsb |
add edi, [_color_step] |
loop @b |
mov edx, [_tile_width] |
add edi, [line_step] |
dec bx |
jz .quit |
jmp .decode |
|
.step6: sub dx, cx |
@@: movsb |
add edi, [_color_step] |
loop @b |
jmp .decode |
|
.quit: pop edi |
ret |
endp |
|
|
proc merge_down _img, _bottom, _layer_number |
locals |
copy_width rd 1 |
copy_height rd 1 |
img_x1 rd 1 |
img_y1 rd 1 |
bottom_x1 rd 1 |
bottom_y1 rd 1 |
img_total_bpl rd 1 |
bottom_total_bpl rd 1 |
img_length rd 1 |
bottom_length rd 1 |
endl |
push ebx esi edi |
|
mov ebx, [_bottom] |
mov edx, [_img] |
|
mov [img_x1], 0 |
push [edx+Image.Width] |
pop [img_length] |
|
mov [bottom_x1], 0 |
mov ecx, [ebx+Image.Width] |
mov [bottom_length], ecx |
|
mov eax, [edx+Image.Extended] |
movsx eax, word[eax+xcf_ext.offset_x] |
cmp eax, 0 |
jg .greater_x |
jl .lesser_x |
mov [copy_width], ecx |
jmp .done_x |
.greater_x: |
add [bottom_x1], eax |
sub [bottom_length], eax |
jns .label_x |
mov [copy_width], 0 |
jmp .done_x |
.lesser_x: |
sub [img_x1], eax |
add [img_length], eax |
jns .label_x |
mov [copy_width], 0 |
jmp .done_x |
.label_x: |
mov ecx, [img_length] |
cmp ecx, [bottom_length] |
jng @f |
mov ecx, [bottom_length] |
@@: |
mov [copy_width], ecx |
.done_x: |
|
|
mov [img_y1], 0 |
push [edx+Image.Height] |
pop [img_length] |
|
mov [bottom_y1], 0 |
mov ecx, [ebx+Image.Height] |
mov [bottom_length], ecx |
|
mov eax, [edx+Image.Extended] |
movsx eax, word[eax+xcf_ext.offset_y] |
cmp eax, 0 |
jg .greater_y |
jl .lesser_y |
mov [copy_height], ecx |
jmp .done_y |
.greater_y: |
add [bottom_y1], eax |
sub [bottom_length], eax |
jns .label_y |
mov [copy_height], 0 |
jmp .done_y |
.lesser_y: |
sub [img_y1], eax |
add [img_length], eax |
jns .label_y |
mov [copy_height], 0 |
jmp .done_y |
.label_y: |
mov ecx, [img_length] |
cmp ecx, [bottom_length] |
jng @f |
mov ecx, [bottom_length] |
@@: |
mov [copy_height], ecx |
.done_y: |
|
mov esi, [edx+Image.Data] |
mov edi, [ebx+Image.Data] |
|
mov eax, [edx+Image.Width] |
imul eax, [img_y1] |
add eax, [img_x1] |
shl eax, 1 |
cmp [edx+Image.Width], Image.bpp16 |
je @f |
shl eax, 1 |
@@: add esi, eax |
|
mov eax, [ebx+Image.Width] |
imul eax, [bottom_y1] |
add eax, [bottom_x1] |
shl eax, 1 |
cmp [ebx+Image.Width], Image.bpp8 |
je @f |
shl eax, 1 |
@@: add edi, eax |
|
|
mov eax, [edx+Image.Width] |
sub eax, [copy_width] |
shl eax, 1 |
cmp [edx+Image.Width], Image.bpp16 |
je @f |
shl eax, 1 |
@@: mov [img_total_bpl], eax |
|
mov eax, [ebx+Image.Width] |
sub eax, [copy_width] |
shl eax, 1 |
cmp [ebx+Image.Width], Image.bpp8 |
je @f |
shl eax, 1 |
@@: mov [bottom_total_bpl], eax |
|
cmp [_layer_number], 0 |
jne .not_first |
mov ecx, [copy_width] |
imul ecx, [copy_height] |
cmp [ebx+Image.Type], Image.bpp8 |
je .bpp8 |
.bpp32: rep movsd |
jmp .done |
.bpp8: rep movsw |
jmp .done |
.not_first: |
|
push edi |
mov ecx, [edx+Image.Extended] |
mov eax, [ecx+xcf_ext.layer_mode] |
|
mov ecx, [ebx+Image.Extended] |
mov ecx, [ecx+xcf_ext.type] |
|
cmp ecx, XCF_BASETYPE_RGB |
jne @f |
mov edx, 4 |
jmp .type_defined |
@@: |
cmp ecx, XCF_BASETYPE_GRAY |
jne @f |
mov edx, 8 |
jmp .type_defined |
@@: |
mov edx, 12 |
.type_defined: |
mov ecx, (composite_table_end-composite_table_begin)/8 |
mov edi, composite_table_begin |
|
.still: |
cmp eax, [edi] |
jne @f |
add edi, edx |
mov edx, [edi] |
jmp .composite_found |
@@: |
add edi, 16 |
dec ecx |
jnz .still |
|
.composite_found: |
pop edi |
|
mov ecx, [ebx+Image.Extended] |
cmp [ecx+xcf_ext.type], XCF_BASETYPE_INDEXED |
jne @f |
stdcall edx, [copy_width], [copy_height], [bottom_total_bpl], [img_total_bpl] |
jmp .done |
@@: |
cmp eax, 1 |
ja @f |
stdcall edx, [copy_width], [copy_height], [bottom_total_bpl], [img_total_bpl] |
jmp .done |
@@: |
|
|
cmp [ebx+Image.Type], Image.bpp8 |
jne @f |
stdcall merge_8a, [copy_width], [copy_height], [img_total_bpl], [bottom_total_bpl] |
jmp .done |
@@: stdcall merge_32, [copy_width], [copy_height], [img_total_bpl], [bottom_total_bpl] |
; jmp .done |
.done: |
stdcall img.destroy, [_img] |
pop edi esi ebx |
ret |
endp |
|
|
proc pack_8a _img |
mov ebx, [_img] |
mov esi, [ebx+Image.Data] |
mov edi, [ebx+Image.Data] |
mov ecx, [ebx+Image.Width] |
mov edx, [ebx+Image.Height] |
imul ecx, edx |
@@: lodsw |
stosb |
dec ecx |
jnz @b |
ret |
endp |
|
|
proc apply_opacity _img, _color_step |
|
push ebx |
|
mov edx, [ebx+Image.Extended] |
mov edx, [edx+xcf_ext.opacity] |
cmp dl, 0xff |
je .quit |
|
mov ecx, [ebx+Image.Width] |
imul ecx, [ebx+Image.Height] |
mov esi, [ebx+Image.Data] |
mov ebx, [_color_step] |
add esi, ebx |
mov edi, esi |
@@: lodsb |
mul dl |
shr ax, 8 |
stosb |
add esi, ebx |
add edi, ebx |
dec ecx |
jnz @b |
|
.quit: pop ebx |
ret |
endp |
|
|
proc apply_alpha_mask _img, _mask, _color_step |
|
push ebx |
|
mov ebx, [_img] |
mov esi, [_mask] |
mov esi, [esi+Image.Data] |
mov edi, [ebx+Image.Data] |
mov ecx, [ebx+Image.Width] |
imul ecx, [ebx+Image.Height] |
mov ebx, [_color_step] |
add edi, ebx |
@@: |
lodsb |
mul byte[edi] |
shr ax, 8 |
stosb |
add edi, ebx |
dec ecx |
jnz @b |
|
stdcall img.destroy, [_mask] |
pop ebx |
ret |
endp |
|
|
proc pixel_rgb2hsv |
locals |
vsha rd 1 |
max rd 1 |
min rd 1 |
med rd 1 |
endl |
push ebx ecx edx |
|
mov [vsha], eax |
movzx eax, byte[vsha] ; eax = al = blue |
movzx ecx, byte[vsha+1] ; ecx = cl = green |
movzx edx, byte[vsha+2] ; edx = dl = red |
|
cmp al, cl |
jne @f |
cmp al, dl |
jne @f |
ror eax, 8 |
mov ax, 0 |
rol eax, 8 |
jmp .quit |
|
@@: cmp dl, cl |
ja @f |
cmp dl, al |
ja @f |
mov byte[min], dl |
jmp .min_found |
@@: cmp cl, al |
ja @f |
cmp cl, dl |
ja @f |
mov byte[min], cl |
jmp .min_found |
@@: mov byte[min], al |
; jmp .min_found |
.min_found: |
|
cmp dl, cl |
jb @f |
cmp dl, al |
jb @f |
mov byte[max], dl |
sub cx, ax |
mov dx, cx |
mov cx, 0 |
jmp .max_found |
@@: cmp cl, al |
jb @f |
cmp cl, dl |
jb @f |
mov byte[max], cl |
sub ax, dx |
mov dx, ax |
mov cx, 85 |
jmp .max_found |
@@: mov byte[max], al |
sub dx, cx |
mov cx, 171 |
; jmp .max_found |
.max_found: |
|
mov al, byte[max] |
sub al, byte[min] |
mov byte[med], al |
|
|
imul dx, 43 |
movsx eax, dx |
ror eax, 16 |
mov dx, ax |
rol eax, 16 |
mov byte[med+1], 0 |
idiv word[med] |
add al, cl |
mov byte[vsha+2], al |
|
mov al, byte[max] |
mov byte[vsha], al |
|
mov byte[vsha+1], 0 |
test al, al |
jz @f |
mov byte[vsha+1], 0xff |
cmp al, byte[med] |
je @f |
mov al, byte[med] |
shl ax, 8 |
div byte[max] |
mov byte[vsha+1], al |
@@: |
mov eax, [vsha] |
|
.quit: pop edx ecx ebx |
ret |
endp |
|
|
proc pixel_hsv2rgb |
locals |
vsha rd 1 |
f rb 1 |
c rb 1 |
x rb 1 |
endl |
|
push ebx ecx edx |
|
|
mov [vsha], eax |
mov bl, byte[vsha+1] |
mul bl |
mov byte[c], ah |
|
movzx eax, byte[vsha+2] |
cmp eax, 43 |
ja @f |
lea eax, [eax*3] |
shl eax, 1 |
mov ebx, eax |
shr ebx, 7 |
sub eax, ebx |
shr ebx, 1 |
sub eax, ebx |
jmp .ok |
|
@@: cmp eax, 86 |
ja @f |
sub eax, 44 |
lea eax, [eax*3] |
shl eax, 1 |
neg al |
add al, 0xff |
jmp .ok |
|
@@: cmp eax, 129 |
ja @f |
sub eax, 87 |
lea eax, [eax*3] |
shl eax, 1 |
jmp .ok |
|
@@: cmp eax, 171 |
ja @f |
sub eax, 130 |
lea eax, [eax*3] |
shl eax, 1 |
neg al |
add al, 0xff |
jmp .ok |
|
@@: cmp eax, 214 |
ja @f |
sub eax, 172 |
lea eax, [eax*3] |
shl eax, 1 |
jmp .ok |
@@: |
sub eax, 215 |
lea eax, [eax*3] |
shl eax, 1 |
neg al |
add al, 0xff |
; jmp .ok |
.ok: |
|
neg al |
add al, 0xff |
neg al |
add al, 0xff |
; shr ax, 8 |
mul byte[c] |
mov byte[x], ah |
|
|
|
mov al, byte[vsha+2] |
cmp al, 43 |
jae @f |
mov eax, [vsha] |
shr eax, 8 |
mov ah, byte[c] |
shl eax, 8 |
mov ah, byte[x] |
mov al, 0 |
jmp .done |
|
@@: cmp al, 86 |
jae @f |
mov eax, [vsha] |
shr eax, 8 |
mov ah, byte[x] |
shl eax, 8 |
mov ah, byte[c] |
mov al, 0 |
jmp .done |
|
@@: cmp al, 129 |
jae @f |
mov eax, [vsha] |
shr eax, 8 |
mov ah, 0 |
shl eax, 8 |
mov ah, byte[c] |
mov al, byte[x] |
jmp .done |
|
@@: cmp al, 171 |
jae @f |
mov eax, [vsha] |
shr eax, 8 |
mov ah, 0 |
shl eax, 8 |
mov ah, byte[x] |
mov al, byte[c] |
jmp .done |
|
@@: cmp al, 214 |
jae @f |
mov eax, [vsha] |
shr eax, 8 |
mov ah, byte[x] |
shl eax, 8 |
mov ah, 0 |
mov al, byte[c] |
jmp .done |
|
@@: mov eax, [vsha] |
shr eax, 8 |
mov ah, byte[c] |
shl eax, 8 |
mov ah, 0 |
mov al, byte[x] |
; jmp .done |
|
.done: |
mov bl, byte[vsha] |
sub bl, byte[c] |
ror eax, 8 |
add ah, bl |
rol eax, 8 |
add ah, bl |
add al, bl |
|
.quit: pop edx ecx ebx |
ret |
endp |
|
|
proc pixel_rgb2hsl |
; http://www.asmcommunity.net/board/index.php?topic=7425 |
; iblis: "I don't know what X-Filez is, but yes you may use it however you wish. That's why I made this post, to share." |
; so pixel_rgb2hsl procedure is based on code by Greg Hoyer (iblis). thanks! |
;--------------------------------------------------------------; |
; By Greg Hoyer aka "Iblis" ; |
; ; |
; RGB2HSL converts a COLORREF oriented dword filled with 8bit ; |
; Red/Green/Blue values (00ggbbrr) to a similarly oriented ; |
; dword filled with Hue/Saturation/Luminance values (00llsshh) ; |
; This procedure returns the full range, from 0-255. This ; |
; offers slightly more precision over Windows' "color picker" ; |
; common dialog, which displays HSL values ranging from 0-240. ; |
; ; |
; It is important to note that true HSL values are normally ; |
; represented as floating point fractions from 0.0 to 1.0. ; |
; As such, this algorithm cannot be used to do the precise, ; |
; consistent conversions that may be required by heavy-duty ; |
; graphics applications. To get the decimal fraction for ; |
; the returned values, convert the Hue, Saturation, and/or ; |
; Luminance values to floating point, and then divide by 255. ; |
;--------------------------------------------------------------; |
locals |
bgra rd 1 |
endl |
push ebx esi edi |
|
mov [bgra], eax |
|
movzx esi, byte[bgra+0] |
movzx edi, byte[bgra+1] |
movzx ebx, byte[bgra+2] |
mov cl, -1 |
cmp esi, edi |
ja .cmp1 |
xchg esi, edi |
neg cl |
shl cl, 1 |
.cmp1: cmp edi, ebx |
jb .cmp2 |
xchg edi, ebx |
neg cl |
.cmp2: cmp esi, ebx |
ja .cmp3 |
xchg esi, ebx |
not cl |
.cmp3: neg ebx |
add ebx, esi |
mov eax, edi |
add edi, esi |
jz .done |
sub esi, eax |
jz .done |
mov eax, esi |
shl eax, 8 |
sub eax, esi |
push edi |
cmp edi, 0xff |
jbe .csat |
neg edi |
add edi, 510 |
.csat: xor edx, edx |
div edi |
pop edi |
shr edi, 1 |
shl eax, 8 |
or edi, eax |
add cl, 3 |
jnc .noneg |
neg ebx |
.noneg: shl cl, 2 |
mov eax, 0x13135db9 |
shr eax, cl |
and eax, 7 |
mul esi |
add eax, ebx |
mov ebx, eax |
shl eax, 8 |
sub eax, ebx |
mov ebx, esi |
shl esi, 1 |
lea ebx, [ebx*4+esi] |
xor edx, edx |
div ebx |
shl eax, 16 |
or eax, edi |
.done: bswap eax |
shr eax, 8 |
|
mov bl, byte[bgra+3] |
bswap eax |
mov al, bl |
ror eax, 8 |
|
|
pop edi esi ebx |
ret |
endp |
|
|
proc pixel_hsl2rgb |
; http://www.asmcommunity.net/board/index.php?topic=7425 |
; iblis: "I don't know what X-Filez is, but yes you may use it however you wish. That's why I made this post, to share." |
; so pixel_hsl2rgb procedure is based on code by Greg Hoyer (iblis). thanks! |
;--------------------------------------------------------------; |
; By Greg Hoyer aka "Iblis" ; |
; ; |
; HSL2RGB does the opposite of RGB2HSL. It converts a ; |
; Hue/Saturation/Luminance (00llsshh) dword back into its ; |
; corresponding RGB COLORREF (00bbggrr). This function is ; |
; intented to be used exclusively with RGB2HSL (see above) ; |
; ; |
; If you're using this for your own custom color-chooser ; |
; dialog, remember that the values are in the range of 0-255. ; |
; If you MUST emulate the Windows' color-chooser, convert HSL ; |
; values this way before you display them: ; |
; ; |
; display_value = ( x * 240 ) / 255 ; |
; ; |
; ...where x represents any one of the HSL values. ; |
;--------------------------------------------------------------; |
locals |
lsha rd 1 |
endl |
|
push ebx esi edi |
|
mov [lsha], eax |
|
movzx ebx, byte[lsha+0] |
lea esi, [ebx*2] |
movzx edi, byte[lsha+1] |
xor eax, eax |
mov cl, 1 |
cmp bl, 0x7f |
ja .lcase |
dec al |
xor ecx, ecx |
.lcase: add eax, edi |
mul ebx |
or ecx, ecx |
jz .scase |
neg eax |
mov ecx, ebx |
add ecx, edi |
mov edx, ecx |
shl ecx, 8 |
sub ecx, edx |
add eax, ecx |
.scase: xor edx, edx |
xor ecx, ecx |
dec cl |
mov edi, ecx |
div ecx |
jz .done |
mov ecx, eax |
sub esi, eax |
movzx eax, byte[lsha+2] |
mov ebx, eax |
shl eax, 1 |
lea eax, [ebx*4+eax] |
xor edx, edx |
div edi |
mov ebx, eax |
mov eax, ecx |
sub eax, esi |
mul edx |
push ebx |
mov ebx, ecx |
shl ebx, 8 |
sub ebx, ecx |
sub ebx, eax |
xchg eax, ebx |
xor edx, edx |
div edi |
shl eax, 24 |
or ecx, eax |
mov eax, esi |
shl eax, 8 |
sub eax, esi |
shl esi, 16 |
or ecx, esi |
add eax, ebx |
xor edx, edx |
div edi |
mov ch, al |
mov eax, ecx |
pop ecx |
cmp cl, 6 |
jz .done |
or ecx, ecx |
jz .done |
bswap eax |
rol eax, 8 |
xchg ah, al |
dec ecx |
jz .done |
ror eax, 8 |
xchg ah, al |
dec ecx |
jz .done |
rol eax, 8 |
xchg ah, al |
dec ecx |
jz .done |
bswap eax |
rol eax, 8 |
xchg ah, al |
dec ecx |
jz .done |
ror eax, 8 |
xchg ah, al |
.done: and eax, 0x00ffffff |
|
mov bl, byte[lsha+3] |
bswap eax |
mov al, bl |
ror eax, 8 |
|
pop edi esi ebx |
ret |
endp |
|
|
match =MMX,COMPOSITE_MODE{include 'composite_mmx.inc'} |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
;! Below is private data you should never use directly from your code ;; |
;;================================================================================================;; |
;;////////////////////////////////////////////////////////////////////////////////////////////////;; |
;;================================================================================================;; |
xcf_prop_table_begin: |
dd 00, parse_prop_00 |
dd 01, parse_prop_01 |
dd 06, parse_prop_06 |
dd 07, parse_prop_07 |
dd 08, parse_prop_08 |
dd 11, parse_prop_11 |
dd 15, parse_prop_15 |
xcf_prop_table_end: |
|
composite_table_begin: |
.p00 dd 00, composite_rgb_00, composite_gray_00, composite_indexed_00 ; Normal |
.p01 dd 01, composite_rgb_01, composite_gray_01, composite_gray_01 ; Dissolve : random dithering to discrete alpha |
;.p02 dd 02, composite_rgb_02, 0, composite_indexed_02 ; Behind : not selectable in the GIMP UI. not implemented |
.p03 dd 03, composite_rgb_03, composite_rgb_03, composite_indexed_00 ; Multiply |
.p04 dd 04, composite_rgb_04, composite_rgb_04, composite_indexed_00 ; Screen |
.p05 dd 05, composite_rgb_05, composite_rgb_05, composite_indexed_00 ; Overlay |
.p06 dd 06, composite_rgb_06, composite_rgb_06, composite_indexed_00 ; Difference |
.p07 dd 07, composite_rgb_07, composite_rgb_07, composite_indexed_00 ; Addition |
.p08 dd 08, composite_rgb_08, composite_rgb_08, composite_indexed_00 ; Subtract |
.p09 dd 09, composite_rgb_09, composite_rgb_09, composite_indexed_00 ; Darken Only |
.p10 dd 10, composite_rgb_10, composite_rgb_10, composite_indexed_00 ; Lighten Only |
.p11 dd 11, composite_rgb_11, composite_gray_00, composite_indexed_00 ; Hue (H of HSV) |
.p12 dd 12, composite_rgb_12, composite_gray_00, composite_indexed_00 ; Saturation (S of HSV) |
.p13 dd 13, composite_rgb_13, composite_gray_00, composite_indexed_00 ; Color (H and S of HSL) |
.p14 dd 14, composite_rgb_14, composite_gray_00, composite_indexed_00 ; Value (V of HSV) |
.p15 dd 15, composite_rgb_15, composite_rgb_15, composite_indexed_00 ; Divide |
.p16 dd 16, composite_rgb_16, composite_rgb_16, composite_indexed_00 ; Dodge |
.p17 dd 17, composite_rgb_17, composite_rgb_17, composite_indexed_00 ; Burn |
.p18 dd 18, composite_rgb_18, composite_rgb_18, composite_indexed_00 ; Hard Light |
.p19 dd 19, composite_rgb_05, composite_rgb_05, composite_indexed_00 ; Soft Light : XCF version >= 2 only ('soft light' == 'overlay') |
.p20 dd 20, composite_rgb_20, composite_rgb_20, composite_indexed_00 ; Grain Extract : XCF version >= 2 only |
.p21 dd 21, composite_rgb_21, composite_rgb_21, composite_indexed_00 ; Grain Merge : XCF version >= 2 only |
composite_table_end: |
|
random_a dd 1103515245 |
random_b dd 777 |
random_c dd 12345 |