[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352]
/* * Convert data format of figure */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "bookfile_figure.h" /* verify prototypes */ #include "bookreader_recdef.h" struct bitstream { int words_filled; /* Completed words */ int bit_off; /* bits written to current word */ int (*flush)(void *,int,char *); void *flush_arg; unsigned long buffer[65]; }; static int add_bits ( struct bitstream *bs, int value, int size ); static int compress_data ( struct bitstream *bs, int code_size, unsigned char *data, int width, int height ); /* hdr[2] = section #, hdr[3] = x, hdr[4] = y, hdr[5] = w hdr[6] = h * hdr[7] = picbytes, hdr[8]<0..7> = primitive * data[4..5] col, data[6..7] = rows */ int LIB$INIT_TIMER(), LIB$SHOW_TIMER(); int bkg_convert_figure_to_gif ( long hdr[10], /* Section header figure subrec */ unsigned char *data, int datalen, /* data read from section */ int (*output)(void*, int, char *), /* User-supplied output function */ void *outarg ) /* user-arg for output function */ { FILE* out; int i, j, k, width, height, value, mask, status; float aspect; short *cols, *rows; char trailer[2] = { 0, ';' }; unsigned char *cur_row, *cur_col; unsigned char *pixel_row, *pixel_image; int size, count; #ifdef __DECC #pragma nomember_alignment #endif struct gif_header { char signature[6]; /* GIF87a */ short width, height; /* little-endian */ unsigned char flags; /* <0..2> gct_size (2**(val+1)). */ /* <3> color table sorted */ /* <4..6> out device clr res (7)*/ /* <7> Global color table if set */ short aspect; /* aspect ratio */ unsigned char color_table[6]; /* 2-entry color table */ /* Image header follows */ char separator; /* ',' */ short left,top; /* origin */ short iwidth, iheight; /* Image size */ unsigned char iflags; /* <0..2> pixel depth */ /* <3..5> mbz */ /* <6> Interlace flag */ /* <7> local color table */ unsigned char code_size; /* first byte of image data */ } header; #ifdef __DECC #pragma member_alignment #endif struct bitstream bs; /* * Get dimensions of image and move data point to start of image bits. */ data += 4; cols = (short *)&data[0]; rows = (short *) &data[2]; datalen = datalen - 8; data += 4; /* skip origin and size info */ width = *cols; height = *rows; /* * Build gif header in structure and output. */ strcpy ( header.signature, "GIF87a" ); header.width = *cols; header.height = *rows; header.flags = 0; /* ASSUME 2^(0+1) = 2 BITS */ header.flags = header.flags | 0x00080; /* include GCT */ header.aspect = 0; header.color_table[0] = header.color_table[1] = header.color_table[2] = 0; header.color_table[3] = header.color_table[4] = header.color_table[5] = 255; header.separator = ','; header.left = header.top = 0; header.iwidth = width; header.iheight = height; header.iflags = 0; header.code_size = 2; /* first byte of raster data */ status = output( outarg, sizeof(header), (char *) &header ); if ( (status&1) == 0 ) return status; /* * Initialize data stream structure and do LZ compression on bits. * add bits automatically calls output routine when buffer fills. */ LIB$INIT_TIMER(); bs.words_filled = 0; bs.bit_off = 8; /* leave room for count byte. */ bs.flush = output; bs.flush_arg = outarg; bs.buffer[0] = 0; status = compress_data ( &bs, 2, data, width, height ); if ( (status&1) == 0 ) return status; /* * Flush remaining bits in buffer and add final trailer bytes. */ count = bs.words_filled*4 + (bs.bit_off+7)/8; /* include whole byte */ if ( count > 1 ) { bs.buffer[0] |= (count-1); status = output ( outarg, count, (char *) bs.buffer ); if ( (status&1) == 0 ) return status; } status = output ( outarg, 2, trailer ); if ( (status&1) == 0 ) return status; LIB$SHOW_TIMER(); return status; } /* * GIF encoder. * * The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated." * */ /*****************************************************************************/ static unsigned bmask[33] = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 0x03fff, 0x07fff, 0x0ffff, 0x01ffff, 0x03ffff, 0x07ffff, 0x0fffff, 0x01fffff, 0x03ffff, 0x07ffff, 0x0ffffff, 0x01ffffff, 0x03fffff, 0x07fffff, 0x0ffffff, 0x1fffffff, 0x3ffffff, 0x7ffffff, 0xffffffff }; static int add_bits ( struct bitstream *bs, int value, int size ) { int cur, pos, off, ov_bits, status; unsigned low; cur = bs->words_filled; off = bs->bit_off; #ifdef DEBUG printf("<%d,%d=%d>", off, size, value ); #endif if ( off + size <= 32 ) { /* * All fits in current longword of buffer. */ low = (value &bmask[size]); bs->buffer[cur] |= (low << off); bs->bit_off = off + size; } else { /* * value straddles two longwords. */ ov_bits = size + off - 32; if ( ov_bits > 0 ) { low = (value & bmask[size-ov_bits]); bs->buffer[cur++] |= (low<<off); } #ifdef DEBUG printf("buf[%d]=%x\n", cur-1, bs->buffer[cur-1] ); #endif if ( cur > 62 ) { long bcount; bcount = cur*4; bs->buffer[0] |= (bcount-1); /* load first (low) byte */ status = bs->flush ( bs->flush_arg, cur*4, (char *)bs->buffer ); if ( (status&1) == 0 ) return cur; value = (value & (~bmask[size-ov_bits])); /* zero field */ value = value << 8; /* make room for count */ ov_bits += 8; size += 8; cur = 0; } low = value; low = (low>>(size-ov_bits)); bs->buffer[cur] = (low & bmask[ov_bits]); bs->bit_off = ov_bits; } bs->words_filled = cur; return cur; } struct code_t_entry { short prefix, code, next_hash; }; struct lz_state { int code_size; /* Number of bits of input size */ int clear; /* value of clear code (2^code_size) */ int eoi; /* End-of-info code (clear+1); */ int out_size; int max_code; /* hight entry in code_table */ int max_hash; #define HASH_BITS 13 #define HASH_TABLE_SIZE 8192 int hash_shift; /* shift for charval in hash func */ struct code_t_entry table[4096]; /* code table */ short hash_table[HASH_TABLE_SIZE]; }; typedef struct lz_state *lzptr; static int initialize_lz_state ( lzptr lz, int code_size ) { int i, max_code, max_hash; struct code_t_entry *table; short *hash; lz->code_size = code_size; lz->clear = 1; for ( i = 0; i < code_size; i++ ) lz->clear *= 2; lz->eoi = lz->clear+1; lz->out_size = code_size + 1; lz->max_code = max_code = lz->eoi; max_hash = HASH_TABLE_SIZE; lz->hash_shift = 12; while ( (code_size+lz->hash_shift) > HASH_BITS) { lz->hash_shift = lz->hash_shift - 1; } /* max_hash = bmask[code_size+lz->hash_shift]; * / max_hash = bmask[HASH_BITS]; /* optimize for 1 bit data */ lz->max_hash = max_hash; /* * Initialize the tables. */ table = lz->table; for ( i = 0; i <= max_code; i++ ) { table[i].prefix = -1; table[i].code = i; table[i].next_hash = 0; } for ( ; i < 4096; i++ ) table[i].prefix = table[i].code = 0; hash = lz->hash_table; for ( i = 0; i < max_hash; i++ ) hash[i] = 0; return 1; } static int compress_data ( struct bitstream *bs, int code_size, unsigned char *data, int width, int height ) { int code, prefix, current, new, out_size, i, j, hashval; int code_limit, value, mask; unsigned char *dptr, *data_end; struct code_t_entry *table; short *hash_table; struct lz_state lz; dptr = data; initialize_lz_state ( &lz, code_size ); table = lz.table; hash_table = lz.hash_table; out_size = lz.out_size; code_limit = bmask[out_size]; add_bits ( bs, lz.clear, out_size ); value = *dptr++; prefix = (value&1) ? 0 : 1; /* first bit */ mask = 2; for ( i = 0; i < height; i++ ) { for ( j = (i==0) ? 1 : 0; j < width; j++ ) { /* * Extract next bit from input bits. */ current = ((value&mask) != 0) ? 0 : 1; mask *= 2; if ( mask > 128 ) { mask = 1; value = *dptr++; } /* * Find prefix//current table entry */ /* hashval = (lz.max_hash&((current<<lz.hash_shift) ^ prefix)); */ hashval = (current << 12) | prefix; /* optimized */ code = hash_table[hashval]; while ( code ) { if ( (table[code].prefix == prefix) && (table[code].code == current) ) break; code = table[code].next_hash; } /* * If code is non-zero, current prefix//code found in table and i is * the code. Make it the prefix and continue loop; */ if ( code ) { prefix = code; } else { /* * Entry not found, output current prefix. */ add_bits ( bs, prefix, out_size ); /* prefix = current; */ /* * Add new entry to table and update output size. */ new = ++lz.max_code; if ( new > code_limit ) { out_size++; code_limit = code_limit*2 + 1; } if ( new > 4092 ) { /* Reset so we don't overflow */ add_bits ( bs, current, out_size ); add_bits ( bs, lz.clear, out_size ); current = lz.clear; initialize_lz_state ( &lz, code_size ); #ifdef DEBUG printf("Reset code table, out_size %d, clear=%d\n", lz.out_size, lz.clear ); #endif out_size = lz.out_size; code_limit = bmask[out_size]; prefix = ((value&mask) != 0) ? 0 : 1; mask *= 2; if ( mask > 128 ) { mask = 1; value = *dptr++; } j++; if ( j >= width ) break; } else { lz.table[new].prefix = prefix; lz.table[new].code = current; lz.table[new].next_hash = hash_table[hashval]; lz.hash_table[hashval] = new; /* prefix for next value */ prefix = current; } } } if ( mask != 1 ) { /* wrap to next byte at eol */ mask = 1; value = *dptr++;; } } /* * Flush remaining to output. */ add_bits ( bs, prefix, out_size ); if ( i >= height ) { add_bits ( bs, lz.eoi, out_size ); return 1; } return 1; }