libimg: encode API; pnm (pbm, pgm, ppm) encoding in raw mode

git-svn-id: svn://kolibrios.org@2684 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Ivan Baravy 2012-05-25 23:02:44 +00:00
parent d2c5967771
commit 0f1707c32e
4 changed files with 353 additions and 73 deletions

View File

@ -28,6 +28,7 @@ include '../../../../macros.inc'
purge section,mov,add,sub purge section,mov,add,sub
include 'libimg.inc' include 'libimg.inc'
;include '../../../../system/board/trunk/debug.inc'
section '.flat' code readable align 16 section '.flat' code readable align 16
@ -85,7 +86,7 @@ proc img.is_img _data, _length ;////////////////////////////////////////////////
;< --- TBD --- ;; ;< --- TBD --- ;;
;;================================================================================================;; ;;================================================================================================;;
push ebx push ebx
mov ebx, img._.formats_table mov ebx, img.formats_table
@@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
or eax, eax or eax, eax
jnz @f jnz @f
@ -152,11 +153,12 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////////////////////////;; proc img.to_rgb2 _img, _out ;/////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? decodes image data into RGB triplets and stores them where [_out] points to ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_img] = pointer to source image ;;
;> [_out] = where to store RGB triplets ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< --- TBD --- ;; ;< none ;;
;;================================================================================================;; ;;================================================================================================;;
push esi edi push esi edi
mov esi, [_img] mov esi, [_img]
@ -173,9 +175,9 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.to_rgb _img ;////////////////////////////////////////////////////////////////////////////;; proc img.to_rgb _img ;////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? decodes image data into RGB triplets and returns pointer to memory area containing them ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_img] = pointer to source image ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 / pointer to rgb_data (array of [rgb] triplets) ;; ;< eax = 0 / pointer to rgb_data (array of [rgb] triplets) ;;
;;================================================================================================;; ;;================================================================================================;;
@ -213,11 +215,12 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img._.do_rgb ;///////////////////////////////////////////////////////////////////////////////;; proc img._.do_rgb ;///////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? decodes [esi + Image.Data] data into RGB triplets and stores them at [edi] ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> esi = pointer to source image ;;
;> edi = pointer to memory to store RGB triplets ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< --- TBD --- ;; ;< none ;;
;;================================================================================================;; ;;================================================================================================;;
mov ecx, [esi + Image.Width] mov ecx, [esi + Image.Width]
imul ecx, [esi + Image.Height] imul ecx, [esi + Image.Height]
@ -552,14 +555,16 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.decode _data, _length, _options ;////////////////////////////////////////////////////////;; proc img.decode _data, _length, _options ;////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? decodes loaded into memory graphic file ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_data] = pointer to file in memory ;;
;> [_length] = size in bytes of memory area pointed to by [_data] ;;
;> [_options] = 0 / pointer to the structure of additional options ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 / pointer to image ;; ;< eax = 0 / pointer to image ;;
;;================================================================================================;; ;;================================================================================================;;
push ebx push ebx
mov ebx, img._.formats_table mov ebx, img.formats_table
@@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length] @@: stdcall [ebx + FormatsTableEntry.Is], [_data], [_length]
or eax, eax or eax, eax
jnz @f jnz @f
@ -575,25 +580,103 @@ proc img.decode _data, _length, _options ;//////////////////////////////////////
endp endp
;;================================================================================================;; ;;================================================================================================;;
proc img.encode _img, _p_length, _options ;///////////////////////////////////////////////////////;; proc img.encode _img, _common, _specific ;////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? encode image to some format ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_img] = pointer to input image ;;
;> [_common] = some most important options ;;
; 0x00 : byte : format id (defined in libimg.inc) ;;
; 0x01 : byte : fast encoding (0) / best compression ratio (255) ;;
; 0 : store uncompressed data (if supported both by the format and libimg) ;;
; 1 - 255 : use compression, if supported ;;
; this option may be ignored if any format specific options are defined ;;
; i.e. the 0 here will be ignored if some compression algorithm is specified ;;
; 0x02 : byte : flags (bitfield) ;;
; 0x01 : return an error if format specific conditions cannot be met ;;
; 0x02 : preserve current bit depth. means 8bpp/16bpp/24bpp and so on ;;
; 0x04 : delete alpha channel, if any ;;
; 0x08 : flush alpha channel with 0xff, if any; add it if none ;;
; 0x03 : byte : reserved, must be 0 ;;
;> [_specific] = 0 / pointer to the structure of format specific options ;;
; see <format_name>.inc for description ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 / pointer to encoded data ;; ;< eax = 0 / pointer to encoded data ;;
;< [_p_length] = data length ;; ;< ecx = error code / the size of encoded data ;;
; 1 : out of memory ;;
; 2 : format is not supported ;;
; 3 : specific conditions cannot be satisfied ;;
; 4 : bit depth cannot be preserved ;;
;;================================================================================================;; ;;================================================================================================;;
mov ebx, [_img]
movzx eax, byte[_common]
dec eax
imul eax, sizeof.FormatsTableEntry
add eax, FormatsTableEntry.Capabilities
add eax, img.formats_table
mov eax, [eax]
test eax, 1 ; is encoding to this format supported at all?
jnz @f
mov ecx, LIBIMG_ERROR_FORMAT
jmp .error
@@:
mov ecx, [ebx + Image.Type]
mov edx, 1
shl edx, cl
test eax, edx
jnz .bit_depth_ok
test byte[_common+2], LIBIMG_ENCODE_STRICT_BIT_DEPTH
jz @f
mov ecx, LIBIMG_ERROR_BIT_DEPTH
jmp .error
@@:
mov edx, 1 SHL Image.bpp24
test eax, edx
jnz @f
mov ecx, LIBIMG_ERROR_BIT_DEPTH
jmp .error
@@:
stdcall img.create, [ebx + Image.Width], [ebx + Image.Height], Image.bpp24
test eax, eax
jnz @f
mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY
jmp .error
@@:
push eax
stdcall img.to_rgb2, ebx, [eax + Image.Data]
pop ebx
.bit_depth_ok:
movzx eax, byte[_common]
dec eax
imul eax, sizeof.FormatsTableEntry
add eax, FormatsTableEntry.Encode
add eax, img.formats_table
mov eax, [eax]
stdcall eax, [_img], [_common], [_specific]
push eax ecx
cmp ebx, [_img]
je @f
stdcall img.destroy, ebx
@@:
pop ecx eax
jmp .quit
.error:
xor eax, eax xor eax, eax
.quit:
ret ret
endp endp
;;================================================================================================;; ;;================================================================================================;;
proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;; proc img.create _width, _height, _type ;//////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? creates an Image structure and initializes some its fields ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_width] = width of an image in pixels ;;
;> [_height] = height of an image in pixels ;;
;> [_type] = one of the Image.bppN constants from libimg.inc ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 / pointer to image ;; ;< eax = 0 / pointer to image ;;
;;================================================================================================;; ;;================================================================================================;;
@ -629,11 +712,12 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;; proc img.destroy.layer _img ;/////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? frees memory occupied by an image and all the memory regions its fields point to ;;
;? for image sequences deletes only one frame and fixes Previous/Next pointers ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_img] = pointer to image ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = false / true ;; ;< eax = 0 (fail) / 1 (success) ;;
;;================================================================================================;; ;;================================================================================================;;
mov eax, [_img] mov eax, [_img]
mov edx, [eax + Image.Previous] mov edx, [eax + Image.Previous]
@ -655,11 +739,12 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;; proc img.destroy _img ;///////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? --- TBD --- ;; ;? frees memory occupied by an image and all the memory regions its fields point to ;;
;? follows Previous/Next pointers and deletes all the images in sequence ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> --- TBD --- ;; ;> [_img] = pointer to image ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = false / true ;; ;< eax = 0 (fail) / 1 (success) ;;
;;================================================================================================;; ;;================================================================================================;;
push 1 push 1
mov eax, [_img] mov eax, [_img]
@ -1787,6 +1872,24 @@ proc img.draw _img, _x, _y, _width, _height, _xpos, _ypos ;/////////////////////
ret ret
endp endp
align 4
img.formats_table:
.bmp dd LIBIMG_FORMAT_ID_BMP, img.is.bmp, img.decode.bmp, img.encode.bmp, 0
.ico dd LIBIMG_FORMAT_ID_ICO, img.is.ico, img.decode.ico_cur, img.encode.ico, 0
.cur dd LIBIMG_FORMAT_ID_CUR, img.is.cur, img.decode.ico_cur, img.encode.cur, 0
.gif dd LIBIMG_FORMAT_ID_GIF, img.is.gif, img.decode.gif, img.encode.gif, 0
.png dd LIBIMG_FORMAT_ID_PNG, img.is.png, img.decode.png, img.encode.png, 0
.jpg dd LIBIMG_FORMAT_ID_JPEG, img.is.jpg, img.decode.jpg, img.encode.jpg, 0
.tga dd LIBIMG_FORMAT_ID_TGA, img.is.tga, img.decode.tga, img.encode.tga, 0
.pcx dd LIBIMG_FORMAT_ID_PCX, img.is.pcx, img.decode.pcx, img.encode.pcx, 0
.xcf dd LIBIMG_FORMAT_ID_XCF, img.is.xcf, img.decode.xcf, img.encode.xcf, 0
.tiff dd LIBIMG_FORMAT_ID_TIFF, img.is.tiff, img.decode.tiff, img.encode.tiff,0
.pnm dd LIBIMG_FORMAT_ID_PNM, img.is.pnm, img.decode.pnm, img.encode.pnm, 1 + (1 SHL Image.bpp1) + (1 SHL Image.bpp8) + (1 SHL Image.bpp24)
.wbmp dd LIBIMG_FORMAT_ID_WBMP, img.is.wbmp, img.decode.wbmp, img.encode.wbmp,0
.z80 dd LIBIMG_FORMAT_ID_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
;;================================================================================================;; ;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;; ;;================================================================================================;;
@ -1991,24 +2094,6 @@ img._.get_scanline_len: ;///////////////////////////////////////////////////////
;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;; ;;================================================================================================;;
align 4
img._.formats_table:
.bmp dd img.is.bmp, img.decode.bmp, img.encode.bmp
.ico dd img.is.ico, img.decode.ico_cur, img.encode.ico
.cur dd img.is.cur, img.decode.ico_cur, img.encode.cur
.gif dd img.is.gif, img.decode.gif, img.encode.gif
.png dd img.is.png, img.decode.png, img.encode.png
.jpg dd img.is.jpg, img.decode.jpg, img.encode.jpg
.tga dd img.is.tga, img.decode.tga, img.encode.tga
.pcx dd img.is.pcx, img.decode.pcx, img.encode.pcx
.xcf dd img.is.xcf, img.decode.xcf, img.encode.xcf
.tiff dd img.is.tiff, img.decode.tiff, img.encode.tiff
.pnm dd img.is.pnm, img.decode.pnm, img.encode.pnm
.wbmp dd img.is.wbmp, img.decode.wbmp, img.encode.wbmp
.z80 dd img.is.z80, img.decode.z80, img.encode.z80 ;this must be the last entry as there are no
;signatures in z80 screens at all
dd 0
align 4 align 4
type2bpp dd 8, 24, 32, 15, 16, 1 type2bpp dd 8, 24, 32, 15, 16, 1
img._.do_rgb.handlers: img._.do_rgb.handlers:
@ -2060,8 +2145,9 @@ export \
img.flip , 'img_flip' , \ img.flip , 'img_flip' , \
img.flip.layer , 'img_flip_layer' , \ img.flip.layer , 'img_flip_layer' , \
img.rotate , 'img_rotate' , \ img.rotate , 'img_rotate' , \
img.rotate.layer, 'img_rotate_layer', \ img.rotate.layer , 'img_rotate_layer' , \
img.draw , 'img_draw' img.draw , 'img_draw' , \
img.formats_table, 'img_formats_table'
; import from deflate unpacker ; import from deflate unpacker
; is initialized only when PNG loading is requested ; is initialized only when PNG loading is requested

