diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/dataio/export/bltins/exgif.x | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/dataio/export/bltins/exgif.x')
-rw-r--r-- | pkg/dataio/export/bltins/exgif.x | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/pkg/dataio/export/bltins/exgif.x b/pkg/dataio/export/bltins/exgif.x new file mode 100644 index 00000000..462b70e4 --- /dev/null +++ b/pkg/dataio/export/bltins/exgif.x @@ -0,0 +1,557 @@ +include <mach.h> +include <fset.h> +include <evvexpr.h> +include "../export.h" +include "../exbltins.h" + + +define SZ_GIFSTRUCT 30 + +define GIF_INIT_BITS Memi[$1] # initial number of bits +define GIF_MAXCODE Memi[$1+1] # max output code +define GIF_FREE_ENT Memi[$1+2] # first unused entry +define GIF_OFFSET Memi[$1+3] # offset into output buffer +define GIF_IN_COUNT Memi[$1+4] # length of input +define GIF_CUR_BITS Memi[$1+5] # current no. bits in code +define GIF_N_BITS Memi[$1+6] # no. of max bits +define GIF_CUR_ACCUM Memi[$1+7] # current accumulator +define GIF_A_COUNT Memi[$1+8] # no. of chars in 'packet' +define GIF_CLEAR_CODE Memi[$1+9] # clear hash table code +define GIF_EOF_CODE Memi[$1+10] # EOF code +define GIF_CLEAR_FLAG Memi[$1+11] # hash table has been cleared? +define GIF_CURX Memi[$1+12] # current 'x' position in image +define GIF_CURY Memi[$1+13] # current 'y' position in image +define GIF_PASS Memi[$1+14] # interlacing pass number +define GIF_WIDTH Memi[$1+15] # width of output image +define GIF_HEIGHT Memi[$1+16] # height of output image +define GIF_EXPNUM Memi[$1+17] # expression we're evaluating +define GIF_LNUM Memi[$1+18] # line w/in that expression +define GIF_NPIX Memi[$1+19] # no. of pixels to process +define GIF_PERCENT Memi[$1+20] # percent of file completed + +define GIF_CDPTR Memi[$1+25] # compressed data (ptr) +define GIF_HPTR Memi[$1+26] # hash table (ptr) +define GIF_APTR Memi[$1+27] # packet accumulator (ptr) +define GIF_DPTR Memi[$1+28] # expression data (ptr) +define GIF_CPTR Memi[$1+29] # code table (ptr) + +define ACCUM Mems[GIF_APTR($1)+$2] +define HTAB Memi[GIF_HPTR($1)+$2] +define CODETAB Memi[GIF_CPTR($1)+$2] +define DATA Mems[GIF_DPTR($1)+$2-1] +define CDATA Mems[GIF_CDPTR($1)+$2] + +define HSIZE 5003 # 80% occupancy +define USE_INTERLACE true # Write interlaced GIF files? + +#---------------------------------------------------------------------------- +define INTERLACE 040X # Image descriptor flags +define GLOBAL_COLORMAP 080X +define LOCAL_COLORMAP 080X # (currently unused) + +# Define the flags for the GIF89a extension blocks (currently unused). +define GE_PLAINTEXT 001X # Plain Text Extension +define GE_APPLICATION 0FFX # Application Extension +define GE_COMMENT 0FEX # Comment Extension +define GE_GCONTROL 0F9X # Graphics Control Extension + + +# EX_GIF - Write the output image to a GIF 87a file. + +procedure ex_gif (ex) + +pointer ex #i task struct pointer + +pointer gif +int nbytes, flags + +char ch[2] +int or() + +begin + # Check to see that we have the correct number of expressions to + # write this format. + flags = EX_OUTFLAGS(ex) + if (EX_NEXPR(ex) != 1 && !bitset(flags, OF_BAND)) + call error (7, "Invalid number of expressions for GIF file.") + if (bitset(flags, OF_LINE) || bitset (flags, LINE_STORAGE)) + call error (7, "Line storage illegal for GIF file.") + + # Fix the output pixel type to single bytes. + call ex_do_outtype (ex, "b1") + EX_OUTFLAGS(ex) = or (EX_OUTFLAGS(ex), OF_FLIPY) + + # Allocate the gif structure. + iferr { + call calloc (gif, SZ_GIFSTRUCT, TY_STRUCT) + call calloc (GIF_APTR(gif), 257, TY_SHORT) + call calloc (GIF_HPTR(gif), HSIZE, TY_INT) + call calloc (GIF_CPTR(gif), HSIZE, TY_INT) + call calloc (GIF_DPTR(gif), max(256,EX_OCOLS(ex)), TY_SHORT) + call calloc (GIF_CDPTR(gif), (2*EX_OROWS(ex)*EX_OCOLS(ex)),TY_SHORT) + } then + call error (0, "Error allocating gif structure.") + + GIF_WIDTH(gif) = EX_OCOLS(ex) + GIF_HEIGHT(gif) = EX_OROWS(ex) + GIF_NPIX(gif) = EX_OROWS(ex) * EX_OCOLS(ex) + GIF_CURX(gif) = 1 + GIF_CURY(gif) = 0 + GIF_PASS(gif) = 1 + GIF_EXPNUM(gif) = EX_NEXPR(ex) + GIF_LNUM(gif) = GIF_HEIGHT(gif) + + # Write the header information. + call gif_wheader (ex, EX_FD(ex)) + + # Start processing the expressions and write compressed image data. + call gif_compress (ex, gif, EX_FD(ex)) + + # Write the GIF file terminator and dump the whole thing to disk. + if (mod(GIF_OFFSET(gif),2) == 1) { + CDATA(gif,GIF_OFFSET(gif)) = '\0' + GIF_OFFSET(gif) = GIF_OFFSET(gif) + 1 + ch[1] = ';' + ch[2] = ';' + nbytes = (GIF_OFFSET(gif) + 1) / SZB_CHAR + } else { + ch[1] = '\0' + ch[2] = ';' + nbytes = GIF_OFFSET(gif) / SZB_CHAR + } + call achtsb (CDATA(gif,0), CDATA(gif,0), GIF_OFFSET(gif)) + call write (EX_FD(ex), CDATA(gif,0), nbytes) + call achtsb (ch, ch, 2) + call write (EX_FD(ex), ch, 1) + + # Clean up the pointers. + call mfree (GIF_APTR(gif), TY_SHORT) + call mfree (GIF_DPTR(gif), TY_SHORT) + call mfree (GIF_CDPTR(gif), TY_SHORT) + call mfree (GIF_HPTR(gif), TY_INT) + call mfree (GIF_CPTR(gif), TY_INT) + call mfree (gif, TY_STRUCT) +end + + +# GIF_WHEADER - Write the GIF header information. This covers not only the +# global file header but all the preliminary stuff up until the actual image +# data + +procedure gif_wheader (ex, fd) + +pointer ex #i tast struct pointer +int fd #i output file descriptor + +char sig[7] # GIF signature +char lsd[772] # Screen and Color Map information +short SWidth, SHeight # Screen width and height + +short stmp +int i, j + +int shifti(), ori() + +define GIF_SIGNATURE "GIF87a" + +begin + fd = EX_FD(ex) + + # Write the GIF signature. This is technically the "header", following + # this are the scene/color/image descriptors. + call strcpy (GIF_SIGNATURE, sig, 7) + call strpak (sig, sig, 7) + call write (fd, sig, 7/SZB_CHAR) + + # Logical Screen Descriptor. + SWidth = EX_OCOLS(ex) + SHeight = EX_OROWS(ex) + call gif_putword (fd, SWidth) + call gif_putword (fd, SHeight) + + # Set the 'packed' flags and write it out + i = 0 + i = ori (i, GLOBAL_COLORMAP) # indicate a colormap + i = ori (i, (shifti(7, 4))) # color resolution + i = ori (i, (8-1)) # bits per pixel + lsd[1] = i # packed flags + lsd[2] = 0 # background color + lsd[3] = 0 # aspect ratio + lsd[4] = 0 # filler expansion byte + + # Write out the colormap. + if (EX_CMAP(ex) != NULL) { + j = 1 + for (i=4 ; i <= 772; i=i+3) { + lsd[i ] = CMAP(EX_CMAP(ex), EX_RED, j) + lsd[i+1] = CMAP(EX_CMAP(ex), EX_GREEN, j) + lsd[i+2] = CMAP(EX_CMAP(ex), EX_BLUE, j) + j = j + 1 + } + } else { + j = 0 + for (i=4 ; i <= 772; i=i+3) { + lsd[i ] = j + lsd[i+1] = j + lsd[i+2] = j + j = j + 1 + } + } + lsd[772] = ',' + call achtcb (lsd, lsd, 772) + call write (fd, lsd, 772/SZB_CHAR) + + # Write the image header. + stmp = 0 + call gif_putword (fd, stmp) + call gif_putword (fd, stmp) + call gif_putword (fd, SWidth) + call gif_putword (fd, SHeight) + + # Next set the interlace flag and the initial code size in the next + # two bytes. + if (USE_INTERLACE) + stmp = ori (shifti(INTERLACE,8), 8) + else + stmp = 8 + if (BYTE_SWAP2 == YES) + call bswap2 (stmp, 1, stmp, 1, 2) + call write (fd, stmp, 1) +end + + +# GIF_COMPRESS - Compress the image data using a modified LZW. + +procedure gif_compress (ex, gif, fd) + +pointer ex #i tast struct pointer +pointer gif #i gif struct pointer +int fd #i output file descriptor + +long fcode +int i, c, ent, disp +int hsize_reg, hshift + +short gif_next_pixel() +int xori(), shifti() + +define probe_ 99 +define nomatch_ 98 + +begin + GIF_INIT_BITS(gif) = 9 # initialize + GIF_N_BITS(gif) = 9 + GIF_OFFSET(gif) = 0 + GIF_CLEAR_FLAG(gif) = NO + GIF_IN_COUNT(gif) = 1 + GIF_MAXCODE(gif) = 511 + GIF_CLEAR_CODE(gif) = 256 + GIF_EOF_CODE(gif) = GIF_CLEAR_CODE(gif) + 1 + GIF_FREE_ENT(gif) = GIF_CLEAR_CODE(gif) + 2 + GIF_A_COUNT(gif) = 0 + + ent = gif_next_pixel (ex, gif) + hshift = 0 + for (fcode = HSIZE; fcode < 65536 ; fcode = fcode * 2) + hshift = hshift + 1 + hshift = 8-hshift # set hash code range bound + + hsize_reg = HSIZE # clear the hash table + call amovki (-1, HTAB(gif,0), HSIZE) + + call gif_output (fd, gif, GIF_CLEAR_CODE(gif)) + + # Now loop over the pixels. + repeat { + c = gif_next_pixel (ex, gif) + if (c == EOF) + break + GIF_IN_COUNT(gif) = GIF_IN_COUNT(gif) + 1 + + fcode = shifti (c, 12) + ent + i = xori (shifti (c, hshift), ent) + + if (HTAB(gif,i) == fcode) { + ent = CODETAB(gif,i) + next + } else if (HTAB(gif,i) < 0) # empty slot + goto nomatch_ + disp = hsize_reg - i # secondary hash (after G. Knott) + if (i == 0) + disp = 1 + +probe_ i = i - disp + if (i < 0) + i = i + hsize_reg + + if (HTAB(gif,i) == fcode) { + ent = CODETAB(gif,i) + next + } + if (HTAB(gif,i) >= 0) + goto probe_ + +nomatch_ call gif_output (fd, gif, ent) + ent = c + if (GIF_FREE_ENT(gif) < 4096) { + CODETAB(gif,i) = GIF_FREE_ENT(gif) + GIF_FREE_ENT(gif) = GIF_FREE_ENT(gif) + 1 + HTAB(gif,i) = fcode + } else { + # Clear out the hash table. + call amovki (-1, HTAB(gif,0), HSIZE) + GIF_FREE_ENT(gif) = GIF_CLEAR_CODE(gif) + 2 + GIF_CLEAR_FLAG(gif) = YES + call gif_output (fd, gif, GIF_CLEAR_CODE(gif)) + } + } + + # Write out the final code. + call gif_output (fd, gif, ent) + call gif_output (fd, gif, GIF_EOF_CODE(gif)) +end + + +# GIF_NEXT_PIXEL - Writes a 16-bit integer in GIF order (LSB first). + +short procedure gif_next_pixel (ex, gif) + +pointer ex #i tast struct pointer +pointer gif #i gif struct pointer + +short pix +pointer op, out +pointer ex_chtype(), ex_evaluate() + +begin + if (GIF_NPIX(gif) == 0) + return (EOF) + + # If the current X position is at the start of a line get the new + # data, otherwise just return what we already know. + pix = 1 + if (GIF_CURX(gif) == 1) { + call ex_getpix (ex, GIF_LNUM(gif)) + op = ex_evaluate (ex, O_EXPR(ex,GIF_EXPNUM(gif))) + out = ex_chtype (ex, op, TY_UBYTE) + call aclrs (DATA(gif,1), O_LEN(op)) + call achtbu (Memc[out], DATA(gif,1), O_LEN(op)) + call mfree (out, TY_CHAR) + call evvfree (op) + } + pix = DATA(gif,GIF_CURX(gif)) + + # Increment the position. + if (GIF_CURY(gif) == EX_OROWS(ex)) { + GIF_CURX(gif) = min (EX_OCOLS(ex), GIF_CURX(gif) + 1) + } else + call gif_bump_pixel (ex, gif) + + GIF_NPIX(gif) = GIF_NPIX(gif) - 1 + return (pix) +end + + +# GIF_BUMP_PIXEL - Update the current x and y values for interlacing. + +procedure gif_bump_pixel (ex, gif) + +pointer ex #i tast struct pointer +pointer gif #i gif struct pointer + +int i, row, sum + +begin + GIF_CURX(gif) = GIF_CURX(gif) + 1 + + # If we are at the end of a scan line, set curx back to the beginning + # Since we are interlaced, bump the cury to the appropriate spot. + + if (GIF_CURX(gif) > GIF_WIDTH(gif)) { + GIF_CURX(gif) = 1 + + if (USE_INTERLACE) { + switch (GIF_PASS(gif)) { + case 1: + GIF_CURY(gif) = GIF_CURY(gif) + 8 + if (GIF_CURY(gif) >= GIF_HEIGHT(gif)) { + GIF_PASS(gif) = GIF_PASS(gif) + 1 + GIF_CURY(gif) = 4 + } + case 2: + GIF_CURY(gif) = GIF_CURY(gif) + 8 + if (GIF_CURY(gif) >= GIF_HEIGHT(gif)) { + GIF_PASS(gif) = GIF_PASS(gif) + 1 + GIF_CURY(gif) = 2 + } + case 3: + GIF_CURY(gif) = GIF_CURY(gif) + 4 + if (GIF_CURY(gif) >= GIF_HEIGHT(gif)) { + GIF_PASS(gif) = GIF_PASS(gif) + 1 + GIF_CURY(gif) = 1 + } + case 4: + GIF_CURY(gif) = GIF_CURY(gif) + 2 + if (GIF_CURY(gif) >= GIF_HEIGHT(gif)) { + GIF_EXPNUM(gif) = EX_NEXPR(ex) + GIF_LNUM(gif) = EX_OROWS(ex) + GIF_CURY(gif) = GIF_HEIGHT(gif) + return + } + } + + # Now figure out where we are in the expressions. + i = EX_NEXPR(ex) + sum = GIF_HEIGHT(gif) + while (sum >= GIF_CURY(gif)) { + sum = sum - O_HEIGHT(ex,i) + i = i - 1 + } + GIF_EXPNUM(gif) = i + 1 + GIF_LNUM(gif) = (sum + O_HEIGHT(ex,i+1)) - GIF_CURY(gif) + 1 + + row = ((EX_OROWS(ex) * EX_OCOLS(ex)) - GIF_NPIX(gif)) / + EX_OCOLS(ex) + #if (EX_VERBOSE(ex) == YES) + call ex_pstat (ex, row, GIF_PERCENT(gif)) + + } else { + GIF_CURY(gif) = GIF_CURY(gif) + 1 + + # Now figure out where we are in the expressions. + i = EX_NEXPR(ex) + sum = GIF_HEIGHT(gif) + while (sum >= GIF_CURY(gif)) { + sum = sum - O_HEIGHT(ex,i) + i = i - 1 + } + + if ((i+1) == GIF_EXPNUM(gif)) { + GIF_LNUM(gif) = GIF_LNUM(gif) - 1 + } else { + GIF_EXPNUM(gif) = i + 1 + GIF_LNUM(gif) = O_HEIGHT(ex,i+1) + } + + #if (EX_VERBOSE(ex) == YES) + call ex_pstat (ex, GIF_CURY(gif), GIF_PERCENT(gif)) + } + } +end + + +# GIF_OUTPUT - Output the given code. + +procedure gif_output (fd, gif, code) + +int fd #i output file descriptor +pointer gif #i gif struct pointer +int code #i code to output + +long masks[17] +int i + +int ori(), andi(), shifti() + +data (masks(i), i=1,5) /00000X, 00001X, 00003X, 00007X, 0000FX/ +data (masks(i), i=6,9) /0001FX, 0003FX, 0007FX, 000FFX/ +data (masks(i), i=10,13) /001FFX, 003FFX, 007FFX, 00FFFX/ +data (masks(i), i=14,17) /01FFFX, 03FFFX, 07FFFX, 0FFFFX/ + +begin + GIF_CUR_ACCUM(gif) = andi(GIF_CUR_ACCUM(gif),masks[GIF_CUR_BITS(gif)+1]) + + if (GIF_CUR_BITS(gif) > 0) + GIF_CUR_ACCUM(gif) = ori (GIF_CUR_ACCUM(gif), + shifti (code, GIF_CUR_BITS(gif))) + else + GIF_CUR_ACCUM(gif) = code + GIF_CUR_BITS(gif) = GIF_CUR_BITS(gif) + GIF_N_BITS(gif) + + while (GIF_CUR_BITS(gif) >= 8) { + call char_out (fd, gif, andi (GIF_CUR_ACCUM(gif), 0FFX)) + GIF_CUR_ACCUM(gif) = shifti (GIF_CUR_ACCUM(gif), -8) + GIF_CUR_BITS(gif) = GIF_CUR_BITS(gif) - 8 + } + + # If the next entry is going to be too big for the code size then + # increase it if possible. + if (GIF_FREE_ENT(gif) > GIF_MAXCODE(gif) || GIF_CLEAR_FLAG(gif)==YES) { + if (GIF_CLEAR_FLAG(gif) == YES) { + GIF_MAXCODE(gif) = 511 + GIF_N_BITS(gif) = 9 + GIF_CLEAR_FLAG(gif) = NO + } else { + GIF_N_BITS(gif) = GIF_N_BITS(gif) + 1 + if (GIF_N_BITS(gif) == 12) + GIF_MAXCODE(gif) = 4096 + else + GIF_MAXCODE(gif) = shifti (1, GIF_N_BITS(gif)) - 1 + } + } + + if (code == GIF_EOF_CODE(gif)) { + # At EOF, write the rest of the buffer. + while (GIF_CUR_BITS(gif) >= 8) { + call char_out (fd, gif, andi (GIF_CUR_ACCUM(gif), 0FFX)) + GIF_CUR_ACCUM(gif) = shifti (GIF_CUR_ACCUM(gif), -8) + GIF_CUR_BITS(gif) = GIF_CUR_BITS(gif) - 8 + } + + call flush_char (gif) + call flush (fd) + } +end + + +# GIF_PUTWORD - Writes a 16-bit integer in GIF order (LSB first). + +procedure gif_putword (fd, w) + +int fd +short w + +short val +int tmp, shifti() + +begin + # If this is a MSB-first machine swap the bytes before output. + if (BYTE_SWAP2 == NO) { + call bitpak (int(w), tmp, 9, 8) + call bitpak (shifti(int(w),-8), tmp, 1, 8) + val = tmp + } else + val = w + + call write (fd, val, SZ_SHORT/SZ_CHAR) +end + + +procedure char_out (fd, gif, c) + +int fd #i output file descriptor +pointer gif #i gif struct pointer +int c #i char to output + +begin + ACCUM(gif,GIF_A_COUNT(gif)) = c + GIF_A_COUNT(gif) = GIF_A_COUNT(gif) + 1 + if (GIF_A_COUNT(gif) >= 254) + call flush_char (gif) +end + + +procedure flush_char (gif) + +pointer gif #i gif struct pointer + +begin + if (GIF_A_COUNT(gif) > 0) { + CDATA(gif,GIF_OFFSET(gif)) = GIF_A_COUNT(gif) + GIF_OFFSET(gif) = GIF_OFFSET(gif) + 1 + call amovs (ACCUM(gif,0), CDATA(gif,GIF_OFFSET(gif)), + GIF_A_COUNT(gif)) + GIF_OFFSET(gif) = GIF_OFFSET(gif) + GIF_A_COUNT(gif) + GIF_A_COUNT(gif) = 0 + } +end |