1. GIF loader bug fix
- Posted by Michael Bolin <michaeltom at GEOCITIES.COM> Apr 04, 1997
- 1006 views
- Last edited Apr 05, 1997
Hi all! The GIF loader I posted to this list recently contained a bug that would in rare cases cause it to crash. I have just fixed this, so here's the new code: ------------------------------------------- include machine.e include file.e global constant PCX_OPEN_FAILED=1, PCX_UNEXPECTED_EOF=2, PCX_UNSUPPORTED_FORMAT=3, GIF_OPEN_FAILED=1, GIF_UNEXPECTED_EOF=2, GIF_UNSUPPORTED_FORMAT=3 object junk sequence image,the_palette,bit_table integer file_num,exit_flag,palette_at_end integer x_size,y_size,bits_per_pixel,n_colors integer background,bytes_per_line,x_min,x_max integer y_min,y_max,n_planes bit_table=repeat({},256) for n=0 to 255 do bit_table[n+1]=int_to_bits(n,8) end for function read_bytes(integer amount) sequence bytes bytes=repeat(0,amount) for b=1 to amount do bytes[b]=getc(file_num) if bytes[b]=-1 then exit_flag=GIF_UNEXPECTED_EOF end if end for return bytes end function function bytes_left() integer place,end_place place=where(file_num) if seek(file_num,-1)=0 then end_place=where(file_num) if seek(file_num,place)=0 then return end_place-place else return -1 end if else return -1 end if end function procedure read_pcx_header() if bytes_left()<128 then exit_flag=PCX_UNEXPECTED_EOF return end if junk=getc(file_num) palette_at_end=0 if getc(file_num)=5 then palette_at_end=1 end if if getc(file_num)!=1 then exit_flag=PCX_UNSUPPORTED_FORMAT return end if bits_per_pixel=getc(file_num) if bits_per_pixel!=1 and bits_per_pixel!=8 then exit_flag=PCX_UNSUPPORTED_FORMAT return end if x_min=getc(file_num)+getc(file_num)*256 y_min=getc(file_num)+getc(file_num)*256 x_max=getc(file_num)+getc(file_num)*256 y_max=getc(file_num)+getc(file_num)*256 x_size=x_max-x_min+1 y_size=y_max-y_min+1 junk=read_bytes(4) the_palette={} if palette_at_end then junk=read_bytes(48) else for c=1 to 16 do the_palette=append(the_palette,read_bytes(3)) end for end if if exit_flag then return end if if getc(file_num) then exit_flag=PCX_UNSUPPORTED_FORMAT return end if n_planes=getc(file_num) bytes_per_line=getc(file_num)+getc(file_num)*256 junk=read_bytes(6) for x=1 to 54 do junk=getc(file_num) if junk=-1 then exit_flag=PCX_UNEXPECTED_EOF return elsif junk then exit_flag=PCX_UNSUPPORTED_FORMAT return end if end for end procedure procedure read_pcx_image() sequence one_row,bits,new_row integer number,byte,line,count,and_value,place integer plane_power,amount image=repeat({},y_size) one_row=repeat(0,bytes_per_line*n_planes) line=1 while line<=y_size do number=1 while number<=length(one_row) do byte=getc(file_num) if byte=-1 then exit_flag=PCX_UNEXPECTED_EOF return end if if byte>191 then count=byte-193 byte=getc(file_num) if byte=-1 then exit_flag=PCX_UNEXPECTED_EOF return end if one_row[number..number+count]=byte number=number+count+1 else one_row[number]=byte number=number+1 end if end while if bits_per_pixel=1 then bits=repeat(0,bytes_per_line*8*n_planes) place=1 for p=0 to n_planes-1 do plane_power=power(2,p) for t=1 to bytes_per_line do byte=one_row[p*bytes_per_line+t] and_value=256 for z=1 to 8 do and_value=and_value/2 if and_bits(byte,and_value) then bits[place]=plane_power end if place=place+1 end for end for end for amount=bytes_per_line*8 new_row=bits[1..amount] for p=1 to n_planes-1 do new_row=new_row+bits[amount*p+1..amount*(p+1)] end for if length(new_row)>x_size then new_row=new_row[1..x_size] end if else new_row=one_row end if image[line]=new_row line=line+1 end while if palette_at_end then junk=getc(file_num) for c=1 to 256 do the_palette=append(the_palette,read_bytes(3)) if find(-1,the_palette[c]) then exit_flag=PCX_UNEXPECTED_EOF return end if end for end if end procedure procedure read_gif_header() object work sequence stuff,bits integer global_color_map if bytes_left()<6 then exit_flag=GIF_UNEXPECTED_EOF return end if stuff=read_bytes(3) if compare(stuff,"GIF") and compare(stuff,"GIF") then exit_flag=GIF_UNSUPPORTED_FORMAT return end if junk=read_bytes(3) if bytes_left()<7 then exit_flag=GIF_UNEXPECTED_EOF return end if junk=read_bytes(4) bits=bit_table[getc(file_num)+1] global_color_map=bits[8] bits_per_pixel=bits_to_int(bits[1..3])+1 n_colors=power(2,bits_per_pixel) background=getc(file_num) junk=getc(file_num) the_palette={} if global_color_map then if bytes_left()<n_colors*3 then exit_flag=GIF_UNEXPECTED_EOF return end if for c=1 to n_colors do the_palette=append(the_palette,read_bytes(3)) end for end if while 1 do work=getc(file_num) if work=-1 then exit_flag=GIF_UNEXPECTED_EOF return elsif work=',' then exit end if end while end procedure procedure read_gif_image() object work sequence strings,bits,output,work_bits,string,stream integer interlace,code_size,clear_code,end_of_info integer num_bits,code,old,done,pointer,block_length integer bit_add if bytes_left()<9 then exit_flag=GIF_UNEXPECTED_EOF return end if junk=read_bytes(4) x_size=getc(file_num)+getc(file_num)*256 y_size=getc(file_num)+getc(file_num)*256 work=getc(file_num) bits=bit_table[work+1] if bits[8] then bits_per_pixel=bits_to_int(bits[1..3])+1 n_colors=power(2,bits_per_pixel) the_palette={} for c=1 to n_colors do the_palette=append(the_palette,read_bytes(3)) end for if exit_flag then return end if end if interlace=bits[7] image=repeat({},y_size) output={} if n_colors=2 then n_colors=4 end if strings=repeat({},n_colors+2) for t=1 to n_colors do strings[t]={t-1} end for code_size=getc(file_num) if code_size=-1 then exit_flag=GIF_UNEXPECTED_EOF return end if clear_code=power(2,code_size)+1 end_of_info=clear_code+1 num_bits=code_size+1 stream={} while 1 do block_length=getc(file_num) if block_length=0 then exit end if for b=1 to block_length do stream=append(stream,getc(file_num)) end for end while if find(-1,stream) then exit_flag=GIF_UNEXPECTED_EOF return end if stream=append(stream,0) stream=append(stream,-1) pointer=1 bits={} while length(bits)<26 do bits=bits & bit_table[stream[pointer]+1] pointer=pointer+1 end while bits=bits[num_bits+1..length(bits)] work_bits=bits[1..num_bits] code=bits_to_int(work_bits)+1 output=strings[code] old=code bits=bits[num_bits+1..length(bits)] done=0 while 1 do while length(bits)<26 and done=0 do work=stream[pointer] pointer=pointer+1 if work=-1 then done=1 exit end if bits=bits & bit_table[work+1] end while if length(bits)<num_bits then exit end if code=1 bit_add=1 for b=1 to num_bits do if bits[b] then code=code+bit_add end if bit_add=bit_add+bit_add end for bits=bits[num_bits+1..length(bits)] if code=end_of_info then exit elsif code=clear_code then strings=repeat({},n_colors+2) for t=1 to n_colors do strings[t]={t-1} end for num_bits=code_size+1 work_bits=bits[1..num_bits] code=bits_to_int(work_bits)+1 for t=1 to length(strings[code]) do output=append(output,strings[code][t]) end for old=code bits=bits[num_bits+1..length(bits)] else if code<=length(strings) then string=strings[code] for t=1 to length(string) do output=append(output,string[t]) end for work=strings[old] & string[1] strings=append(strings,work) old=code else work=strings[old] & strings[old][1] for t=1 to length(work) do output=append(output,work[t]) end for strings=append(strings,work) old=code end if end if if length(strings)=power(2,num_bits) then num_bits=num_bits+1 if num_bits=13 then num_bits=12 end if end if end while work=repeat({},y_size) for r=0 to y_size-1 do work[r+1]=output[r*x_size+1..r*x_size+x_size] end for if interlace then image=repeat({},y_size) pointer=1 for l=1 to y_size by 8 do image[l]=work[pointer] pointer=pointer+1 end for for l=5 to y_size by 8 do image[l]=work[pointer] pointer=pointer+1 end for for l=3 to y_size by 4 do image[l]=work[pointer] pointer=pointer+1 end for for l=2 to y_size by 2 do image[l]=work[pointer] pointer=pointer+1 end for else image=work end if end procedure global function read_pcx(sequence filename) exit_flag=0 file_num=open(filename,"rb") if file_num<0 then return PCX_OPEN_FAILED end if read_pcx_header() if exit_flag then close(file_num) return exit_flag end if read_pcx_image() close(file_num) if exit_flag then return exit_flag end if the_palette=the_palette[1..power(2,bits_per_pixel*n_planes)] return {the_palette,image} end function global function read_gif(sequence file_name) exit_flag=0 file_num=open(file_name,"rb") if file_num<0 then return GIF_OPEN_FAILED end if read_gif_header() if exit_flag then close(file_num) return exit_flag end if read_gif_image() close(file_num) if exit_flag then return exit_flag end if return {the_palette,image} end function ------------------------------------------- Regards, Michael Bolin
2. Re: GIF loader bug fix
- Posted by David Alan Gay <moggie at INTERLOG.COM> Apr 05, 1997
- 981 views
> Hi all! > > The GIF loader I posted to this list recently contained a bug that > would in rare cases cause it to crash. I have just fixed this, so > here's the new code: (eagerly snippity-snip-snip-snipping :) ) > Regards, > Michael Bolin Michael, I ran a few test runs with your fixxed source and it works great. Thank you! With your permission, I would like to use it in "A Beginner's Guide To Euphoria 2.00", as it would allow me to load GIFs instead of BMPs. This would lighten my load in picture files by about 70%. I'll be sure to put credit for your work in the documentation. Thanks David Gay http://www.interlog.com/~moggie/Euphoria "A Beginner's Guide To Euphoria"
3. Re: GIF loader bug fix
- Posted by Michael Bolin <michaeltom at GEOCITIES.COM> Apr 05, 1997
- 1016 views
- Last edited Apr 06, 1997
> Michael, I ran a few test runs with your fixxed source and it works great. > Thank you! With your permission, I would like to use it in "A Beginner's > Guide To Euphoria 2.00", as it would allow me to load GIFs instead of BMPs. > This would lighten my load in picture files by about 70%. I'll be sure to > put credit for your work in the documentation. Sure thing! It's meant to be free anyway :) Regards, Michael Bolin