View File

@ -17,11 +17,40 @@
;; ;; ;; ;;
;;================================================================================================;; ;;================================================================================================;;
; list of format id's
LIBIMG_FORMAT_ID_BMP = 1
LIBIMG_FORMAT_ID_ICO = 2
LIBIMG_FORMAT_ID_CUR = 3
LIBIMG_FORMAT_ID_GIF = 4
LIBIMG_FORMAT_ID_PNG = 5
LIBIMG_FORMAT_ID_JPEG = 6
LIBIMG_FORMAT_ID_TGA = 7
LIBIMG_FORMAT_ID_PCX = 8
LIBIMG_FORMAT_ID_XCF = 9
LIBIMG_FORMAT_ID_TIFF = 10
LIBIMG_FORMAT_ID_PNM = 11
LIBIMG_FORMAT_ID_WBMP = 12
LIBIMG_FORMAT_ID_Z80 = 13
; error codes
LIBIMG_ERROR_OUT_OF_MEMORY = 1
LIBIMG_ERROR_FORMAT = 2
LIBIMG_ERROR_CONDITIONS = 3
LIBIMG_ERROR_BIT_DEPTH = 4
LIBIMG_ERROR_ENCODER = 5
; encode flags (byte 0x02 of _common option)
LIBIMG_ENCODE_STRICT_SPECIFIC = 0x01
LIBIMG_ENCODE_STRICT_BIT_DEPTH = 0x02
LIBIMG_ENCODE_DELETE_ALPHA = 0x08
LIBIMG_ENCODE_FLUSH_ALPHA = 0x10
struct FormatsTableEntry struct FormatsTableEntry
Format_id dd ?
Is dd ? Is dd ?
Decode dd ? Decode dd ?
Encode dd ? Encode dd ?
Capabilities dd ?
ends ends
struct Image struct Image

