private static void CheckFrame(Stream s, ColourTable globalColourTable, Bitmap bitmap) { CheckExtensionIntroducer(s); CheckGraphicControlLabel(s); CheckGraphicControlExtension(s); CheckImageSeparator(s); bool shouldHaveLocalColourTable = (globalColourTable == null) ? true : false; int lctSizeBits = shouldHaveLocalColourTable ? 1 : 0; ImageDescriptor id = CheckImageDescriptor(s, shouldHaveLocalColourTable, lctSizeBits); if (globalColourTable == null) { // no global colour table so must be a local colour table on // each frame ColourTable lct = CheckColourTable(s, id.LocalColourTableSize); CheckImageData(s, lct, id, bitmap); } else { CheckImageData(s, globalColourTable, id, bitmap); } CheckBlockTerminator(s); }
/// <summary> /// Returns a colour table containing the colours of the quantized image. /// </summary> /// <returns> /// A colour table containing up to 256 colours, being the colours of /// the image after quantization. /// </returns> private ColourTable ColourMap() { ColourTable map = new ColourTable(); int[] originalIndices = new int[_neuronCount]; int[] thisNeuron; // Build an array of the original indices of the neurons in the // network, before the BuildIndex method reordered them. for (int neuronIndex = 0; neuronIndex < _neuronCount; neuronIndex++) { thisNeuron = _network[neuronIndex]; originalIndices[thisNeuron[3]] = neuronIndex; } for (int i = 0; i < _neuronCount; i++) { int indexInNetwork = originalIndices[i]; map.Add(Color.FromArgb(255, _network[indexInNetwork][0], _network[indexInNetwork][1], _network[indexInNetwork][2])); } return(map); }
/// <summary> /// Returns the index within the supplied colour table of the colour /// closest to the supplied colour. /// </summary> /// <param name="colourToFind"> /// The colour to find the closest match for. /// </param> /// <param name="colourTable"> /// The active colour table. /// </param> /// <returns> /// Returns -1 if the supplied colour is null. /// </returns> private static int FindClosest(Color colourToFind, ColourTable colourTable) { if (colourTable == null) { // TESTME: FindClosest - null colour table return(-1); } int r = colourToFind.R; int g = colourToFind.G; int b = colourToFind.B; int minpos = 0; int dmin = 256 * 256 * 256; int len = colourTable.Length; for (int i = 0; i < len; i++) { int dr = r - colourTable[i].R; int dg = g - colourTable[i].G; int db = b - colourTable[i].B; int d = dr * dr + dg * dg + db * db; if (d < dmin) { dmin = d; minpos = i; } } return(minpos); }
/// <summary> /// Decodes the supplied GIF stream. /// </summary> public void Decode() { _frameDelays = new List <int>(); _loadedFrames = new Queue <GifFrame>(); _frames = new Collection <GifFrame>(); _applicationExtensions = new Collection <ApplicationExtension>(); _gct = null; _header = new GifHeader(_stream); if (_header.ErrorState != ErrorState.Ok) { return; } _lsd = new LogicalScreenDescriptor(_stream); if (TestState(ErrorState.EndOfInputStream)) { return; } if (_lsd.HasGlobalColourTable) { _gct = new ColourTable(_stream, _lsd.GlobalColourTableSize); } if (ConsolidatedState == ErrorState.Ok) { ReadContents(_stream); } ApplyMemoryFields(); }
/// <summary> /// Writes an image descriptor to the supplied stream. /// </summary> /// <param name="imageSize"> /// The size, in pixels, of the image in this frame. /// </param> /// <param name="position"> /// The position of this image within the logical screen. /// </param> /// <param name="localColourTable"> /// The local colour table for this frame. /// Supply null if the global colour table is to be used for this frame. /// </param> /// <param name="outputStream"> /// The stream to write to. /// </param> private static void WriteImageDescriptor(Size imageSize, Point position, ColourTable localColourTable, Stream outputStream) { bool hasLocalColourTable; int localColourTableSize; if (localColourTable == null) { hasLocalColourTable = false; localColourTableSize = 0; } else { hasLocalColourTable = true; localColourTableSize = localColourTable.SizeBits; } bool isInterlaced = false; // encoding of interlaced images not currently supported bool localColourTableIsSorted = false; // sorting of colour tables not currently supported ImageDescriptor id = new ImageDescriptor(position, imageSize, hasLocalColourTable, isInterlaced, localColourTableIsSorted, localColourTableSize); outputStream.WriteByte(GifComponent.CodeImageSeparator); id.WriteToStream(outputStream); }
private void ConstructorStreamTest(bool xmlDebugging) { MemoryStream s = CreateStream(); // Extra stuff not included in the frame stream, to pass to the // constructor. ColourTable colourTable = WikipediaExample.GlobalColourTable; GraphicControlExtension ext = WikipediaExample.GraphicControlExtension; LogicalScreenDescriptor lsd = WikipediaExample.LogicalScreenDescriptor; _frame = new GifFrame(s, lsd, colourTable, ext, null, null, xmlDebugging); Assert.AreEqual(ErrorState.Ok, _frame.ConsolidatedState); WikipediaExample.CheckImage(_frame.TheImage); WikipediaExample.CheckImageDescriptor(_frame.ImageDescriptor); WikipediaExample.CheckGraphicControlExtension(_frame.GraphicControlExtension); WikipediaExample.CheckImageData(_frame.IndexedPixels); Assert.AreEqual(0, _frame.BackgroundColour.R); Assert.AreEqual(0, _frame.BackgroundColour.G); Assert.AreEqual(0, _frame.BackgroundColour.B); if (xmlDebugging) { Assert.AreEqual(ExpectedDebugXml, _frame.DebugXml); } }
public GifFrame(Stream inputStream, LogicalScreenDescriptor lsd, ColourTable gct, GraphicControlExtension gce, GifFrame previousFrame, GifFrame previousFrameBut1) : base(inputStream, lsd, gct, gce, previousFrame, previousFrameBut1) { }
private static ColourTable CheckColourTable(Stream s, int colourTableSize) { // read colour table ColourTable ct = new ColourTable(s, colourTableSize); Assert.AreEqual(ErrorState.Ok, ct.ConsolidatedState); return(ct); }
protected ColourTable GetTextureClut(ushort clut, int length) { ColourTable colourTable = new ColourTable { clut = clut, x = (clut & 0x1F) << 4, //(clut & 0x3F) << 4, y = (clut >> 6) & 0x1FF, colours = null }; Color[] colours = new Color[length]; int scaledX = colourTable.x; int scaledY = colourTable.y; int yOffset = scaledY * _TotalWidth; for (int x = 0; x < length;) { int xOffset = scaledX; try { xOffset += x; ushort val = _TextureData[yOffset + xOffset]; ushort alpha = 255; ushort red = val; ushort green = val; ushort blue = val; blue = (ushort)(((ushort)(val << 1) >> 11) << 3); green = (ushort)(((ushort)(val << 6) >> 11) << 3); red = (ushort)(((ushort)(val << 11) >> 11) << 3); alpha = (ushort)(val >> 15); if (alpha != 0 || blue != 0 || green != 0 || red != 0) { alpha = 255; } else { alpha = 0; } colours[x++] = Color.FromArgb(alpha, red, green, blue); } catch (Exception ex) { } } colourTable.colours = colours; return(colourTable); }
private ColourTable GetColorTable() { if (_colorTable != null || ColourSelectionMode != CGM.Commands.ColourSelectionMode.Type.INDEXED) { return(_colorTable); } _colorTable = Commands.SingleOrDefault(c => c.ElementClass == ClassCode.AttributeElements && c.ElementId == 34) as ColourTable; return(_colorTable); }
private ColourTable SetActiveColourTable() { ColourTable act; // active colour table if (_strategy == ColourTableStrategy.UseLocal) { if (_quantizerType == QuantizerType.UseSuppliedPalette) { if (_frames[_encodingFrame].Palette == null) { // TESTME: SetActiveColourTable - SetActiveColourTable, UseSuppliedPalette, no palette supplied string message = "You have opted to use a local colour table built " + "from a supplied palette, but frame " + _encodingFrame + "does not have a palette."; throw new InvalidOperationException(message); } else { // Build local colour table from colours in the frame's // supplied palette. act = new ColourTable(); foreach (Color c in _frames[_encodingFrame].Palette) { act.Add(c); } act.Pad(); } } else { // Build local colour table based on colours in the image. Image thisImage = _frames[_encodingFrame].TheImage; _pixelAnalysis = new PixelAnalysis(thisImage, _quantizerType); _pixelAnalysis.ColourQuality = _quality; _pixelAnalysis.Analyse(); // make local colour table active act = _pixelAnalysis.ColourTable; } } else { // make global colour table active act = _globalColourTable; } return(act); }
/// <summary> /// Reads GIF image from stream /// </summary> /// <param name="inputStream"> /// Stream containing GIF file. /// </param> /// <exception cref="ArgumentNullException"> /// The supplied stream is null. /// </exception> private void ReadStream(Stream inputStream) { _frames = new Collection <GifFrame>(); _applicationExtensions = new Collection <ApplicationExtension>(); _gct = null; _readStreamCounterText = "Reading stream byte"; AddCounter(_readStreamCounterText, (int)inputStream.Length); _header = new GifHeader(inputStream, XmlDebugging); MyProgressCounters[_readStreamCounterText].Value = (int)inputStream.Position; WriteDebugXmlNode(_header.DebugXmlReader); if (_header.ErrorState != ErrorState.Ok) { WriteDebugXmlFinish(); return; } _lsd = new LogicalScreenDescriptor(inputStream, XmlDebugging); MyProgressCounters[_readStreamCounterText].Value = (int)inputStream.Position; WriteDebugXmlNode(_lsd.DebugXmlReader); if (TestState(ErrorState.EndOfInputStream)) { WriteDebugXmlFinish(); return; } if (_lsd.HasGlobalColourTable) { _gct = new ColourTable(inputStream, _lsd.GlobalColourTableSize, XmlDebugging); MyProgressCounters[_readStreamCounterText].Value = (int)inputStream.Position; WriteDebugXmlNode(_gct.DebugXmlReader); } if (ConsolidatedState == ErrorState.Ok) { ReadContents(inputStream); MyProgressCounters[_readStreamCounterText].Value = (int)inputStream.Position; } inputStream.Close(); WriteDebugXmlFinish(); RemoveCounter(_readStreamCounterText); }
/// <summary> /// Creates a colour table directly from the distinct colours in the /// supplied image(s). /// </summary> private void CreateDirectColourTable() { //AddCounter( buildColourTableCounterText, // _distinctColours.Values.Count ); _colourTable = new ColourTable(); int distinctColourIndex = 0; foreach (Color c in _distinctColours.Values) { //MyProgressCounters[buildColourTableCounterText].Value //= distinctColourIndex; _colourTable.Add(c); distinctColourIndex++; } _colourTable.Pad(); //RemoveCounter( buildColourTableCounterText ); }
public void IndexerTest() { ReportStart(); Stream s = PrepareStream(); _table = new ColourTable(s, 4); Random r = new Random(); for (int i = 0; i < _table.Length; i++) { Color c = Color.FromArgb(r.Next()); _table[i] = c; Assert.AreEqual(c, _table[i], "Index " + i); Assert.AreEqual(c, _table.Colours[i], "Index " + i); } ReportEnd(); }
/// <summary> /// Converts the supplied image to a collection of pixel indices using /// the supplied colour table. /// Only used when the QuantizerType is set to UseSuppliedPalette /// </summary> /// <param name="act">The active colour table</param> /// <param name="image">The image</param> /// <returns></returns> private IndexedPixels MakeIndexedPixels(ColourTable act, Image image) { //AddCounter( counterText, pixelCount ); Bitmap bitmap = (Bitmap)image; IndexedPixels ip = new IndexedPixels(); for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { Color c = bitmap.GetPixel(x, y); int index = FindClosest(c, act); ip.Add((byte)index); //MyProgressCounters[counterText].Value = ip.Count; } } //RemoveCounter( counterText ); return(ip); }
public void IndexerGetTestIndexOutOfRange() { ReportStart(); Stream s = PrepareStream(); _table = new ColourTable(s, 4); try { Color c = _table[4]; } catch (ArgumentOutOfRangeException ex) { string message = "Colour table size: 4. Index: " + 4; StringAssert.Contains(message, ex.Message); Assert.AreEqual("index", ex.ParamName); ReportEnd(); throw; } }
public void ConstructorStreamTestTooFewColours() { ReportStart(); Stream s = new MemoryStream(); try { _table = new ColourTable(s, -1); } catch (ArgumentOutOfRangeException ex) { string message = "The number of colours must be between 0 and 256. " + "Number supplied: -1"; StringAssert.Contains(message, ex.Message); Assert.AreEqual("numberOfColours", ex.ParamName); ReportEnd(); throw; } }
private void ConstructorStreamTestColourTableTooShort(bool xmlDebugging) { Stream s = PrepareStream(); // Pass larger number of colours than are actually in the stream _table = new ColourTable(s, 5, xmlDebugging); Assert.AreEqual(ErrorState.ColourTableTooShort, _table.ErrorState); Assert.AreEqual(5, _table.Length); Assert.AreEqual(Color.FromArgb(255, 0, 0, 0), _table[0]); Assert.AreEqual(Color.FromArgb(255, 255, 0, 0), _table[1]); Assert.AreEqual(Color.FromArgb(255, 0, 255, 0), _table[2]); Assert.AreEqual(Color.FromArgb(255, 0, 0, 255), _table[3]); // missing colour should be set to black by the constructor Assert.AreEqual(Color.FromArgb(0, 0, 0, 0), _table[4]); if (xmlDebugging) { Assert.AreEqual(ExpectedDebugXml, _table.DebugXml); } }
public void ConstructorStreamNullLogicalScreenDescriptorTest() { MemoryStream s = CreateStream(); // Extra stuff not included in the frame stream, to pass to the // constructor ColourTable colourTable = WikipediaExample.GlobalColourTable; GraphicControlExtension ext = WikipediaExample.GraphicControlExtension; LogicalScreenDescriptor lsd = null; try { _frame = new GifFrame(s, lsd, colourTable, ext, null, null); } catch (ArgumentNullException ex) { Assert.AreEqual("lsd", ex.ParamName); throw; } }
/// <summary> /// Creates a colour table directly from the distinct colours in the /// supplied image(s). /// </summary> private void CreateDirectColourTable() { string buildColourTableCounterText = "Creating colour table from images"; AddCounter(buildColourTableCounterText, _distinctColours.Values.Count); _colourTable = new ColourTable(); int distinctColourIndex = 0; foreach (Color c in _distinctColours.Values) { MyProgressCounters[buildColourTableCounterText].Value = distinctColourIndex; _colourTable.Add(c); distinctColourIndex++; } _colourTable.Pad(); RemoveCounter(buildColourTableCounterText); }
private void ConstructorStreamNoImageDataTest(bool xmlDebugging) { MemoryStream s = new MemoryStream(); // Image descriptor byte[] idBytes = WikipediaExample.ImageDescriptorBytes; s.Write(idBytes, 0, idBytes.Length); // miss out the image data // // Table-based image data // byte[] imageData = WikipediaExample.ImageDataBytes; // s.Write( imageData, 0, imageData.Length ); byte[] imageData = new byte[] { 0x08, // LZW minimum code size // 0x00, // block size = 11 // // 11 bytes of LZW encoded data follows // 0x00, 0x01, 0x04, 0x18, 0x28, 0x70, 0xA0, 0xC1, 0x83, 0x01, 0x01, 0x00 // block terminator }; s.Write(imageData, 0, imageData.Length); s.Seek(0, SeekOrigin.Begin); // Extra stuff not included in the frame stream, to pass to the // constructor ColourTable colourTable = WikipediaExample.GlobalColourTable; GraphicControlExtension ext = WikipediaExample.GraphicControlExtension; LogicalScreenDescriptor lsd = WikipediaExample.LogicalScreenDescriptor; _frame = new GifFrame(s, lsd, colourTable, ext, null, null, xmlDebugging); Assert.AreEqual(ErrorState.TooFewPixelsInImageData, _frame.ConsolidatedState); if (xmlDebugging) { Assert.AreEqual(ExpectedDebugXml, _frame.DebugXml); } }
private void ConstructorStreamTest(bool xmlDebugging) { Stream s = PrepareStream(); _table = new ColourTable(s, 4, xmlDebugging); Assert.AreEqual(4, _table.Length); Assert.AreEqual(4, _table.Colours.Length); Assert.AreEqual(Color.FromArgb(255, 0, 0, 0), _table.Colours[0]); Assert.AreEqual(Color.FromArgb(255, 255, 0, 0), _table.Colours[1]); Assert.AreEqual(Color.FromArgb(255, 0, 255, 0), _table.Colours[2]); Assert.AreEqual(Color.FromArgb(255, 0, 0, 255), _table.Colours[3]); Assert.AreEqual(Color.FromArgb(255, 0, 0, 0), _table[0]); Assert.AreEqual(Color.FromArgb(255, 255, 0, 0), _table[1]); Assert.AreEqual(Color.FromArgb(255, 0, 255, 0), _table[2]); Assert.AreEqual(Color.FromArgb(255, 0, 0, 255), _table[3]); Assert.AreEqual(ErrorState.Ok, _table.ConsolidatedState); if (xmlDebugging) { Assert.AreEqual(ExpectedDebugXml, _table.DebugXml); } }
/// <summary> /// Reads GIF image from stream /// </summary> /// <param name="inputStream"> /// Stream containing GIF file. /// </param> /// <exception cref="ArgumentNullException"> /// The supplied stream is null. /// </exception> private void ReadStream(Stream inputStream) { _frames = new Collection <GifFrame>(); _applicationExtensions = new Collection <ApplicationExtension>(); _gct = null; _header = new GifHeader(inputStream, XmlDebugging); WriteDebugXmlNode(_header.DebugXmlReader); if (_header.ErrorState != ErrorState.Ok) { WriteDebugXmlFinish(); return; } _lsd = new LogicalScreenDescriptor(inputStream, XmlDebugging); WriteDebugXmlNode(_lsd.DebugXmlReader); if (TestState(ErrorState.EndOfInputStream)) { WriteDebugXmlFinish(); return; } if (_lsd.HasGlobalColourTable) { _gct = new ColourTable(inputStream, _lsd.GlobalColourTableSize, XmlDebugging); WriteDebugXmlNode(_gct.DebugXmlReader); } if (ConsolidatedState == ErrorState.Ok) { ReadContents(inputStream); } inputStream.Close(); WriteDebugXmlFinish(); }
public void WriteToStreamTest() { ReportStart(); _table = new ColourTable(); _table.Add(Color.FromArgb(255, 255, 0, 0)); // red _table.Add(Color.FromArgb(255, 0, 255, 0)); // green _table.Add(Color.FromArgb(255, 0, 0, 255)); // blue _table.Add(Color.FromArgb(255, 255, 255, 255)); // white MemoryStream s = new MemoryStream(); _table.WriteToStream(s); s.Seek(0, SeekOrigin.Begin); ColourTable t = new ColourTable(s, 4); Assert.AreEqual(ErrorState.Ok, t.ConsolidatedState); Assert.AreEqual(_table.Colours.Length, t.Colours.Length); for (int i = 0; i < t.Colours.Length; i++) { Assert.AreEqual(_table[i], t[i], "Colour index " + i); } ReportEnd(); }
private static void CheckImageData(Stream s, ColourTable act, ImageDescriptor id, Bitmap expectedBitmap) { // read, decode and check image data // Cannot compare encoded LZW data directly as different encoders // will create different colour tables, so even if the bitmaps are // identical, the colour indices will be different int pixelCount = id.Size.Width * id.Size.Height; TableBasedImageData tbid = new TableBasedImageData(s, pixelCount); Assert.AreEqual(ErrorState.Ok, tbid.ConsolidatedState); for (int y = 0; y < id.Size.Height; y++) { for (int x = 0; x < id.Size.Width; x++) { int i = (y * id.Size.Width) + x; Assert.AreEqual(expectedBitmap.GetPixel(x, y), act[tbid.Pixels[i]], "X: " + x + ", Y: " + y); } } }
public Bitmap Render() { var inputList = new List<PointD>(PixelHeight*PixelWidth); var xAxisValues = Maths.DoubleRange(PixelWidth, TopLeftCorner.X, TopLeftCorner.X + ViewWidth); var yAxisValues = Maths.DoubleRange(PixelHeight, TopLeftCorner.Y, TopLeftCorner.Y + ViewHeight); for (int x = 0; x < PixelWidth; x++) { for (int y = 0; y < PixelHeight; y++) { inputList.Add(new PointD(xAxisValues[x], yAxisValues[y])); } } var output = Model.Iterate(inputList, MaxIterations); var colourTable = new ColourTable(1024){ StartColor = Color.Black, EndColor = Color.FromArgb(255, 255, 0, 255) }; colourTable.SetupColourTable(); var bitmap = new Bitmap(PixelWidth, PixelHeight); bitmapRenderer.Render(bitmap, output, colourTable, MaxIterations); return bitmap; }
private void RenderImage() { try { statusLabel.Text = "Status: Rendering"; if (Convert.ToBoolean(pixelStepTextBox.Text.Equals("")) || Convert.ToBoolean(pixelStepTextBox.Text.Equals("0")) || Convert.ToBoolean(iterationCountTextBox.Text.Equals("")) || Convert.ToBoolean(yMinCheckBox.Text.Equals("")) || Convert.ToBoolean(yMaxCheckBox.Text.Equals("")) || Convert.ToBoolean(xMinCheckBox.Text.Equals("")) || Convert.ToBoolean(xMaxCheckBox.Text.Equals(""))) { // Choose default parameters and warn the user if the settings are all empty. pixelStepTextBox.Text = "1"; iterationCountTextBox.Text = "85"; yMinCheckBox.Text = "-1"; yMaxCheckBox.Text = "1"; xMinCheckBox.Text = "-2"; xMaxCheckBox.Text = "1"; MessageBox.Show("Invalid fields detected. Using default values."); statusLabel.Text = "Status: Error"; return; } else { // Show zoom and undo controls. zoomCheckbox.Show(); undoButton.Show(); undoNum++; } // Mandelbrot iteration count. kMax = Convert.ToInt32(iterationCountTextBox.Text); numColours = kMax; // If colourTable is not yet created or kMax has changed, create colourTable. if ((colourTable == null) || (kMax != colourTable.kMax) || (numColours != colourTable.nColour)) { colourTable = new ColourTable(numColours, kMax); } // Get the x, y range (mathematical coordinates) to plot. yMin = Convert.ToDouble(yMinCheckBox.Text); yMax = Convert.ToDouble(yMaxCheckBox.Text); xMin = Convert.ToDouble(xMinCheckBox.Text); xMax = Convert.ToDouble(xMaxCheckBox.Text); // Zoom scale. zoomScale = Convert.ToInt16(zoomTextBox.Text); // Clear any existing graphics content. g.Clear(Color.White); // Initialise working variables. int height = (int)g.VisibleClipBounds.Size.Height; int kLast = -1; double modulusSquared; Color color; Color colorLast = Color.Red; // Get screen boundary (lower left & upper right). This is // used when calculating the pixel scaling factors. ComplexPoint screenBottomLeft = new ComplexPoint(xMin, yMin); ComplexPoint screenTopRight = new ComplexPoint(xMax, yMax); // Create pixel manager. This sets up the scaling factors used when // converting from mathemathical to screen (pixel units) using the myPixelManager = new ScreenPixelManage(g, screenBottomLeft, screenTopRight); // The pixel step size defines the increment in screen pixels for each point // at which the Mandelbrot calcualtion will be done. e.g. a Step of 5 means // that the calcualtion will be done a 5-pixel increments. The X & Y increments // are the same. // // This increment is converted to mathematical coordinates. int xyPixelStep = Convert.ToInt16(pixelStepTextBox.Text); ComplexPoint pixelStep = new ComplexPoint(xyPixelStep, xyPixelStep); ComplexPoint xyStep = myPixelManager.GetDeltaMathsCoord(pixelStep); // Start stopwatch - used to measure performance improvements // (from improving the efficiency of the maths implementation). Stopwatch sw = new Stopwatch(); sw.Start(); // Main loop, nested over Y (outer) and X (inner) values. int lineNumber = 0; int yPix = myBitmap.Height - 1; for (double y = yMin; y < yMax; y += xyStep.img) { int xPix = 0; for (double x = xMin; x < xMax; x += xyStep.real) { // Create complex point C = x + i*y. ComplexPoint c = new ComplexPoint(x, y); // Initialise complex value Zk. ComplexPoint zk = new ComplexPoint(0, 0); // Do the main Mandelbrot calculation. Iterate until the equation // converges or the maximum number of iterations is reached. int k = 0; do { zk = zk.DoCmplxSqPlusConst(c); modulusSquared = zk.DoMoulusSq(); k++; } while ((modulusSquared <= 4.0) && (k < kMax)); if (k < kMax) { // Max number of iterations was not reached. This means that the // equation converged. Now assign a colour to the current pixel that // depends on the number of iterations, k, that were done. if (k == kLast) { // If the iteration count is the same as the last count, re-use the // last pen. This avoids re-calculating colour factors which is // computationally intensive. We benefit from this often because // adjacent pixels are often the same colour, especially in large parts // of the Mandelbrot set that are away from the areas of detail. color = colorLast; } else { // Calculate coluor scaling, from k. We don't use complicated/fancy colour // lookup tables. Instead, the following simple conversion works well: // // hue = (k/kMax)**0.25 where the constant 0.25 can be changed if wanted. // This formula stretches colours allowing more to be assigned at higher values // of k, which brings out detail in the Mandelbrot images. // The following is a full colour calculation, replaced now with colour table. // Uncomment and disable the colour table if wanted. The colour table works // well but supports fewer colours than full calculation of hue and colour // using double-precision arithmetic. //double colourIndex = ((double)k) / kMax; //double hue = Math.Pow(colourIndex, 0.25); // Colour table lookup. // Convert the hue value to a useable colour and assign to current pen. // The saturation and lightness are hard-coded at 0.9 and 0.6 respectively, // which work well. color = colourTable.GetColour(k); colorLast = color; } // Draw single pixel if (xyPixelStep == 1) { // Pixel step is 1, set a single pixel. if ((xPix < myBitmap.Width) && (yPix >= 0)) { myBitmap.SetPixel(xPix, yPix, color); } } else { // Pixel step is > 1, set a square of pixels. for (int pX = 0; pX < xyPixelStep; pX++) { for (int pY = 0; pY < xyPixelStep; pY++) { if (((xPix + pX) < myBitmap.Width) && ((yPix - pY) >= 0)) { myBitmap.SetPixel(xPix + pX, yPix - pY, color); } } } } } xPix += xyPixelStep; } yPix -= xyPixelStep; lineNumber++; if ((lineNumber % 120) == 0) { Refresh(); } } // Finished rendering. Stop the stopwatch and show the elapsed time. sw.Stop(); Refresh(); stopwatchLabel.Text = Convert.ToString(sw.Elapsed.TotalSeconds); statusLabel.Text = "Status: Render complete"; // Save current settings to undo file. StreamWriter writer = new StreamWriter(@"C:\Users\" + userName + "\\mandelbrot_config\\Undo\\undo" + undoNum + ".txt"); writer.Write(pixelStepTextBox.Text + Environment.NewLine + iterationCountTextBox.Text + Environment.NewLine + yMinCheckBox.Text + Environment.NewLine + yMaxCheckBox.Text + Environment.NewLine + xMinCheckBox.Text + Environment.NewLine + xMaxCheckBox.Text); writer.Close(); writer.Dispose(); } catch (Exception e2) { MessageBox.Show("Exception Trapped: " + e2.Message, "Error"); statusLabel.Text = "Status: Error"; } }
public void WikipediaExampleTest() { ReportStart(); _e = new AnimatedGifEncoder(); GifFrame frame = new GifFrame(WikipediaExample.ExpectedBitmap); frame.Delay = WikipediaExample.DelayTime; _e.AddFrame(frame); // TODO: some way of creating/testing a UseLocal version of WikipediaExample string fileName = "WikipediaExampleUseGlobal.gif"; _e.WriteToFile(fileName); Stream s = File.OpenRead(fileName); int code; // check GIF header GifHeader gh = new GifHeader(s); Assert.AreEqual(ErrorState.Ok, gh.ConsolidatedState); // check logical screen descriptor LogicalScreenDescriptor lsd = new LogicalScreenDescriptor(s); Assert.AreEqual(ErrorState.Ok, lsd.ConsolidatedState); WikipediaExample.CheckLogicalScreenDescriptor(lsd); // read global colour table ColourTable gct = new ColourTable(s, WikipediaExample.GlobalColourTableSize); Assert.AreEqual(ErrorState.Ok, gct.ConsolidatedState); // cannot compare global colour table as different encoders will // produce difference colour tables. // WikipediaExample.CheckGlobalColourTable( gct ); // check for extension introducer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code); // check for app extension label code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeApplicationExtensionLabel, code); // check netscape extension ApplicationExtension ae = new ApplicationExtension(s); Assert.AreEqual(ErrorState.Ok, ae.ConsolidatedState); NetscapeExtension ne = new NetscapeExtension(ae); Assert.AreEqual(ErrorState.Ok, ne.ConsolidatedState); Assert.AreEqual(0, ne.LoopCount); // check for extension introducer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code); // check for gce label code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeGraphicControlLabel, code); // check graphic control extension GraphicControlExtension gce = new GraphicControlExtension(s); Assert.AreEqual(ErrorState.Ok, gce.ConsolidatedState); WikipediaExample.CheckGraphicControlExtension(gce); // check for image separator code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeImageSeparator, code); // check for image descriptor ImageDescriptor id = new ImageDescriptor(s); Assert.AreEqual(ErrorState.Ok, id.ConsolidatedState); WikipediaExample.CheckImageDescriptor(id); // read, decode and check image data // Cannot compare encoded LZW data directly as different encoders // will create different colour tables, so even if the bitmaps are // identical, the colour indices will be different int pixelCount = WikipediaExample.FrameSize.Width * WikipediaExample.FrameSize.Height; TableBasedImageData tbid = new TableBasedImageData(s, pixelCount); for (int y = 0; y < WikipediaExample.LogicalScreenSize.Height; y++) { for (int x = 0; x < WikipediaExample.LogicalScreenSize.Width; x++) { int i = (y * WikipediaExample.LogicalScreenSize.Width) + x; Assert.AreEqual(WikipediaExample.ExpectedBitmap.GetPixel(x, y), gct[tbid.Pixels[i]], "X: " + x + ", Y: " + y); } } // Check for block terminator after image data code = ExampleComponent.CallRead(s); Assert.AreEqual(0x00, code); // check for GIF trailer code = ExampleComponent.CallRead(s); Assert.AreEqual(GifComponent.CodeTrailer, code); // check we're at the end of the stream code = ExampleComponent.CallRead(s); Assert.AreEqual(-1, code); s.Close(); _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState); BitmapAssert.AreEqual(WikipediaExample.ExpectedBitmap, (Bitmap)_d.Frames[0].TheImage, ""); ReportEnd(); }
/// <summary> /// Tests the AnimatedGifEncoder and the encoded GIF file it produces /// using the supplied parameters as property values. /// </summary> private void TestAnimatedGifEncoder(ColourTableStrategy strategy, int colourQuality, Size logicalScreenSize) { _e = new AnimatedGifEncoder(); // Check default properties set by constructor. Assert.AreEqual(ColourTableStrategy.UseGlobal, _e.ColourTableStrategy, "Colour table strategy set by constructor"); Assert.AreEqual(10, _e.SamplingFactor, "Colour quantization quality set by constructor"); Assert.AreEqual(Size.Empty, _e.LogicalScreenSize, "Logical screen size set by constructor"); _e.ColourTableStrategy = strategy; _e.SamplingFactor = colourQuality; _e.LogicalScreenSize = logicalScreenSize; // Check property set/gets Assert.AreEqual(strategy, _e.ColourTableStrategy, "Colour table strategy property set/get"); Assert.AreEqual(colourQuality, _e.SamplingFactor, "Colour quantization quality property set/get"); Assert.AreEqual(logicalScreenSize, _e.LogicalScreenSize, "Logical screen size property get/set"); foreach (GifFrame thisFrame in _frames) { _e.AddFrame(thisFrame); } StackTrace t = new StackTrace(); StackFrame f = t.GetFrame(1); string fileName = "Checks." + this.GetType().Name + "." + f.GetMethod().Name + ".gif"; _e.WriteToFile(fileName); Stream s = File.OpenRead(fileName); // global info CheckGifHeader(s); bool shouldHaveGlobalColourTable = (strategy == ColourTableStrategy.UseGlobal); LogicalScreenDescriptor lsd = CheckLogicalScreenDescriptor(s, shouldHaveGlobalColourTable); // Only check the global colour table if there should be one ColourTable gct = null; if (shouldHaveGlobalColourTable) { gct = CheckColourTable(s, lsd.GlobalColourTableSize); } CheckExtensionIntroducer(s); CheckAppExtensionLabel(s); CheckNetscapeExtension(s, 0); CheckFrame(s, gct, Bitmap1()); CheckFrame(s, gct, Bitmap2()); // end of image data CheckGifTrailer(s); CheckEndOfStream(s); s.Close(); // Check the file using the decoder _d = new GifDecoder(fileName); _d.Decode(); Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState, "Decoder consolidated state"); Assert.AreEqual(2, _d.Frames.Count, "Decoder frame count"); Assert.AreEqual(shouldHaveGlobalColourTable, _d.LogicalScreenDescriptor.HasGlobalColourTable, "Should have global colour table"); Assert.AreEqual(logicalScreenSize, _d.LogicalScreenDescriptor.LogicalScreenSize, "Decoder logical screen size"); BitmapAssert.AreEqual(Bitmap1(), (Bitmap)_d.Frames[0].TheImage, "frame 0"); BitmapAssert.AreEqual(Bitmap2(), (Bitmap)_d.Frames[1].TheImage, "frame 1"); bool shouldHaveLocalColourTable = !shouldHaveGlobalColourTable; Assert.AreEqual(shouldHaveLocalColourTable, _d.Frames[0].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table"); Assert.AreEqual(shouldHaveLocalColourTable, _d.Frames[1].ImageDescriptor.HasLocalColourTable, "Frame 0 has local colour table"); }
private void WriteFrame(Stream outputStream) { GifFrame thisFrame = _frames[_encodingFrame]; Image thisImage = thisFrame.TheImage; ColourTable act = SetActiveColourTable(); int transparentColourIndex; if (_transparent == Color.Empty) { transparentColourIndex = 0; } else { // TESTME: WriteFrame - _transparent != Color.Empty transparentColourIndex = FindClosest(_transparent, act); } WriteGraphicCtrlExt(thisFrame, transparentColourIndex, outputStream); ColourTable lct; if (_strategy == ColourTableStrategy.UseLocal) { lct = act; } else { lct = null; } WriteImageDescriptor(thisImage.Size, thisFrame.Position, lct, outputStream); // Write a local colour table if the strategy is to do so if (_strategy == ColourTableStrategy.UseLocal) { act.WriteToStream(outputStream); IndexedPixels ip; if (_quantizerType == QuantizerType.UseSuppliedPalette) { ip = MakeIndexedPixels(act, thisImage); } else { ip = _pixelAnalysis.IndexedPixels; } WritePixels(ip, outputStream); } else // global colour table { IndexedPixels ip; if (_quantizerType == QuantizerType.UseSuppliedPalette) { ip = MakeIndexedPixels(act, thisImage); } else { ip = _pixelAnalysis.IndexedPixelsCollection[_encodingFrame]; } WritePixels(ip, outputStream); } }
/// <summary> /// Writes a Logical Screen Descriptor to the supplied stream. /// Also writes a global colour table if required. /// </summary> /// <param name="outputStream"> /// The stream to write to. /// </param> private void WriteLogicalScreenDescriptor(Stream outputStream) { bool hasGlobalColourTable = _strategy == ColourTableStrategy.UseGlobal; int colourResolution = 7; // TODO: parameterise colourResolution? bool globalColourTableIsSorted = false; // Sorting of colour tables is not currently supported int backgroundColorIndex = 0; // TODO: parameterise backgroundColourIndex? int pixelAspectRatio = 0; // TODO: parameterise pixelAspectRatio? if (_strategy == ColourTableStrategy.UseGlobal) { if (_quantizerType == QuantizerType.UseSuppliedPalette) { // use supplied palette _globalColourTable = new ColourTable(); //AddCounter( buildColourTableCounterText, // _palette.Count ); int paletteIndex = 0; foreach (Color c in _palette) { _globalColourTable.Add(c); //MyProgressCounters[buildColourTableCounterText].Value //= paletteIndex; paletteIndex++; } _globalColourTable.Pad(); //RemoveCounter( buildColourTableCounterText ); } else { // Analyse the pixels in all the images to build the // global colour table. Collection <Image> images = new Collection <Image>(); foreach (GifFrame thisFrame in _frames) { Image thisImage = thisFrame.TheImage; images.Add(thisImage); } _pixelAnalysis = new PixelAnalysis(images); _pixelAnalysis.ColourQuality = _quality; _pixelAnalysis.Analyse(); _globalColourTable = _pixelAnalysis.ColourTable; } LogicalScreenDescriptor lsd = new LogicalScreenDescriptor(_logicalScreenSize, hasGlobalColourTable, colourResolution, globalColourTableIsSorted, _globalColourTable.SizeBits, backgroundColorIndex, pixelAspectRatio); lsd.WriteToStream(outputStream); _globalColourTable.WriteToStream(outputStream); } else { LogicalScreenDescriptor lsd = new LogicalScreenDescriptor(_logicalScreenSize, hasGlobalColourTable, colourResolution, globalColourTableIsSorted, 7, backgroundColorIndex, pixelAspectRatio); lsd.WriteToStream(outputStream); } }