Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
1 #pragma warning disable 675 // Bitwise-or operator used on a sign-extended operand
5 * Class GifDecoder - Decodes a GIF file into one or more frames.
8 * GifDecoder d = new GifDecoder();
9 * d.read("sample.gif");
10 * int n = d.getFrameCount();
11 * for (int i = 0; i < n; i++) {
12 * BufferedImage frame = d.getFrame(i); // frame i
13 * int t = d.getDelay(i); // display duration of frame in milliseconds
14 * // do something with frame
17 * No copyright asserted on the source code of this class. May be used for
18 * any purpose, however, refer to the Unisys LZW patent for any additional
19 * restrictions. Please forward any corrections to kweiner@fmsware.com.
21 * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick.
22 * @version 1.03 November 2003
28 using System.Collections;
30 using System.Drawing.Imaging;
33 namespace Aga.Controls
40 get { return _image; }
46 get { return _delay; }
49 public GifFrame(Image im, int del)
56 public class GifDecoder
58 public const int StatusOK = 0;//File read status: No errors.
59 public const int StatusFormatError = 1; //File read status: Error decoding file (may be partially decoded)
60 public const int StatusOpenError = 2; //Unable to open source.
62 private Stream inStream;
65 private int width; // full image width
66 private int height; // full image height
67 private bool gctFlag; // global color table used
68 private int gctSize; // size of global color table
69 private int loopCount = 1; // iterations; 0 = repeat forever
71 private int[] gct; // global color table
72 private int[] lct; // local color table
73 private int[] act; // active color table
75 private int bgIndex; // background color index
76 private int bgColor; // background color
77 private int lastBgColor; // previous bg color
78 private int pixelAspect; // pixel aspect ratio
80 private bool lctFlag; // local color table flag
81 private bool interlace; // interlace flag
82 private int lctSize; // local color table size
84 private int ix, iy, iw, ih; // current image rectangle
85 private Rectangle lastRect; // last image rect
86 private Image image; // current frame
87 private Bitmap bitmap;
88 private Image lastImage; // previous frame
90 private byte[] block = new byte[256]; // current data block
91 private int blockSize = 0; // block size
93 // last graphic control extension info
94 private int dispose = 0;
95 // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
96 private int lastDispose = 0;
97 private bool transparency = false; // use transparent color
98 private int delay = 0; // delay in milliseconds
99 private int transIndex; // transparent color index
101 private const int MaxStackSize = 4096;
102 // max decoder pixel stack size
104 // LZW decoder working arrays
105 private short[] prefix;
106 private byte[] suffix;
107 private byte[] pixelStack;
108 private byte[] pixels;
110 private ArrayList frames; // frames read from current file
111 private int frameCount;
112 private bool _makeTransparent;
115 * Gets the number of frames read from file.
116 * @return frame count
118 public int FrameCount
127 * Gets the first (or only) image read.
129 * @return BufferedImage containing first frame, or null if none.
135 return GetFrame(0).Image;
140 * Gets the "Netscape" iteration count, if any.
141 * A count of 0 means repeat indefinitiely.
143 * @return iteration count if one was specified, else 1.
153 public GifDecoder(Stream stream, bool makeTransparent)
155 _makeTransparent = makeTransparent;
156 if (Read(stream) != 0)
157 throw new InvalidOperationException();
161 * Creates new frame image from current data (and previous
162 * frames as specified by their disposition codes).
164 private int[] GetPixels(Bitmap bitmap)
166 int [] pixels = new int [ 3 * image.Width * image.Height ];
168 for (int th = 0; th < image.Height; th++)
170 for (int tw = 0; tw < image.Width; tw++)
172 Color color = bitmap.GetPixel(tw, th);
173 pixels[count] = color.R;
175 pixels[count] = color.G;
177 pixels[count] = color.B;
184 private void SetPixels(int[] pixels)
187 for (int th = 0; th < image.Height; th++)
189 for (int tw = 0; tw < image.Width; tw++)
191 Color color = Color.FromArgb( pixels[count++] );
192 bitmap.SetPixel( tw, th, color );
195 if (_makeTransparent)
196 bitmap.MakeTransparent(bitmap.GetPixel(0, 0));
199 private void SetPixels()
201 // expose destination image's pixels as int array
203 // (( int ) image.getRaster().getDataBuffer()).getData();
204 int[] dest = GetPixels( bitmap );
206 // fill in starting image contents based on last image's dispose code
209 if (lastDispose == 3)
211 // use image before last
212 int n = frameCount - 2;
215 lastImage = GetFrame(n - 1).Image;
223 if (lastImage != null)
226 // ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData();
227 int[] prev = GetPixels( new Bitmap( lastImage ) );
228 Array.Copy(prev, 0, dest, 0, width * height);
231 if (lastDispose == 2)
233 // fill last image rect area with background color
234 Graphics g = Graphics.FromImage( image );
235 Color c = Color.Empty;
238 c = Color.FromArgb( 0, 0, 0, 0 ); // assume background is transparent
242 c = Color.FromArgb( lastBgColor ) ;
243 // c = new Color(lastBgColor); // use given background color
245 Brush brush = new SolidBrush( c );
246 g.FillRectangle( brush, lastRect );
253 // copy each source line to the appropriate place in the destination
257 for (int i = 0; i < ih; i++)
286 int k = line * width;
287 int dx = k + ix; // start of line in dest
288 int dlim = dx + iw; // end of dest line
289 if ((k + width) < dlim)
291 dlim = k + width; // past dest edge
293 int sx = i * iw; // start of line in source
296 // map color and insert in destination
297 int index = ((int) pixels[sx++]) & 0xff;
311 * Gets the image contents of frame n.
313 * @return BufferedImage representation of frame.
315 public GifFrame GetFrame(int n)
317 if ((n >= 0) && (n < frameCount))
318 return (GifFrame)frames[n];
320 throw new ArgumentOutOfRangeException();
326 * @return GIF image dimensions
328 public Size FrameSize
332 return new Size(width, height);
337 * Reads GIF image from stream
339 * @param BufferedInputStream containing GIF file.
340 * @return read status code (0 = no errors)
342 private int Read( Stream inStream )
345 if ( inStream != null)
347 this.inStream = inStream;
354 status = StatusFormatError;
361 status = StatusOpenError;
368 * Decodes LZW image data into pixel array.
369 * Adapted from John Cristy's ImageMagick.
371 private void DecodeImageData()
393 if ((pixels == null) || (pixels.Length < npix))
395 pixels = new byte[npix]; // allocate new pixel array
397 if (prefix == null) prefix = new short[MaxStackSize];
398 if (suffix == null) suffix = new byte[MaxStackSize];
399 if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1];
401 // Initialize GIF data stream decoder.
404 clear = 1 << data_size;
405 end_of_information = clear + 1;
406 available = clear + 2;
408 code_size = data_size + 1;
409 code_mask = (1 << code_size) - 1;
410 for (code = 0; code < clear; code++)
413 suffix[code] = (byte) code;
416 // Decode GIF pixel stream.
418 datum = bits = count = first = top = pi = bi = 0;
420 for (i = 0; i < npix;)
424 if (bits < code_size)
426 // Load bytes until there are enough bits for a code.
429 // Read a new data block.
435 datum += (((int) block[bi]) & 0xff) << bits;
442 // Get the next code.
444 code = datum & code_mask;
448 // Interpret the code
450 if ((code > available) || (code == end_of_information))
455 code_size = data_size + 1;
456 code_mask = (1 << code_size) - 1;
457 available = clear + 2;
461 if (old_code == NullCode)
463 pixelStack[top++] = suffix[code];
469 if (code == available)
471 pixelStack[top++] = (byte) first;
476 pixelStack[top++] = suffix[code];
479 first = ((int) suffix[code]) & 0xff;
481 // Add a new string to the string table,
483 if (available >= MaxStackSize)
485 pixelStack[top++] = (byte) first;
486 prefix[available] = (short) old_code;
487 suffix[available] = (byte) first;
489 if (((available & code_mask) == 0)
490 && (available < MaxStackSize))
493 code_mask += available;
498 // Pop a pixel off the pixel stack.
501 pixels[pi++] = pixelStack[top];
505 for (i = pi; i < npix; i++)
507 pixels[i] = 0; // clear missing pixels
513 * Returns true if an error was encountered during reading/decoding
517 return status != StatusOK;
521 * Initializes or re-initializes reader
527 frames = new ArrayList();
533 * Reads a single byte from the input stream.
540 curByte = inStream.ReadByte();
544 status = StatusFormatError;
550 * Reads next variable length block from input.
552 * @return number of bytes stored in "buffer"
554 private int ReadBlock()
563 while (n < blockSize)
565 count = inStream.Read(block, n, blockSize - n);
577 status = StatusFormatError;
584 * Reads color table as 256 RGB integer values
586 * @param ncolors int number of colors to read
587 * @return int array containing 256 colors (packed ARGB with full alpha)
589 private int[] ReadColorTable(int ncolors)
591 int nbytes = 3 * ncolors;
593 byte[] c = new byte[nbytes];
597 n = inStream.Read(c, 0, c.Length );
604 status = StatusFormatError;
608 tab = new int[256]; // max size to avoid bounds checks
613 int r = ((int) c[j++]) & 0xff;
614 int g = ((int) c[j++]) & 0xff;
615 int b = ((int) c[j++]) & 0xff;
616 tab[i++] = ( int ) ( 0xff000000 | (r << 16) | (g << 8) | b );
623 * Main file parser. Reads GIF content blocks.
625 private void ReadContents()
627 // read GIF file content blocks
629 while (!(done || Error()))
635 case 0x2C : // image separator
639 case 0x21 : // extension
643 case 0xf9 : // graphics control extension
644 ReadGraphicControlExt();
647 case 0xff : // application extension
650 for (int i = 0; i < 11; i++)
652 app += (char) block[i];
654 if (app.Equals("NETSCAPE2.0"))
659 Skip(); // don't care
662 default : // uninteresting extension
668 case 0x3b : // terminator
672 case 0x00 : // bad byte, but keep going and see what happens
676 status = StatusFormatError;
683 * Reads Graphics Control Extension values
685 private void ReadGraphicControlExt()
687 Read(); // block size
688 int packed = Read(); // packed fields
689 dispose = (packed & 0x1c) >> 2; // disposal method
692 dispose = 1; // elect to keep old image if discretionary
694 transparency = (packed & 1) != 0;
695 delay = ReadShort() * 10; // delay in milliseconds
696 transIndex = Read(); // transparent color index
697 Read(); // block terminator
701 * Reads GIF file header information.
703 private void ReadHeader()
706 for (int i = 0; i < 6; i++)
710 if (!id.StartsWith("GIF"))
712 status = StatusFormatError;
717 if (gctFlag && !Error())
719 gct = ReadColorTable(gctSize);
720 bgColor = gct[bgIndex];
725 * Reads next frame image
727 private void ReadImage()
729 ix = ReadShort(); // (sub)image position & size
735 lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
736 interlace = (packed & 0x40) != 0; // 2 - interlace flag
739 lctSize = 2 << (packed & 7); // 6-8 - local color table size
743 lct = ReadColorTable(lctSize); // read table
744 act = lct; // make local table active
748 act = gct; // make global table active
749 if (bgIndex == transIndex)
755 save = act[transIndex];
756 act[transIndex] = 0; // set transparent color if specified
761 status = StatusFormatError; // no color table defined
766 DecodeImageData(); // decode pixel data
773 // create new image to receive frame data
775 // new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
777 bitmap = new Bitmap( width, height );
779 SetPixels(); // transfer pixel data to image
781 frames.Add(new GifFrame(bitmap, delay)); // add image to frame list
785 act[transIndex] = save;
792 * Reads Logical Screen Descriptor
794 private void ReadLSD()
797 // logical screen size
799 height = ReadShort();
803 gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
804 // 2-4 : color resolution
806 gctSize = 2 << (packed & 7); // 6-8 : gct size
808 bgIndex = Read(); // background color index
809 pixelAspect = Read(); // pixel aspect ratio
813 * Reads Netscape extenstion to obtain iteration count
815 private void ReadNetscapeExt()
822 // loop count sub-block
823 int b1 = ((int) block[1]) & 0xff;
824 int b2 = ((int) block[2]) & 0xff;
825 loopCount = (b2 << 8) | b1;
827 } while ((blockSize > 0) && !Error());
831 * Reads next 16-bit value, LSB first
833 private int ReadShort()
835 // read 16-bit value, LSB first
836 return Read() | (Read() << 8);
840 * Resets frame state for reading next image.
842 private void ResetFrame()
844 lastDispose = dispose;
845 lastRect = new Rectangle(ix, iy, iw, ih);
847 lastBgColor = bgColor;
853 * Skips variable length blocks up to and including
854 * next zero length block.
861 } while ((blockSize > 0) && !Error());