View File

@ -182,16 +182,127 @@ endp
;;================================================================================================;; ;;================================================================================================;;
proc img.encode.pnm _img, _p_length, _options ;///////////////////////////////////////////////////;; proc img.encode.pnm _img, _common, _specific ;////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;? Encode image into raw data in pnm format ;; ;? Encode image into raw data in pnm format ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;> _img = pointer to image ;; ;> [_img] = pointer to image ;;
;> [_common] = format independent options ;;
;> [_specific] = 0 / pointer to the structure of format specific options ;;
;;------------------------------------------------------------------------------------------------;; ;;------------------------------------------------------------------------------------------------;;
;< eax = 0 (error) or pointer to encoded data ;; ;< eax = 0 / pointer to encoded data ;;
;< _p_length = encoded data length ;; ;< ecx = error code / the size of encoded data ;;
;;================================================================================================;; ;;================================================================================================;;
locals
encoded_file rd 1
encoded_file_size rd 1
encoded_data_size rd 1
endl
push ebx
mov ebx, [_img]
mov eax, [ebx + Image.Type]
cmp eax, Image.bpp1
je .pbm
cmp eax, Image.bpp8
je .pgm
cmp eax, Image.bpp24
je .ppm
mov ecx, LIBIMG_ERROR_BIT_DEPTH
jmp .error
.pbm:
mov ecx, [ebx + Image.Width]
add ecx, 7
shr ecx, 3
imul ecx, [ebx + Image.Height]
mov [encoded_data_size], ecx
add ecx, (2 + 1) + (2 + pnm._.creator_comment.size + 1) + (5 + 1 + 5 + 1) + (3 + 1)
mov [encoded_file_size], ecx
stdcall [mem.alloc], ecx
mov [encoded_file], eax
test eax, eax
jnz @f
mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY
jmp .error
@@:
mov edi, eax
mov ax, 'P4'
call pnm._.write_header
mov esi, [ebx + Image.Data]
mov ecx, [encoded_data_size]
rep movsb
mov eax, [encoded_file]
mov ecx, [encoded_file_size]
jmp .quit
.pgm:
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
mov [encoded_data_size], ecx
add ecx, (2 + 1) + (2 + pnm._.creator_comment.size + 1) + (5 + 1 + 5 + 1) + (3 + 1)
mov [encoded_file_size], ecx
stdcall [mem.alloc], ecx
mov [encoded_file], eax
test eax, eax
jnz @f
mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY
jmp .error
@@:
mov edi, eax
mov ax, 'P5'
call pnm._.write_header
mov dword[edi], '255 '
add edi, 3
mov byte[edi], 0x0A
add edi, 1
mov esi, [ebx + Image.Data]
mov ecx, [encoded_data_size]
rep movsb
mov eax, [encoded_file]
mov ecx, [encoded_file_size]
jmp .quit
.ppm:
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
lea ecx, [ecx*3]
mov [encoded_data_size], ecx
add ecx, (2 + 1) + (2 + pnm._.creator_comment.size + 1) + (5 + 1 + 5 + 1) + (3 + 1)
mov [encoded_file_size], ecx
stdcall [mem.alloc], ecx
mov [encoded_file], eax
test eax, eax
jnz @f
mov ecx, LIBIMG_ERROR_OUT_OF_MEMORY
jmp .error
@@:
mov edi, eax
mov ax, 'P6'
call pnm._.write_header
mov dword[edi], '255 '
add edi, 3
mov byte[edi], 0x0A
add edi, 1
mov esi, [ebx + Image.Data]
mov ecx, [ebx + Image.Width]
imul ecx, [ebx + Image.Height]
@@:
lodsb
mov byte[edi+2], al
lodsb
mov byte[edi+1], al
movsb
add edi, 2
dec ecx
jnz @b
mov eax, [encoded_file]
mov ecx, [encoded_file_size]
jmp .quit
.error:
xor eax, eax xor eax, eax
.quit:
pop ebx
ret ret
endp endp
@ -220,6 +331,54 @@ proc pnm._.get_number
ret ret
endp endp
proc pnm._.write_header
stosw
mov byte[edi], 0x0A
add edi, 1
mov word[edi], '# '
add edi, 2
mov esi, pnm._.creator_comment
mov ecx, pnm._.creator_comment.size
rep movsb
mov byte[edi], 0x0A
add edi, 1
push edi
mov al, ' '
mov ecx, (5 + 1 + 5)
rep stosb
pop edi
push edi
add edi, 4
mov eax, [ebx + Image.Width]
mov ecx, 10
.write_width:
xor edx, edx
div cx
add dl, '0'
mov byte[edi], dl
dec edi
test ax, ax
jnz .write_width
mov eax, [ebx + Image.Height]
pop edi
push edi
add edi, 10
.write_height:
xor edx, edx
div cx
add dl, '0'
mov byte[edi], dl
dec edi
test ax, ax
jnz .write_height
pop edi
add edi, 11
mov byte[edi], 0x0A
add edi, 1
ret
endp
;;================================================================================================;; ;;================================================================================================;;
;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;; ;;================================================================================================;;
@ -228,3 +387,5 @@ endp
;;////////////////////////////////////////////////////////////////////////////////////////////////;; ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
;;================================================================================================;; ;;================================================================================================;;
sz pnm._.creator_comment ,'CREATOR: KolibriOS / libimg'

View File

@ -24,3 +24,7 @@ PNM_PBM = 0
PNM_PGM = 1 PNM_PGM = 1
PNM_PPM = 2 PNM_PPM = 2
struct Encode_PNM ; ignored so far. just an example
Size dd ? ; the size of this structure
Mode dd ? ; PNM_RAW or PNM_ASCII
ends