Académique Documents
Professionnel Documents
Culture Documents
by
Josquin S Corrales Prepared For Dr. Yacoub El-Ziq MatrixView USA February 8, 2007
Table of Contents
Overview .................................................................................................................................................. 3 Development Platform Configuration .................................................................................................. 3 TIFF to GIF Conversion ........................................................................................................................... 4 Reference TIFF to GIF Converter Design ............................................................................................4 TIFF File Format2 ................................................................................................................................ 4 GIF File Format ....................................................................................................................................4 Embedded LZW ........................................................................................................................................ 8 Device Driver ...................................................................................................................................9 DataFlow: ........................................................................................................................................ 9 malloc/xil_malloc .......................................................................................................................... 11 EDK Debugger .............................................................................................................................. 13 Fast Simplex Link ................................................................................................................................... 13 LZW Compression Algorithm..................................................................................................................13 Appendix A: Stand Alone Re/TIFF Sources ........................................................................................... 14 Appendix B: Microblaze Implementation Sources ................................................................................. 37
Overview
The project objective was to develop a chip design that performed image file format conversion for an input TIFF to output GIF. In order to simplify the process, the projected was divided into three parts. Part I demonstrates a C version of the converter than runs on common x86 architectures in order to gain an understanding of TIFF and GIF file formats. No specialized hardware or chip was used. Part II demonstrates porting the C converter an embedded processor running on an FPGA using IP cores provided by the Xilinx Embedded Development Kit (EDK) and the development board support packages (BSP). Part III demonstrates a Verilog module that performs the data conversion.
The GIF file format follows a grammar that provides a division of the byte steam and high level overview. The basic definition of the GIF allows for a data stream to contain only the header, the logical screen descriptor, a global color table and a trailer. This will define a GIF image, which can be processed by viewer without error, but will not display any picture because it does not contain image data block. The Grammar.
<GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer <Logical Screen> ::= Logical Screen Descriptor [Global Color Table] <Data> ::= <Graphic Block> | <Special-Purpose Block> <Graphic Block> ::= [Graphic Control Extension] <Graphic-Rendering Block> <Graphic-Rendering Block> ::= <Table-Based Image> | Plain Text Extension <Table-Based Image> ::= Image Descriptor [Local Color Table] Image Data <Special-Purpose Block> ::= Application Extension | Comment Extension
The header contains some constant values that describe the file format that follows, sometimes referred to as the "Magic Number". The Logical Screen Descriptor contains the image width, height, global color table flag, along with other settings that define the format of the data stored in the Image Data block. The Global Color Table contains red-green-blue (RGB) color triplets in three sets of octets (e.g. 24-bits of RGB color entires). This block defines a maximum of 256 RGB entries and at a very basic level each Image Data octet is an index into this color table. The Image Descriptor is a header type block that specifies left position, top, width, height and other data of the Image Data block that follows. The Image Data block specifies the LZW Minimum Code size and the Image Data represented by codewords output by the LZW compression algo. This is the heart of how GIFs store image data. The details of how LZW compression is used to produce the codewords stored in the Image Data block is as follows. LZW is a lossless compression scheme because no round off errors or quantization occurs as in the application of transforms (e.g. wavelets) or other schemes. LZW compression operates by reading the input data, and then producing fixed length output codewords that are used to substitute longer running data input sequences. The codewords are devised by advancing an internal state machine counter called the "string table". Two special code words are added and enumerated to the string table which are the "clear code" and "end of stream code". The "clear" codeword provides the key to the uncompressed gif format. When the clear codeword is encounted by the LZW decoder, it resets the internal string table state machine. Uncompressed GIFs are image files that do not use LZW compression to compress their image data but are still recognizable as GIF by decoders which expect LZW compression image blocks. The idea is to
emit only single-symbol string codes, plus a Clear code every so often to keep the decoder from increasing the code width. The GIF byte order is little-endian. TIFF which has a designator for either. Sample output run
jsc01@LOCALHOST ~/im $ ls -aFl hi_uc.tiff -rw-r--r-- 1 jsc01 None 17130 Nov 2 16:13 hi_uc.tiff jsc01@LOCALHOST ~/im $ ./retiff hi_uc.tiff hi_retiff.gif debug IFD offset 4224 IFD records 16 4226 Tag fe Type 4 4232 Tag 100 Type 3 cols 132 423e Tag 101 Type 3 rows 115 424a Tag 102 Type 3 bps 8 size 15180 from row x cols 4256 Tag 103 Type 3 4262 Tag 106 Type 3 426e Tag 10d Type 2 427a Tag 111 Type 4 strip count 15 strip offset 1632 4286 Tag 115 Type 3 4292 Tag 116 Type 4 rows per strip 8 429e Tag 117 Type 4 strip byte counts offset 69c 42aa Tag 11a Type 5
42b6 Tag 11b Type 5 42c2 Tag 128 Type 3 42ce Tag 131 Type 2 42da Tag 140 Type 3 colormap size 768 colormap offset 80 Strip byte sizes: offset 0 byte size 1056
offset 13 byte size 1056 offset 14 byte size 396 TIFF image size 15180 from byte counts Strip offsets: offset 0 is 6d8
offset 13 is 3c78 offset 14 is 4098 Read image data 0. Read 0420 bytes of 0420 byte counts, offset 0006d8
13. Read 0420 bytes of 0420 byte counts, offset 003c78 14. Read 018c bytes of 018c byte counts, offset 004098 EncodeGIF clear code 100 end of information code 101 clear code 00 69 08 1c 48 b0 a0 c1 83 08 13 2a 5c c8 b0 a1 c3 87 10 23 4a 9c 48 b1 a2 c5 8b 18 33 6a dc c8 b1 a3 c7 8f 20 43 8a 1c 49 b2 a4 c9 93 28 53 aa 5c 89 12 c5 89 14 2f 53 a0 60 1. wrote 0x0420 bytes 49 53 24 cc 14 38 53 a8 d0 a9 b3 a6 4f 8d 38 4f c4 5c b1 73 85 51 16 44 7f 2a 9d a8 d3 e5 4b 15 46 a1 aa 60 d1 02 69 8a a5 58 1b 36 3d 81 e2 83 09 13 42 85 b6 70 c1 02 a9 0a 15 21 4f 7c 5d 6b a2 26 d1 a0 5c 99 e2 ec ea 15
ec 55 b3 80
5c 16 38 83
9c 57 57 87
53 37 90 8e
cb 7e 5d fc
5a 05 91 d4
f5 7c 19 e8
f8 18 a3 64
f2 31 89 15
c3 60 0d 64
88 0f 80 01 bf 54 c9 42 a8 09 12 1f 38 70 00 7b 22 22 ce c0 24 ec ea 24 fa 36 45 11 1f 48 e0 34 89 99 84 07 0e 19 32 54 98 70 81 c3 07 14 53 1d c2 0c 1c da 6e 51 ae 23 a7 f0 0c 98 84 71 d1 24 51 78 46 9d c1 02 85 09 cf 33 90 38 d1 02 2d c3 e1 7b
Figure 3: MSVC++ Binary View of File hi_retiff.gif used to verify correctness of output file format bytes
Embedded LZW
Several factors changed to nature of the assignment including the file format of TIFF in that it is not directly serializable and can be up to 2 GB in size.
Device Driver Device driver API allow access to VHDL and Verilog IP cores from an embedded processor application. UART Timing universal asynchronous receiver/transmitter interrupt based data I/O DataFlow: TIFF file -> Re/TIFF (host cpu) -> UART -> LZW (fpga) -> UART -> Re/TIFF (host cpu) -> GIF file The Xilinx Platform Studio (XPS) includes a wizard to design an embedded processor system. The EDK provides the VHDL IP cores listed Table in listed in cores which map to the Spartan-3 LC development hardware. The mapping is set via an Microprocessor Hardware Specification (MHS) file (e.g. System.mhs). An MHS file defines the configuration of the embedded processor system, and includes the Bus architecture, Peripherals, Processor, Connectivity, and Address space.4 The Base System Builder (BSB) wizard is a software tool that help users quickly build a working embedded processor system targeted at a specific development board. Peripheral microblaze opb_mdm lmb_bram_if_cntlr lmb_bram_if_cntlr bram_block opb_uartlite opb_gpio opb_gpio opb_gpio opb_gpio opb_intc HW Ver 3.00.a 2.00.a 1.00.b 1.00.b 1.00.a 1.00.b 3.01.b 3.01.b 3.01.b 3.01.b 1.00.c Instance Microblaze_0 debug_module dlmb_cntlr ilmb_cntlr lmb_bram RS232 LEDs_4Bit LED_7Segment Push_Buttons_1Bit DIP_Switches_4Bit opb_intc_0
Serial Port Communication Parameters: 115,200 baud, 8 data bits, 1 parity bit, 50 MHz clock rate. 115200
8 0 1 50000000
Figure 5: MicroBlaze Processor Reference Guide. Embedded Development Kit EDK 6.3i. UG081 (v4.2) November 18 2004, pp 12.
Figure 7: RS232 interface to the UART device, processor core, and BRAM5.
The text number plus the data and bss represent the total memory consumed by the embedded design.
At GMT date and time: 2007:1:14:15:55:43 Command bash -c "cd /xygdrive/d/design/m3d5/; mb-size D:/design/m3d5/tiff2gif/ executable.elf; exit;" Started... text data bss dec hex filename 3356 3216 12 6584 19b8 D:/design/m3d5/tiff2gif/executable.elf Done.
malloc/xil_malloc These calls are unimplemented for the Spartan-3 with this version of the EDK. There are Xilinx tech notes explaining that their usage does not properly release memory back to the embedded processor.
Figure 8: System.pbd
Table 1: Summary of Spartan-3 FPGA Attributes Device System Gates Equivalent Logic Cells CLB Array (One CLB = Four Slices) Distributed RAM (bits1) Block RAM (bits1) Dedicated
Multipliers DCMs Maximum User I/O Maximum Differential I/O Pairs XC3S4002 400K 8,064 32 28 896 56K 288K 16 4 264 1166
EDK Debugger
the values */ typedef union _udata { UBYTE b_val[4]; USHORT s_val[2]; ULONG l_val; } udata; /* unsigned data */ /* Image File Directory Entries */ typedef struct _ifd { USHORT tag_id; USHORT type; UBYTE n[4]; udata vo; /* value offset */ } ifd; /* RAW image format */ typedef struct _retiff { USHORT height, width; USHORT bps; /* bits per sample */ ULONG size; /* # of rows in image data array, * in byte counts array, & * in strip offsets array */ ifd *p_cmh; /* color map header */ USHORT *p_cm; /* color map palette */ ULONG *p_bytecounts; /* array of size of strip data */
ULONG *p_stripoffsets; /* TIFF file data strip offsets */ UBYTE **p_imagedata; /* [rows][columns] */ /* image data */ } retiff; typedef struct _lzwGIF { unsigned int height, width; unsigned int size; /* malloc size */ unsigned int length; /* used size (non-free)*/ unsigned char *data; /* compressed data */ unsigned int cm_size; /* color map size */ unsigned char *cm; /* color map */ } lzwGIF; #define MaxCode(number_bits) ((1UL << (number_bits))-1) /* Mystery: Why 5003 ?? 0001 0011 1000 1011 0x138b */ #define MaxHashTable /* 5003 */ /* 2051 */ 617 /* fits! */ #define MaxGIFBits /* 12UL */ /* 11UL */ 9UL /* fits! */ #define MaxGIFTable (1UL << MaxGIFBits) #define GIFOutputCode(code) \ { \ /* \ Emit a code. \ */ \ if (bits > 0) \ datum |= (code) << bits; \ else \ datum=code; \
bits+=number_bits; \ while (bits >= 8) \ { \ /* \ Add a character to current packet. \ */ \ if (code == clear_code) { \ printf("\nclear code %.2x\n", (unsigned char) (datum & 0xff)); \ } else { \ printf("%.2x ", (datum & 0xff)); \ } \ fflush(stdout); \ packet[length++]=(unsigned char) (datum & 0xff); \ if (length >= 254) \ { \ length &= 0xff; \ memcpy(&p_gif->data[p_gif->length], &length , 1); \ p_gif->length++; \ { \ int i; \ for (i=0; i < length; ++i, ++p_gif->length) { \ /* printf("%.2x ",packet[i]); */ \ p_gif->data[p_gif->length] = packet[i]; \ } \ } \ /* \ memcpy(&p_gif->data[p_gif->length], &packet[0], length); \ p_gif->length += length; \ */ \ /* \
{ \ int i; \ for (i = 0; i < length; ++i) { \ printf("%.2x ", packet[i]); \ } \ puts(""); \ } \ */ \ printf("\nlength %d\n\n",length); \ fflush(stdout); \ length=0; \ } \ datum>>=8; \ bits-=8; \ } \ if (free_code > max_code) \ { \ number_bits++; \ if (number_bits == MaxGIFBits) \ max_code=MaxGIFTable; \ else \ max_code=MaxCode(number_bits); \ } \ } int EncodeImage(retiff *p_retiff, lzwGIF *p_gif, const unsigned long data_size); /* File: retiff.c Description : Reads an input TIFF so that the Image File Directory (IFD)
entries are ordered first and the bitmap data last. Creates a GIF output. Compile line : gcc -ansi -g -o retiff retiff.c Written by : JSC 11/23/06 */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include "retiff.h" int main(int argc, char *argv[]) { FILE *fh; UBYTE ifd_size; int i, j; udata *p_dat; ifd **p_ifd; unsigned int rows; unsigned int cols; unsigned int size; /* measured in bytes */ udata ssize; /* byte counts */ unsigned int bc_index; /* output */ ULONG s_offset; ULONG cm_offset; retiff *p_retiff; lzwGIF *p_gif; if (argc < 3) { printf("Usage: %s <in.tiff> <out.gif> [DEBUG]\n\n", argv[0]); puts("\tRewrites input TIFF IFD entries to top of file.\n");
exit(-1); } if (argc == 4) { DEBUG = 1; } else { DEBUG = 0; } p_dat = (udata *) calloc(1, sizeof(udata)); fh = fopen(argv[1],"rb"); fseek(fh, IFD_OFFSET_L, SEEK_CUR); /* assume little-endian */ /* Read in IFD offset val */ fread(&p_dat->b_val[0], 4*sizeof(UBYTE), 1, fh); if (DEBUG) printf("IFD offset %x\n", p_dat->l_val); /* Seek forward to IFD entries */ fseek(fh, (long) p_dat->l_val, SEEK_SET); /* Read number of IFD entries value */ fread(&p_dat->b_val[0], 2*sizeof(UBYTE), 1, fh); if (DEBUG) printf("IFD records %d\n", p_dat->s_val[0]); /* allocate ifd structure */ ifd_size = p_dat->s_val[0]; p_ifd = (ifd **) calloc(ifd_size, sizeof(ifd*)); for (i=0; i < ifd_size; ++i) { p_ifd[i] = (ifd *) calloc(1, sizeof(ifd)); } p_retiff = (retiff *) calloc(1, sizeof(retiff)); /* using calloc to initialize members to 0's */ p_gif = (lzwGIF *) calloc(1, sizeof(lzwGIF)); for (i=0; i < ifd_size && !feof(fh); ++i) {
fpos_t pos; fgetpos(fh, &pos); if (DEBUG) printf("%x\t", pos); if (!fread(p_ifd[i], sizeof(ifd), 1, fh)) { break; } if (DEBUG) printf("Tag %x\tType %x\n", p_ifd[i]->tag_id, p_ifd[i]->type); switch (p_ifd[i]->tag_id) { case TAG_ROWSPERSTRIP : { if (DEBUG) printf("\trows per strip %d\n", p_ifd[i]->vo.l_val); break; } case TAG_IMAGEWIDTH : { cols = p_ifd[i]->vo.l_val; p_gif->width = p_ifd[i]->vo.l_val; if (DEBUG) printf("\tcols %d\n", cols); break; } case TAG_IMAGELENGTH : { rows = p_ifd[i]->vo.l_val; p_gif->height = (unsigned short) p_ifd[i]->vo.l_val; if (DEBUG) printf("\trows %d\n", rows); break; } case TAG_BITSPERSAMPLE : {
size = (rows * cols * p_ifd[i]->vo.l_val) / BITSPERBYTE; p_retiff->bps = p_ifd[i]->vo.s_val[0]; /* higher order bits assumed to be 0 based on TIFF spec and sample file */ if (DEBUG) { printf("\tbps %d\n", p_ifd[i]->vo.l_val); printf("\tsize %d from row x cols\n", size); } break; } case TAG_STRIPOFFSETS : { ssize.b_val[0] = p_ifd[i]->n[0]; ssize.b_val[1] = p_ifd[i]->n[1]; ssize.b_val[2] = p_ifd[i]->n[2]; ssize.b_val[3] = p_ifd[i]->n[3]; s_offset = p_ifd[i]->vo.l_val; if (DEBUG) { printf("\tstrip count %d\n", ssize.l_val); printf("\tstrip offset %d\n", s_offset); } break; } case TAG_STRIPBYTECOUNTS : { bc_index = i; if (DEBUG) printf("\tstrip byte counts offset %x\n", p_ifd[i]->vo.l_val); break; } case TAG_COLORMAP : { udata csize; cm_offset = p_ifd[i]->vo.l_val;
csize.b_val[0] = p_ifd[i]->n[0]; csize.b_val[1] = p_ifd[i]->n[1]; csize.b_val[2] = p_ifd[i]->n[2]; csize.b_val[3] = p_ifd[i]->n[3]; if (DEBUG) { printf("\tcolormap size %d\n", csize.l_val); printf("\tcolormap offset %d\n", cm_offset); } /* assumption is 256 RGB tuplets */ /* assign color map structure */ p_retiff->p_cmh = p_ifd[i]; p_retiff->p_cm = (USHORT *) calloc(csize.l_val, sizeof(USHORT)); /* read color map data */ fseek(fh, (long) p_ifd[i]->vo.l_val, SEEK_SET); fread(p_retiff->p_cm, sizeof(USHORT), csize.l_val, fh); /* transfer to GIF */ p_gif->cm_size = csize.l_val; p_gif->cm = (unsigned char *) calloc(csize.l_val, sizeof(unsigned char)); for (i=0, j=0; i < p_gif->cm_size-2; ++j) { p_gif->cm[i] = (UBYTE) p_retiff->p_cm[j]; /* Red */ p_gif->cm[i+1] = (UBYTE) p_retiff->p_cm[j + 256]; /* Green */ p_gif->cm[i+2] = (UBYTE) p_retiff->p_cm[j + 512]; /* Blue */ i = i + 3; } break; } } } fflush(stdout); /*
Save/Print out the byte count values */ { unsigned int *p_offsets = NULL; udata size; memcpy(&size, p_ifd[bc_index]->n, sizeof(ULONG)); p_offsets = (unsigned int *) calloc(size.l_val, sizeof(unsigned int)); /* seek forward to the byte counts */ fseek(fh, (long) p_ifd[bc_index]->vo.l_val, SEEK_SET); fread(p_offsets, sizeof(unsigned int), size.l_val, fh); if (DEBUG) puts("\nStrip byte sizes:"); p_retiff->size = size.l_val; p_retiff->p_bytecounts = (ULONG *) calloc(size.l_val, sizeof(ULONG)); for (i=0; i < size.l_val; ++i) { if (DEBUG) printf("\toffset %d byte size %d\n", i, p_offsets[i]); p_retiff->p_bytecounts[i] = p_offsets[i]; p_gif->size += p_offsets[i]; } if (DEBUG) printf("\tTIFF image size %d from byte counts\n",p_gif->size); free(p_offsets); } /* Save/print out the strip offsets */ { unsigned int *p_offsets = NULL; p_offsets = (unsigned int *) calloc(ssize.l_val, sizeof(unsigned int));
p_retiff->p_stripoffsets = (ULONG *) calloc(ssize.l_val, sizeof(ULONG)); fseek(fh, (long) s_offset, SEEK_SET); fread(p_offsets, sizeof(unsigned int), ssize.l_val, fh); if (DEBUG) puts("\nStrip offsets:"); for (i=0; i < ssize.l_val; ++i) { p_retiff->p_stripoffsets[i] = p_offsets[i]; if (DEBUG) printf("\toffset %d is %x\n", i, p_offsets[i]); } free(p_offsets); p_offsets=NULL; } /* Read image data into retiff data struct */ { int b_read; /* bytes read */ p_retiff->p_imagedata = (UBYTE **) calloc(p_retiff->size, sizeof(UBYTE *)); puts("\nRead image data"); for (i=0; i < p_retiff->size; ++i) { b_read = 0; p_retiff->p_imagedata[i] = (UBYTE *) calloc(p_retiff->p_bytecounts[i], sizeof(UBYTE)); fseek(fh, (long) p_retiff->p_stripoffsets[i], SEEK_SET); b_read = fread(p_retiff->p_imagedata[i], sizeof(UBYTE), p_retiff->p_bytecounts[i], fh); if (feof(fh)) { if (DEBUG) puts("End of file encountered"); } if (DEBUG)
printf("%d.\tRead %.4x bytes of %.4x byte counts, offset %.6x\n", i, b_read, p_retiff->p_bytecounts[i], p_retiff->p_stripoffsets[i]); } } /* * LZW Compress to GIF structure */ { p_gif->data = (unsigned char *) calloc(p_gif->size, sizeof (unsigned char)); #define LZW_CODE_BIT_SIZE 9 EncodeImage(p_retiff, p_gif, LZW_CODE_BIT_SIZE); /* 9 */ if (DEBUG) printf("\n%x bytes of %x bytes compressed\n", p_gif->length, p_gif->size); } /* * Write the GIF file */ { unsigned char buf[256]; FILE *fh_gif; fh_gif = fopen(argv[2], "wb"); /* Header */ sprintf(buf, "%s", "GIF89a"); fwrite(buf, sizeof(unsigned char), 6, fh_gif); /* Logical Screen Descriptor */ fwrite(&p_gif->width, sizeof(unsigned short), 1, fh_gif); fwrite(&p_gif->height, sizeof(unsigned short), 1, fh_gif); buf[0]=0xf7; /* packed field */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); buf[0]=0x00; /* background color index */
fwrite(buf, sizeof(unsigned char), 1, fh_gif); buf[0]=0x00; /* pixel aspect ratio */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Global Color Table */ fflush(fh_gif); fwrite(p_gif->cm, sizeof(unsigned char), p_gif->cm_size, fh_gif); fflush(fh_gif); /* Image Descriptor */ buf[0]=0x2c; /* Image Separator */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); fflush(fh_gif); buf[0]=0x00; /* Image Left Position */ buf[1]=0x00; fwrite(buf, sizeof(unsigned char), 2, fh_gif); buf[0]=0x00; /* Image Top Position */ buf[1]=0x00; fwrite(buf, sizeof(unsigned char), 2, fh_gif); fwrite(&p_gif->width, sizeof(unsigned short), 1, fh_gif); fwrite(&p_gif->height, sizeof(unsigned short), 1, fh_gif); buf[0]=0x00; /* Packed Fields */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Table Based Image Data */ buf[0]=LZW_CODE_BIT_SIZE-1; /* LZW Minimum Code Size */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Image Data */ { unsigned char *p_data; p_data = &p_gif->data[0]; for (i=0 ; i < p_gif->length ; ++i) { fwrite(p_data++, sizeof(unsigned char), 1, fh_gif);
fflush(fh_gif); } } /* Trailers */ buf[0] = 0x00; buf[1] = 0x3b; fwrite(buf, sizeof(unsigned char), 2, fh_gif); fflush(fh_gif); fclose(fh_gif); fh_gif = NULL; } /* free memory used */ if (p_retiff->p_cm != NULL) { free(p_retiff->p_cm); p_retiff->p_cm = NULL; } if (p_retiff->p_bytecounts != NULL) { free(p_retiff->p_bytecounts); p_retiff->p_bytecounts = NULL; } if (p_retiff->p_stripoffsets != NULL) { free(p_retiff->p_stripoffsets); p_retiff->p_stripoffsets = NULL; } if (p_retiff->p_imagedata != NULL) { for (i=0; i<p_retiff->size; i++) { if (p_retiff->p_imagedata[i] != NULL) { free(p_retiff->p_imagedata[i]); p_retiff->p_imagedata[i] = NULL; }
} free(p_retiff->p_imagedata); p_retiff->p_imagedata = NULL; } free(p_retiff); p_retiff = NULL; if (p_gif->cm != NULL) { free(p_gif->cm); p_gif->cm = NULL; } { /* free gif lzw data */ if (p_gif->data != NULL) { free(p_gif->data); p_gif->data = NULL; } } free(p_gif); p_gif = NULL; for (j=0; j < ifd_size; ++j) { free(p_ifd[j]); p_ifd[j] = NULL; } free(p_ifd); p_ifd=NULL; fclose(fh); fh=NULL; free(p_dat); p_dat = NULL; if (DEBUG) puts("Done.");
exit(0); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % E n c o d e I m a g e % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % EncodeImage LZW compresses an image via GIF-coding. % % The format of the EncodeImage method is: % % int EncodeImage( % retiff *p_retiff, % lzwGIF *p_gif, % const unsigned long data_size) % % A description of each parameter follows: % % o p_retiff: The address of a structure defining the image data. % % o p_gif: output gif image block % % o data_size: The number of bits in the compressed packet. % % Comments: % % JSC 10/28/06 Modified from ImageMagick-6.2.8 coders/gif.c and adapted % for Re-TIFFing
% */ int EncodeImage(retiff *p_retiff, lzwGIF *p_gif, const unsigned long data_size) { unsigned char index; long displacement, k, y; register long i, x; size_t length; short *hash_code, *hash_prefix, waiting_code; unsigned char *packet, *hash_suffix; unsigned long bits, clear_code, datum, end_of_information_code, free_code, max_code, next_pixel, number_bits;
/* Allocate encoder tables. */ assert(p_retiff != (retiff *) NULL); packet=(unsigned char *) calloc(256, sizeof(*packet)); /* codes */ hash_code=(short *) calloc(MaxHashTable, sizeof(*hash_code)); /* omega */ hash_prefix=(short *) calloc(MaxHashTable, sizeof(*hash_prefix)); /* K */ hash_suffix=(unsigned char *) calloc(MaxHashTable, sizeof(*hash_suffix)); /* test for calloc failure e.g. OutOfMemory Exception */ if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) || (hash_prefix == (short *) NULL) || (hash_suffix == (unsigned char *) NULL)) { if (packet != (unsigned char *) NULL) free(packet); if (hash_code != (short *) NULL) free(hash_code); if (hash_prefix != (short *) NULL) free(hash_prefix); if (hash_suffix != (unsigned char *) NULL) free(hash_suffix); return (0); /* FALSE */ } /* Initialize GIF encoder. */ number_bits=data_size; max_code=MaxCode(number_bits);
clear_code=((short) 1UL << (data_size-1)); end_of_information_code=clear_code+1; if (DEBUG) { puts("\nEncodeGIF"); printf("\tclear code %x\n",clear_code); printf("\tend of information code %x\n",end_of_information_code); } free_code=clear_code+2; length=0; datum=0; bits=0; for (i=0; i < MaxHashTable; i++) hash_code[i]=0; GIFOutputCode(clear_code); /* Encode pixels. */ waiting_code=0; for (y=0; y < (long) p_retiff->size; y++) { if (y == 0) /* LZW algo: Initialize table to contain single-char strings. Read first input char -- prefix string w (omega) w == waiting_code or prefix */ waiting_code=(short) p_retiff->p_imagedata[0][0]; for (x=(y == 0) ? 1 : 0; x < (long) p_retiff->p_bytecounts[y]; x++) { index=p_retiff->p_imagedata[y][x] & 0xff; /* Probe hash table.
*/ /* LZW algo (continued) Step: Read next input character k if no such k (input exhausted): code(w) -> output : EXIT if wk exists in string table: wk -> w; repeat Step else wk not in string table : code(w) -> output; wk -> string table; k -> w; repeat Step */ k=(long) (index << (MaxGIFBits-8))+waiting_code; if (k >= MaxHashTable) k-=MaxHashTable; next_pixel=0; /* MagickFalse; */ displacement=1; /* if wk exists in string table ? */ if (hash_code[k] > 0) { if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == (unsigned char) index)) { /* yes -- repeat Step */ waiting_code=hash_code[k]; continue; } if (k != 0) displacement=MaxHashTable-k; for ( ; ; ) { k-=displacement; if (k < 0) k+=MaxHashTable; if (hash_code[k] == 0)
break; if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == (unsigned char) index)) { waiting_code=hash_code[k]; next_pixel=1; /* MagickTrue; */ break; } } if (next_pixel == 1) /* MagickTrue */ continue; } GIFOutputCode((unsigned long) waiting_code); if (free_code < MaxGIFTable) { hash_code[k]=(short) free_code++; hash_prefix[k]=waiting_code; hash_suffix[k]=(unsigned char) index; } else { /* Fill the hash table with empty entries. */ for (k=0; k < MaxHashTable; k++) { hash_code[k]=0; } /* Reset compressor and issue a clear code. */ free_code=clear_code+2; GIFOutputCode(clear_code); number_bits=data_size; max_code=MaxCode(number_bits);
} waiting_code=(short) index; } if (DEBUG) printf("\n%d. wrote 0x%.4x bytes\n", y + 1, p_retiff->p_bytecounts[y]); } /* Flush out the buffered code. */ GIFOutputCode((unsigned long) waiting_code); GIFOutputCode(end_of_information_code); if (bits > 0) { /* Add a character to current packet. */ packet[length++]=(unsigned char) (datum & 0xff); if (length >= 254) { memcpy(&p_gif->data[p_gif->length], &length, 1); p_gif->length++; memcpy(&p_gif->data[p_gif->length], &packet[0], length); p_gif->length += length; length=0; } } /* Flush accumulated data. */
if (length > 0) { printf("%.2x ",length); memcpy(&p_gif->data[p_gif->length], &length, 1); p_gif->length++; memcpy(&p_gif->data[p_gif->length], &packet[0], length); p_gif->length += length; { int i; for (i = 0; i < length; ++i) { printf("%.2x ", packet[i]); } puts(""); } } /* Free encoder memory. */ free(hash_suffix); free(hash_prefix); free(hash_code); free(packet); return (1); /* TRUE */ }
File: mb_tg.h Description : MicroBlaze (uB) TIFF to GIF header data definitions Compile line : Xilinx EDK 6.3 EDK_Gmm.12.3 Written by : JSC 12/02/06 */ #define TRUE 1 #define FALSE 0 /* UART data input */ volatile Xuint8 d_buf; /* single byte data buffer */ volatile Xuint8 d_flag; /* signals data received from UART */ /* LED : */ /* 6543210 */ #define LED_ZERO 0x01 // 0 = 0000001 = 1 = 0x01 #define LED_ONE 0x4f /* 1 = 1001111 = 79 = 0x4f */ #define LED_TWO 0x12 // 2 = 0010010 = 18 = 0x12 #define LED_THREE 0x06 // 3 = 0000110 = 6 = 0x06 #define LED_FOUR 0x4c // 4 = 1001100 = 76 = 0x4c #define LED_FIVE 0x24 // 5 = 0100100 = 36 = 0x24 #define LED_SIX 0x20 // 6 = 0100000 = 32 = 0x20 #define LED_SEVEN 0x0f // 7 = 0001111 = 15 = 0x0f #define LED_EIGHT 0x00 // 8 = 0000000 = 0 = 0x00 #define LED_NINE 0x04 // 9 = 0000100 = 4 = 0x04 /* 6543210 */ #define LED_A 0x08 // A = 0001000 = 8 = 0x08 #define LED_C 0x31 // C = 0110001 = 49 = 0x31 #define LED_E 0x30 // E = 0110000 = 48 = 0x30 #define LED_a 0x02 // a = 0000010 #define LED_b 0x60 // b = 1100000
#define LED_c 0x72 // c = 1110010 #define LED_d 0x42 // d = 1000010 #define LED_e 0x10 // e = 0010000 #define LED_f 0x38 // f = 0111000 #define LED_SEG_ZERO 0x7f #define LED_SEG_ONE 0x7f - 0x01 #define LED_SEG_TWO 0x7f - 0x02 #define LED_SEG_THREE 0x7f - 0x04 #define LED_SEG_FOUR 0x7f - 0x08 #define LED_SEG_FIVE 0x7f - 0x10 #define LED_SEG_SIX 0x7f - 0x20 #define LED_SEG_SEVEN 0x7f - 0x40 #define CR 0x0d /* carriage return */ #define NL 0x0a /* new line (text mode) */ #define PAUSE(LEN) \ { \ int l; \ for (l=0; l < LEN; ++l) { \ /* wait */; \ } \ } #define UPDATE_LED(led, led_state) \ switch (led) { \ case 0: \ led++; led_state = LED_SEG_ZERO; break; \ case 1: \ led++; led_state = LED_SEG_ONE; break; \ case 2: \ led++; led_state = LED_SEG_TWO; break; \ case 3: \
led++; led_state = LED_SEG_THREE; break; \ case 4: \ led++; led_state = LED_SEG_FOUR; break; \ case 5: \ led++; led_state = LED_SEG_FIVE; break; \ case 6: \ led++; led_state = LED_SEG_SIX; break; \ default: \ led = 0; led_state = LED_SEG_SEVEN; break; \ } \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, led_state) #define LED_PRINT(val) \ switch (0x0f & val) { \ case 0: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_ZERO); \ break; \ case 1: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_ONE); \ break; \ case 2: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_TWO); \ break; \ case 3: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_THREE); \ break; \ case 4: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_FOUR); \ break; \ case 5: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_FIVE); \
break; \ case 6: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_SIX); \ break; \ case 7: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_SEVEN); \ break; \ case 8: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_EIGHT); \ break; \ case 9: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_NINE); \ break; \ case 0xa: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_a); \ break; \ case 0xb: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_b); \ break; \ case 0xc: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_c); \ break; \ case 0xd: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_d); \ break; \ case 0xe: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_e); \ break; \ case 0xf: \ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_f); \
} /* image dimensions */ #define X_SIZE 4 /* read from UART */ #define Y_SIZE 4 #define XY_SIZE 8 Xuint8 x_buf[4] = { 0, 0, 0, 0}; Xuint8 y_buf[4] = { 0, 0, 0, 0}; Xuint32 x_dim = 0; Xuint32 y_dim = 0; /* dc = dimension component (x or y) */ /* dc_buf = dc buffer for storing unsigned byte tuples * byte order is little endian */ /* dim_size = iterator counter (X_SIZE or Y_SIZE) */ #define GET_IMG_DIM(DC, DC_BUF, DIM_SIZE) \ for (zd_flag = 0; zd_flag < DIM_SIZE; ++zd_flag) { \ while (!d_flag); /* wait for data i/o */ \ d_flag = FALSE; /* lower flag */ \ \ /* capture image size */ \ DC_BUF[zd_flag] = d_buf; \ } \ DC = \ DC_BUF[0] + \ (DC_BUF[1] << 8) + \ (DC_BUF[2] << 16) + \ (DC_BUF[3] << 24); /* Q: Where does the number 5003 come from? A: When LZW max codeword size is 12 bits, aka the value spec by "MaxGIFBits" constant, then...
5003 = 2^12 + 2^12 * 20%, stepped up to nearest prime number for optimal hash table size */ #define MaxHashTable /* 5003 */ /* 2459 */ /* 1229 */ 617 /* fits! */ #define MaxGIFBits /* 12UL */ /* 11UL */ /* 10UL */ 9UL /* fits! */ #define MaxGIFTable ( 1UL << MaxGIFBits ) #define MaxCode(number_bits) (( 1UL << ( number_bits ))-1) #define LZW_CODE_BIT_SIZE 9 /* fr. EncodeImage, sets max LZW codeword size */ Xint16 hash_code[MaxHashTable] = { /* 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 13 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 14 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 15 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 17 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 18 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 19 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 21 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 22 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 23 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 25 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 26 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 27 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 29 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 31 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 33 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 35 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 37 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */ }; Xint16 hash_prefix[MaxHashTable] = { /* 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 13 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 14 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 15 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 17 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 18 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 19 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 21 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 22 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 23 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 25 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 26 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 27 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 29 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 31 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 33 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 35 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 37 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */ }; Xuint8 hash_suffix[MaxHashTable] = { /* 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 11 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 13 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 14 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 15 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 */
if (bits > 0) \ datum |= (code) << bits; \ else \ datum=code; \ bits+=number_bits; \ while (bits >= 8) { \ /* \ Add a character to current packet. \ */ \ XUartLite_SendByte \ (XPAR_RS232_BASEADDR, \ (datum & 0xff)); \ datum>>=8; \ bits-=8; \ } \ if (free_code > max_code) { \ number_bits++; \ if (number_bits == MaxGIFBits) \ max_code=MaxGIFTable; \ else \ max_code=MaxCode(number_bits); \ } \ } /* File: mb_tg.c Description : MicroBlaze (uB) TIFF to GIF UART interrupt data driven converter * These drivers will be generated in your * XPS project when you run the "Generate Libraries" menu item
* in XPS. * Your XPS project directory is at: * D:\design\memec_3slc_design3 Compile line : Xilinx EDK 6.3 EDK_Gmm.12.3 Written by : JSC 12/02/06 12/13/06 Updated to incorporate LZW */ #include <xuartlite_l.h> /* uartlite peripheral control functions */ #include <xintc_l.h> /* interrupt controller peripheral control functions */ // Located in: microblaze_0/include/xparameters.h #include "xparameters.h" #include "xutil.h" #include "xgpio_l.h" #include "mb_tg.h" void uart_int_handler(void *baseaddr_p) { /* While UART receive FIFO has data */ while (!XUartLite_mIsReceiveEmpty(baseaddr_p)) { /* Read character (s) */ d_flag = TRUE; d_buf = XUartLite_RecvByte((Xuint32) baseaddr_p); } } /* * Routine to write a pattern out to a GPIO * which is configured as an output * PARAMETER C_ALL_INPUTS = 0 */ void WriteToGPOutput(Xuint32 BaseAddress, int gpio_width) { int i=0, j=0, k=0; int numTimes = 5;
XGpio_mSetDataDirection(BaseAddress, 1, 0x00000000); /* Set as outputs */ while (numTimes > 0) { j = 1; for(i=0; i<(gpio_width-1); i++) { XGpio_mSetDataReg(BaseAddress, 1, j); j = j << 1; for (k=0; k<100000; k++) { ; //wait } } j = 1; j = ~j; for(i=0; i<(gpio_width-1); i++) { XGpio_mSetDataReg(BaseAddress, 1, j); j = j << 1; for (k=0; k<100000; k++) { ; //wait } } numTimes--; } } /* * Routine to read data from a GPIO * which is configured as an input * PARAMETER C_ALL_INPUTS = 1 */ Xuint32 ReadFromGPInput(Xuint32 BaseAddress) { Xuint32 data = XGpio_mGetDataReg(BaseAddress, 1); return data;
} //==================================================== int main (void) { Xuint8 /* unsigned 8-bit */ i, index; Xint16 /* signed short */ waiting_code; Xint32 /* long */ displacement, k; Xuint32 /* unsigned long */ x, y; Xuint32 /* unsigned long */ bits, clear_code, datum, end_of_information_code, free_code, max_code, next_pixel, number_bits; Xint8 led, led_state; Xuint8 zd_flag; /* zero data flag */ /* Initialize LZW encoder. */ for (k=0; k < MaxHashTable; k++) {
hash_code[k]=0; hash_prefix[k]=0; hash_suffix[k]=0; } number_bits = /* data_size */ LZW_CODE_BIT_SIZE; max_code = MaxCode(number_bits); clear_code = ((Xint16) 1UL << (/* data_size */ LZW_CODE_BIT_SIZE - 1)); end_of_information_code = clear_code + 1; free_code = clear_code+2; datum = 0; bits = 0; waiting_code = 0; index = 0; /* image data value */ /* interrupt state initialization */ led = 0; zd_flag = 0; /* zero data flag used to determine when to set prefix */ d_flag = FALSE; d_buf = 0; /* Sets up interrupts */ XGpio_mSetDataDirection(XPAR_LED_7SEGMENT_BASEADDR, 1, 0x0); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_ONE); microblaze_enable_interrupts(); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_TWO); /* Register UART interrupt handler */ XIntc_RegisterHandler ( XPAR_OPB_INTC_0_BASEADDR, XPAR_OPB_INTC_0_RS232_INTERRUPT_INTR, (XInterruptHandler) uart_int_handler, (void *) XPAR_RS232_BASEADDR);
/* Register External interrupt handler */ XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_THREE); XIntc_mMasterEnable(XPAR_OPB_INTC_0_BASEADDR); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_FOUR); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_FIVE); XIntc_mEnableIntr(XPAR_OPB_INTC_0_BASEADDR, XPAR_RS232_INTERRUPT_MASK); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_SIX); XUartLite_mEnableIntr(XPAR_RS232_BASEADDR); //XUartLite_ResetFifos(XPAR_RS232_BASEADDR); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_THREE); GET_IMG_DIM(y_dim, y_buf, Y_SIZE); UPDATE_LED(led, led_state); GIFOutputCode(clear_code); for (y = 0; y < y_dim; ++y) { GET_IMG_DIM(x_dim, x_buf, X_SIZE); if (y == 0) { /* * LZW algo: Initialize table to contain single-char strings. * Read first input char -- prefix string w (omega) * w == waiting_code aka "prefix" */ while (!d_flag); /* wait for data i/o */ d_flag = FALSE; /* lower flag */ /* assign waiting data */ waiting_code=(short) d_buf; } for (x=((y == 0) ? 1 : 0); x < x_dim; ++x) { while (!d_flag); /* wait for data i/o */ d_flag = FALSE; /* lower flag */ /* assign waiting data */
index = d_buf; /* Probe hash table. */ /* * LZW algo (continued) * Step: Read next input character k * if no such k (input exhausted): code(w) -> output : EXIT * if wk exists in string table: wk -> w; repeat Step * else wk not in string table : code(w) -> output; * wk -> string table; * k -> w; repeat Step */ k=(long) (index << (MaxGIFBits-8))+waiting_code; if (k >= MaxHashTable) k-=MaxHashTable; next_pixel=0; /* MagickFalse; */ displacement=1; /* if wk exists in string table ? */ if (hash_code[k] > 0) { if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == (unsigned char) index)) { /* yes -- repeat Step */ waiting_code=hash_code[k]; continue; } if (k != 0) displacement=MaxHashTable-k; for ( ; ; ) { k-=displacement;
if (k < 0) k+=MaxHashTable; if (hash_code[k] == 0) break; if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == (unsigned char) index)) { waiting_code=hash_code[k]; next_pixel=1; /* MagickTrue; */ break; } } if (next_pixel == 1) /* MagickTrue */ continue; } GIFOutputCode((unsigned long) waiting_code); if (free_code < MaxGIFTable) { hash_code[k]=(short) free_code++; hash_prefix[k]=waiting_code; hash_suffix[k]=(unsigned char) index; } else { /* Fill the hash table with empty entries. */ UPDATE_LED(led, led_state); for (k=0; k < MaxHashTable; k++) { hash_code[k]=0; } /* Reset compressor and issue a clear code. */
free_code=clear_code+2; GIFOutputCode(clear_code); number_bits= /* data_size */ LZW_CODE_BIT_SIZE; max_code=MaxCode(number_bits); } waiting_code=(short) index; } /* for (x...) */ } /* for (y...) */ END_OF_DATA: GIFOutputCode((unsigned long) waiting_code); GIFOutputCode(end_of_information_code); if (bits > 0) { /* Add a character to current packet. */ XUartLite_SendByte(XPAR_RS232_BASEADDR, (datum & 0xff)); } XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_ZERO); WriteToGPOutput(XPAR_LEDS_4BIT_BASEADDR, 4); WriteToGPOutput(XPAR_LED_7SEGMENT_BASEADDR, 7); XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, LED_ZERO); return 0; } /* File: retiff.h Description : Re-TIFF header data types Compile line : gcc -ansi -g -o retiff retiff.c Written by : JSC 11/29/06
Rev History : 01/04/07 JSC Updated for threaded FPGA LZW UART Tx/Rx data types and functions. */ #define UBYTE unsigned char /* 1 byte */ #define USHORT unsigned short /* 2 bytes */ #define ULONG unsigned long /* 4 bytes */ /* */ #define IFD_OFFSET_L 4L #define IFD_SIZE (UBYTE) 12 /* Used to reset offsets */ #define TAG_STRIPOFFSETS 273 #define TAG_COLORMAP 320 /* Used to re-align image data */ #define TAG_SAMPLESPERPIXEL 277 /* */ #define TAG_ROWSPERSTRIP 278 #define TAG_STRIPBYTECOUNTS 279 #define TAG_IMAGEWIDTH 256 /* cols */ #define TAG_IMAGELENGTH 257 /* rows */ #define TAG_BITSPERSAMPLE 258 /* */ #define BITSPERBYTE 8 /* Serial I/O COM */ #define BUF_SIZE 16 /* Serial I/O read buffer */ #define TIME_OUT 50 /* # times to check Rx buffer */ #define MAX_GIF_BLK_SIZE 0xff /* Max GIF image block size */ #define DIM_SIZE 4 /* Serial i/o writer */ /* Debug level */ int DEBUG = 0; /* For storing TIFF data and interpreting
the values */ typedef union _udata { UBYTE b_val[4]; USHORT s_val[2]; ULONG l_val; } udata; /* unsigned data */ /* Image File Directory Entries */ typedef struct _ifd { USHORT tag_id; USHORT type; UBYTE n[4]; udata vo; /* value offset */ } ifd; /* RAW image format */ typedef struct _retiff { USHORT height, width; USHORT bps; /* bits per sample */ ULONG size; /* # of rows in image data array, * in byte counts array, & * in strip offsets array */ ifd *p_cmh; /* color map header */ USHORT *p_cm; /* color map palette */ ULONG *p_bytecounts; /* array of size of strip data */
ULONG *p_stripoffsets; /* TIFF file data strip offsets */ UBYTE **p_imagedata; /* [rows][columns] */ /* image data */ } retiff; typedef struct _lzwGIF { unsigned int height, width; unsigned int size; /* malloc size */ unsigned int length; /* used size (non-free)*/ unsigned char *data; /* compressed data */ unsigned int cm_size; /* color map size */ unsigned char *cm; /* color map */ } lzwGIF; int fd; /* global file desciptor */ void serial_open(char *device); /* serial com i/o aka Tx/Rx */ void* serial_write(void *ptr); /* threaded writer Tx */ int EncodeImage(retiff *p_retiff, lzwGIF *p_gif, const unsigned long data_size); /* File: retiff.c Description : Reads an input TIFF so that the Image File Directory (IFD) entries are ordered first and the bitmap data last. Added threaded serial I/O. Parts derived from tsl.c, whose header is also included. Creates a GIF output. Compile line : gcc -ansi -g -o retiff retiff.c Written by : JSC 11/23/06 01/03/07 Added Multi-threaded, and FPGA Tx/Rx 12/13/06 Added FPGA UART Serial I/O. Moved LZW into FPGA. */
/* $Id: tsl.c,v 1.12 2004/01/26 06:58:50 james Exp james $ tsl, temperature sensor data logger Copyright (C) 2000 James Cameron (quozl@us.netrek.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <termios.h> #include <fcntl.h> #include <pthread.h> #include "retiff.h" int main(int argc, char *argv[]) { FILE *fh; UBYTE ifd_size; int i, j; udata *p_dat; ifd **p_ifd;
unsigned int rows; unsigned int cols; unsigned int size; /* measured in bytes */ udata ssize; /* byte counts */ unsigned int bc_index; /* output */ ULONG s_offset; ULONG cm_offset; retiff *p_retiff; lzwGIF *p_gif; if (argc < 3) { printf("Usage: %s <in.tiff> <out.gif> [DEBUG]\n\n", argv[0]); puts("\tRewrites input TIFF IFD entries to top of file.\n"); exit(-1); } if (argc == 4) { DEBUG = 1; } else { DEBUG = 0; } p_dat = (udata *) calloc(1, sizeof(udata)); fh = fopen(argv[1], "rb"); fseek(fh, IFD_OFFSET_L, SEEK_CUR); /* assume little-endian */ /* Read in IFD offset val */ fread(&p_dat->b_val[0], 4*sizeof(UBYTE), 1, fh); if (DEBUG) printf("IFD offset %x\n", p_dat->l_val); /* Seek forward to IFD entries */ fseek(fh, (long) p_dat->l_val, SEEK_SET);
/* Read number of IFD entries value */ fread(&p_dat->b_val[0], 2*sizeof(UBYTE), 1, fh); if (DEBUG) printf("IFD records %d\n", p_dat->s_val[0]); /* allocate ifd structure */ ifd_size = p_dat->s_val[0]; p_ifd = (ifd **) calloc(ifd_size, sizeof(ifd*)); for (i=0; i < ifd_size; ++i) { p_ifd[i] = (ifd *) calloc(1, sizeof(ifd)); } p_retiff = (retiff *) calloc(1, sizeof(retiff)); /* using calloc to initialize members to 0's */ p_gif = (lzwGIF *) calloc(1, sizeof(lzwGIF)); for (i=0; i < ifd_size && !feof(fh); ++i) { fpos_t pos; fgetpos(fh, &pos); if (DEBUG) printf("%x\t", pos); if (!fread(p_ifd[i], sizeof(ifd), 1, fh)) { break; } if (DEBUG) printf("Tag 0x%.4x (%d) \tType %x\n", p_ifd[i]->tag_id, p_ifd[i]->tag_id, p_ifd[i]->type); switch (p_ifd[i]->tag_id) { case TAG_ROWSPERSTRIP : { if (DEBUG) printf("\trows per strip %d\n", p_ifd[i]->vo.l_val); break; } case TAG_IMAGEWIDTH : {
cols = p_ifd[i]->vo.l_val; p_gif->width = p_ifd[i]->vo.l_val; if (DEBUG) printf("\tcols %d\n", cols); break; } case TAG_IMAGELENGTH : { rows = p_ifd[i]->vo.l_val; p_gif->height = (unsigned short) p_ifd[i]->vo.l_val; if (DEBUG) printf("\trows %d\n", rows); break; } case TAG_BITSPERSAMPLE : { size = (rows * cols * p_ifd[i]->vo.l_val) / BITSPERBYTE; p_retiff->bps = p_ifd[i]->vo.s_val[0]; /* higher order bits assumed to be 0 based on TIFF spec and sample file */ if (DEBUG) { printf("\tbps %d\n", p_ifd[i]->vo.l_val); printf("\tsize %d from row x cols\n", size); } break; } case TAG_STRIPOFFSETS : { ssize.b_val[0] = p_ifd[i]->n[0]; ssize.b_val[1] = p_ifd[i]->n[1]; ssize.b_val[2] = p_ifd[i]->n[2]; ssize.b_val[3] = p_ifd[i]->n[3]; s_offset = p_ifd[i]->vo.l_val; if (DEBUG) {
printf("\tstrip count %d\n", ssize.l_val); printf("\tstrip offset %d\n", s_offset); } break; } case TAG_STRIPBYTECOUNTS : { bc_index = i; if (DEBUG) printf("\tstrip byte counts 0x%.4x\n", p_ifd[i]->vo.l_val); break; } case TAG_COLORMAP : { udata csize; cm_offset = p_ifd[i]->vo.l_val; csize.b_val[0] = p_ifd[i]->n[0]; csize.b_val[1] = p_ifd[i]->n[1]; csize.b_val[2] = p_ifd[i]->n[2]; csize.b_val[3] = p_ifd[i]->n[3]; if (DEBUG) { printf("\tcolormap size %d\n", csize.l_val); printf("\tcolormap offset %d\n", cm_offset); } /* assumption is 256 RGB tuplets */ /* assign color map structure */ p_retiff->p_cmh = p_ifd[i]; p_retiff->p_cm = (USHORT *) calloc(csize.l_val, sizeof(USHORT)); /* read color map data */ fseek(fh, (long) p_ifd[i]->vo.l_val, SEEK_SET); fread(p_retiff->p_cm, sizeof(USHORT), csize.l_val, fh); /* transfer to GIF */
p_gif->cm_size = csize.l_val; p_gif->cm = (unsigned char *) calloc(csize.l_val, sizeof(unsigned char)); for (i=0, j=0; i < p_gif->cm_size-2; ++j) { p_gif->cm[i] = (UBYTE) p_retiff->p_cm[j]; /* Red */ p_gif->cm[i+1] = (UBYTE) p_retiff->p_cm[j + 256]; /* Green */ p_gif->cm[i+2] = (UBYTE) p_retiff->p_cm[j + 512]; /* Blue */ i = i + 3; } break; } } } fflush(stdout); /* Save/Print out the byte count values */ { unsigned int *p_offsets = NULL; udata size; memcpy(&size, p_ifd[bc_index]->n, sizeof(ULONG)); p_offsets = (unsigned int *) calloc(size.l_val, sizeof(unsigned int)); /* seek forward to the byte counts */ fseek(fh, (long) p_ifd[bc_index]->vo.l_val, SEEK_SET); fread(p_offsets, sizeof(unsigned int), size.l_val, fh); if (DEBUG) puts("\nStrip byte sizes:"); p_retiff->size = size.l_val; p_retiff->p_bytecounts = (ULONG *) calloc(size.l_val, sizeof(ULONG)); p_gif->size = 0; for (i=0; i < size.l_val; ++i) {
if (DEBUG) printf("\toffset %d byte size %d\n", i, p_offsets[i]); p_retiff->p_bytecounts[i] = p_offsets[i]; p_gif->size += p_offsets[i]; } if (DEBUG) printf("\tTIFF image size %d from byte counts\n",p_gif->size); free(p_offsets); } /* Save/print out the strip offsets */ { unsigned int *p_offsets = NULL; p_offsets = (unsigned int *) calloc(ssize.l_val, sizeof(unsigned int)); p_retiff->p_stripoffsets = (ULONG *) calloc(ssize.l_val, sizeof(ULONG)); fseek(fh, (long) s_offset, SEEK_SET); fread(p_offsets, sizeof(unsigned int), ssize.l_val, fh); if (DEBUG) puts("\nStrip offsets:"); for (i=0; i < ssize.l_val; ++i) { p_retiff->p_stripoffsets[i] = p_offsets[i]; if (DEBUG) printf("\toffset %d is %x\n", i, p_offsets[i]); } free(p_offsets); p_offsets=NULL; } /* * Read image data into retiff data struct
*/ { int b_read; /* bytes read */ p_retiff->p_imagedata = (UBYTE **) calloc(p_retiff->size, sizeof(UBYTE *)); if (DEBUG) puts("\nRead image data"); for (i=0; i < p_retiff->size; ++i) { b_read = 0; p_retiff->p_imagedata[i] = (UBYTE *) calloc(p_retiff->p_bytecounts[i], sizeof(UBYTE)); fseek(fh, (long) p_retiff->p_stripoffsets[i], SEEK_SET); b_read = fread(p_retiff->p_imagedata[i], sizeof(UBYTE), p_retiff->p_bytecounts[i], fh); if (feof(fh)) { if (DEBUG) puts("End of file encountered"); } if (DEBUG) printf("%d.\tRead %.4x bytes of %.4x byte counts, offset %.6x\n", i, b_read, p_retiff->p_bytecounts[i], p_retiff->p_stripoffsets[i]); } } /* * LZW Compress to GIF structure */ { /* thread */ int iret; pthread_t pth_uart_wrtr; /* fpga data uart writer thread */ /* com serial i/o */ char *device = "/dev/ttyS10"; /* for UNIX build */ int j; /* data uart i/o time counter */
int retval; unsigned char rdr_buf[BUF_SIZE]; unsigned char *p_wtr_buf; unsigned int wrt_buf_sz; int i; /* LZW data copy counter */ int quot, rmdr; /* To create valid GIF image data blocks */ /* set up thread data & com i/o */ p_wtr_buf = (unsigned char *) calloc(p_gif->size, sizeof (unsigned char)); serial_open(device); /* spawing thread invokes EncodeImage */ /* EncodeImage(p_retiff, p_gif, 9); */ iret = pthread_create( &pth_uart_wrtr, NULL, serial_write, (void *) p_retiff); pthread_detach( pth_uart_wrtr ); /* data is writing to UART */ if ( DEBUG ) puts("\nReceiving LZW data..."); for (j = 0, p_gif->length = 0; j < TIME_OUT ; ++j ) { retval = read(fd, &rdr_buf[0], BUF_SIZE); if (retval == -1) { /* no data this cycle */ /* time out counter increment */ continue; } for (i = 0; i < retval; ++i) { p_wtr_buf[p_gif->length++] = rdr_buf[i]; if (DEBUG) { printf("%.2x ", rdr_buf[i]); } } j = 0; }
if (DEBUG) printf("\nReceived 0x%.4x bytes.\n", p_gif->length); /* add size sentinals */ wrt_buf_sz = p_gif->length; quot = p_gif->length / MAX_GIF_BLK_SIZE; /* integer quotent after division */ rmdr = p_gif->length % MAX_GIF_BLK_SIZE; /* remainder after division */ p_gif->length = p_gif->length + quot + ((rmdr == 0) ? 0 : 1); /* extend gif data size */ if (DEBUG) { printf("div %d, rmdr %d\n", quot, rmdr); } /* copy LZW data into GIF image blocks */ p_gif->data = (unsigned char *) calloc(p_gif->length, sizeof (unsigned char)); for (i = 0, j = 0; i < quot + ((rmdr + quot) / MAX_GIF_BLK_SIZE); ++i) { p_gif->data[j++] = MAX_GIF_BLK_SIZE - 1; memcpy ( &p_gif->data[j], &p_wtr_buf[i * (MAX_GIF_BLK_SIZE - 1)], (MAX_GIF_BLK_SIZE - 1)); j += MAX_GIF_BLK_SIZE - 1; } { int rmdr2; rmdr2 = (rmdr + quot) % MAX_GIF_BLK_SIZE; if (DEBUG) printf("rmdr2 %d\n",rmdr2); p_gif->data[j++] = rmdr2; memcpy ( &p_gif->data[j],
&p_wtr_buf[(quot + ((rmdr + quot) / MAX_GIF_BLK_SIZE)) * (MAX_GIF_BLK_SIZE-1)], rmdr2); } free(p_wtr_buf); if (DEBUG) printf("\n%x bytes of %x bytes compressed\n", p_gif->length, p_gif->size); close(fd); /* op delayed in case uart_wrtr is still working */ } /* * Write the GIF file */ { unsigned char buf[256]; FILE *fh_gif; fh_gif = fopen(argv[2], "wb"); /* Header */ sprintf(buf, "%s", "GIF89a"); fwrite(buf, sizeof(unsigned char), 6, fh_gif); /* Logical Screen Descriptor */ fwrite(&p_gif->width, sizeof(unsigned short), 1, fh_gif); fwrite(&p_gif->height, sizeof(unsigned short), 1, fh_gif); buf[0]=0xf7; /* packed field */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); buf[0]=0x00; /* background color index */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); buf[0]=0x00; /* pixel aspect ratio */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Global Color Table */ fflush(fh_gif); fwrite(p_gif->cm, sizeof(unsigned char), p_gif->cm_size, fh_gif);
fflush(fh_gif); /* Image Descriptor */ buf[0]=0x2c; /* Image Separator */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); fflush(fh_gif); buf[0]=0x00; /* Image Left Position */ buf[1]=0x00; fwrite(buf, sizeof(unsigned char), 2, fh_gif); buf[0]=0x00; /* Image Top Position */ buf[1]=0x00; fwrite(buf, sizeof(unsigned char), 2, fh_gif); fwrite(&p_gif->width, sizeof(unsigned short), 1, fh_gif); fwrite(&p_gif->height, sizeof(unsigned short), 1, fh_gif); buf[0]=0x00; /* Packed Fields */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Table Based Image Data */ buf[0]=0x08; /* LZW Minimum Code Size */ fwrite(buf, sizeof(unsigned char), 1, fh_gif); /* Image Data */ { unsigned char *p_data; p_data = &p_gif->data[0]; for (i=0 ; i < p_gif->length ; ++i) { fwrite(p_data++, sizeof(unsigned char), 1, fh_gif); fflush(fh_gif); } } /* Trailers */ buf[0] = 0x00; buf[1] = 0x3b;
fwrite(buf, sizeof(unsigned char), 2, fh_gif); fflush(fh_gif); fclose(fh_gif); fh_gif = NULL; } /* free memory used */ if (p_retiff->p_cm != NULL) { free(p_retiff->p_cm); p_retiff->p_cm = NULL; } if (p_retiff->p_bytecounts != NULL) { free(p_retiff->p_bytecounts); p_retiff->p_bytecounts = NULL; } if (p_retiff->p_stripoffsets != NULL) { free(p_retiff->p_stripoffsets); p_retiff->p_stripoffsets = NULL; } if (p_retiff->p_imagedata != NULL) { for (i=0; i<p_retiff->size; i++) { if (p_retiff->p_imagedata[i] != NULL) { free(p_retiff->p_imagedata[i]); p_retiff->p_imagedata[i] = NULL; } } free(p_retiff->p_imagedata); p_retiff->p_imagedata = NULL; } free(p_retiff); p_retiff = NULL;
if (p_gif->cm != NULL) { free(p_gif->cm); p_gif->cm = NULL; } { /* free gif lzw data */ if (p_gif->data != NULL) { free(p_gif->data); p_gif->data = NULL; } } free(p_gif); p_gif = NULL; for (j=0; j < ifd_size; ++j) { free(p_ifd[j]); p_ifd[j] = NULL; } free(p_ifd); p_ifd=NULL; fclose(fh); fh=NULL; free(p_dat); p_dat = NULL; if ( DEBUG ) puts("Done."); exit(0); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % E n c o d e I m a g e %
% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % EncodeImage LZW compresses an image via GIF-coding. % % The format of the EncodeImage method is: % % int EncodeImage( % retiff *p_retiff, % lzwGIF *p_gif, % const unsigned long data_size) % % A description of each parameter follows: % % o p_retiff: The address of a structure defining the image data. % % o p_gif: output gif image block % % o data_size: The number of bits in the compressed packet. % % Comments: % % JSC 01/03/07 Updated to send to FPGA via UART where LZW byte % stream is Tx/Rx % JSC 10/28/06 Modified from ImageMagick-6.2.8 coders/gif.c and adapted % for Re-TIFFing % */ int EncodeImage(retiff *p_retiff, lzwGIF *p_gif, const unsigned long data_size) { int x, y, i, retval;
union _sz { unsigned char b_size[4]; unsigned long l_size; } img = {0, 0, 0, 0}; #define DIM_SIZE 4 /* write y dimension */ img.l_size = (unsigned long) p_retiff->size; retval = write(fd, &img.b_size[0], DIM_SIZE); for (y = 0, i = 0; y < (long) p_retiff->size; y++) { /* write x dimension */ img.l_size = (unsigned long) p_retiff->p_bytecounts[y]; retval = write(fd, &img.b_size[0], DIM_SIZE); for (x=0; x < (long) p_retiff->p_bytecounts[y]; x++) { /* index=p_retiff->p_imagedata[y][x] & 0xff; */ /* img data val */ retval = write(fd, &p_retiff->p_imagedata[y][x], 1); } if (DEBUG) printf("\n%d. wrote 0x%.4x bytes\n", y + 1, img.l_size); i += img.l_size; } if (DEBUG) printf("\nEncodeImage exit. Wrote 0x%.4x bytes\n", i); } void* serial_write(void *ptr) { EncodeImage( (retiff *)ptr, NULL, 0); } void serial_open(char *device) { struct termios termios; fd = open(device, O_RDWR | O_NONBLOCK);
/* set the serial port characteristics */ if (tcgetattr(fd, &termios) < 0) { perror("tcgetattr"); exit(1); } if (cfsetospeed(&termios, B115200) < 0) { perror("cfsetospeed"); exit(1); } if (cfsetispeed(&termios, B115200) < 0) { perror("cfsetispeed"); exit(1); } // // c_cflag termios CS8 = 8 bits // termios.c_cflag = CS8 | CSTOPB; if (tcsetattr(fd, TCSANOW, &termios) < 0) { perror("tcsetattr"); exit(1); }
1 See http://www.em.avnet.com 2 TIFF. Revision 6.0 Final June 3, 1992. Adobe Developers Association. 3 spec-gif89a.txt 4 Platform Specification Format Reference Manual. Embedded Development Kit EDK 6.3i. UG131 (v1.0) August 20, 2004, pp 21. 5 Memec 3SLC MicroBlaze Hello World Reference Design. December 1, 2004 Version 6.3.d 6 Xilinx Spartan-3 FPGA Family: Introduction and Ordering Information. DS099-1 (v1.4) January 17, 2005.