public void TextWidgetVisibleTest()
		{
			{
				GuiWidget rectangleWidget = new GuiWidget(100, 50);
				TextWidget itemToAdd = new TextWidget("test Item", 10, 10);
				rectangleWidget.AddChild(itemToAdd);
				rectangleWidget.DoubleBuffer = true;
				rectangleWidget.BackBuffer.NewGraphics2D().Clear(RGBA_Bytes.White);
				rectangleWidget.OnDraw(rectangleWidget.BackBuffer.NewGraphics2D());

				ImageBuffer textOnly = new ImageBuffer(75, 20, 32, new BlenderBGRA());
				textOnly.NewGraphics2D().Clear(RGBA_Bytes.White);

				textOnly.NewGraphics2D().DrawString("test Item", 1, 1);

				if (saveImagesForDebug)
				{
					ImageTgaIO.Save(rectangleWidget.BackBuffer, "-rectangleWidget.tga");
					//ImageTgaIO.Save(itemToAdd.Children[0].BackBuffer, "-internalTextWidget.tga");
					ImageTgaIO.Save(textOnly, "-textOnly.tga");
				}

				Assert.IsTrue(rectangleWidget.BackBuffer.FindLeastSquaresMatch(textOnly, 1), "TextWidgets need to be drawing.");
				rectangleWidget.Close();
			}

			{
				GuiWidget rectangleWidget = new GuiWidget(100, 50);
				TextEditWidget itemToAdd = new TextEditWidget("test Item", 10, 10);
				rectangleWidget.AddChild(itemToAdd);
				rectangleWidget.DoubleBuffer = true;
				rectangleWidget.BackBuffer.NewGraphics2D().Clear(RGBA_Bytes.White);
				rectangleWidget.OnDraw(rectangleWidget.BackBuffer.NewGraphics2D());

				ImageBuffer textOnly = new ImageBuffer(75, 20, 32, new BlenderBGRA());
				textOnly.NewGraphics2D().Clear(RGBA_Bytes.White);

				TypeFacePrinter stringPrinter = new TypeFacePrinter("test Item", 12);
				IVertexSource offsetText = new VertexSourceApplyTransform(stringPrinter, Affine.NewTranslation(1, -stringPrinter.LocalBounds.Bottom));
				textOnly.NewGraphics2D().Render(offsetText, RGBA_Bytes.Black);

				if (saveImagesForDebug)
				{
					ImageTgaIO.Save(rectangleWidget.BackBuffer, "-rectangleWidget.tga");
					//ImageTgaIO.Save(itemToAdd.Children[0].BackBuffer, "-internalTextWidget.tga");
					ImageTgaIO.Save(textOnly, "-textOnly.tga");
				}

				Assert.IsTrue(rectangleWidget.BackBuffer.FindLeastSquaresMatch(textOnly, 1), "TextWidgets need to be drawing.");
				rectangleWidget.Close();
			}
		}
Example #2
0
		public void DoubleBufferTests()
		{
			{
				bool textWidgetDoubleBufferDefault = TextWidget.DoubleBufferDefault;

				// the text widget is double buffered
				TextWidget.DoubleBufferDefault = true;
				ImageBuffer doubleBufferImage = new ImageBuffer(65, 50, 24, new BlenderBGR());
				Button doubleBufferButton = new Button("testing", 0, 0);
				doubleBufferButton.OnDraw(doubleBufferImage.NewGraphics2D());
				SaveImage(doubleBufferImage, "z control.tga");

				// make sure the frame comparison function works.
				{
					ImageBuffer doubleBufferImageCopy = new ImageBuffer(doubleBufferImage, new BlenderBGR());
					Assert.IsTrue(doubleBufferImage == doubleBufferImageCopy);
				}

				// the text widget is not double buffered
				TextWidget.DoubleBufferDefault = false;
				ImageBuffer notDoubleBufferImage = new ImageBuffer(65, 50, 24, new BlenderBGR());
				Button notDoubleBufferButton = new Button("testing", 0, 0);
				notDoubleBufferButton.OnDraw(notDoubleBufferImage.NewGraphics2D());
				SaveImage(notDoubleBufferImage, "z test.tga");

				Assert.IsTrue(doubleBufferImage == notDoubleBufferImage);

				TextWidget.DoubleBufferDefault = textWidgetDoubleBufferDefault;
			}
		}
Example #3
0
		public void ContainsTests()
		{
			// look for 24 bit
			{
				ImageBuffer imageToSearch = new ImageBuffer(150, 150, 24, new BlenderBGR());
				imageToSearch.NewGraphics2D().Circle(new Vector2(100, 100), 3, RGBA_Bytes.Red);
				ImageBuffer circleToFind = new ImageBuffer(10, 10, 24, new BlenderBGR());
				circleToFind.NewGraphics2D().Circle(new Vector2(5, 5), 3, RGBA_Bytes.Red);
				Assert.IsTrue(imageToSearch.Contains(circleToFind), "We should be able to find the circle.");

				ImageBuffer squareToFind = new ImageBuffer(10, 10, 24, new BlenderBGR());
				squareToFind.NewGraphics2D().FillRectangle(4, 4, 8, 8, RGBA_Bytes.Red);
				Assert.IsTrue(!imageToSearch.Contains(squareToFind), "We should be not find a square.");
			}

			// look for 32 bit
			{
				ImageBuffer imageToSearch = new ImageBuffer(150, 150, 32, new BlenderBGRA());
				imageToSearch.NewGraphics2D().Circle(new Vector2(100, 100), 3, RGBA_Bytes.Red);
				ImageBuffer circleToFind = new ImageBuffer(10, 10, 32, new BlenderBGRA());
				circleToFind.NewGraphics2D().Circle(new Vector2(5, 5), 3, RGBA_Bytes.Red);
				Assert.IsTrue(imageToSearch.Contains(circleToFind), "We should be able to find the circle.");

				ImageBuffer squareToFind = new ImageBuffer(10, 10, 32, new BlenderBGRA());
				squareToFind.NewGraphics2D().FillRectangle(4, 4, 8, 8, RGBA_Bytes.Red);
				Assert.IsTrue(!imageToSearch.Contains(squareToFind), "We should be not find a square.");
			}
		}
		public RandomFillWidget(Point2D size)
		{
			LocalBounds = new RectangleDouble(0, 0, size.x, size.y);
			image = new ImageBuffer(size.x, size.y, 32, new BlenderBGRA());

			Random rand = new Random();
			Graphics2D imageGraphics = image.NewGraphics2D();
			for (int i = 0; i < 30; i++)
			{
				imageGraphics.Circle(rand.NextDouble() * image.Width, rand.NextDouble() * image.Height, rand.NextDouble() * 10 + 5, RGBA_Bytes.Red);
			}
		}
Example #5
0
		private bool ClearAndCheckImage(ImageBuffer image, RGBA_Bytes color)
		{
			image.NewGraphics2D().Clear(color);

			for (int y = 0; y < image.Height; y++)
			{
				for (int x = 0; x < image.Width; x++)
				{
					if (image.GetPixel(x, y) != color)
					{
						return false;
					}
				}
			}

			return true;
		}
		public DebugRenderToImage(Mesh meshToRender)
		{
			this.meshToRender = meshToRender;
			image = new ImageBuffer(xResolution, yResolution, 32, new BlenderBGRA());
			graphics = image.NewGraphics2D();

			// assume project on y for now
			foreach (Vertex vertex in meshToRender.Vertices)
			{
				min.x = Math.Min(min.x, vertex.Position[xAxis]);
				min.y = Math.Min(min.y, vertex.Position[yAxis]);

				max.x = Math.Max(max.x, vertex.Position[xAxis]);
				max.y = Math.Max(max.y, vertex.Position[yAxis]);
			}

			scale = Math.Min((image.Width - padding * 2) / (max.x - min.x), (image.Height - padding * 2) / (max.y - min.y));
			origin = new Vector2(min.x * scale, min.y * scale) - new Vector2(padding, padding);
		}
Example #7
0
		public void CompareToLionTGA()
		{
			LionShape lionShape = new LionShape();
			ImageBuffer renderedImage = new ImageBuffer(512, 400, 24, new BlenderBGR());
			byte alpha = (byte)(.1 * 255);
			for (int i = 0; i < lionShape.NumPaths; i++)
			{
				lionShape.Colors[i].Alpha0To255 = alpha;
			}

			Affine transform = Affine.NewIdentity();
			transform *= Affine.NewTranslation(-lionShape.Center.x, -lionShape.Center.y);
			transform *= Affine.NewTranslation(renderedImage.Width / 2, renderedImage.Height / 2);

			// This code renders the lion:
			VertexSourceApplyTransform transformedPathStorage = new VertexSourceApplyTransform(lionShape.Path, transform);
			Graphics2D renderer = renderedImage.NewGraphics2D();
			renderer.Clear(new RGBA_Floats(1.0, 1.0, 1.0, 1.0));
			renderer.Render(transformedPathStorage, lionShape.Colors, lionShape.PathIndex, lionShape.NumPaths);

			ImageTgaIO.Save(renderedImage, "TestOutput.tga");

			Stream imageStream = File.Open("LionRenderMaster.tga", FileMode.Open);
			ImageBuffer masterImage = new ImageBuffer();
			ImageTgaIO.LoadImageData(masterImage, imageStream, 24);

			bool sameWidth = masterImage.Width == renderedImage.Width;
			bool sameHeight = masterImage.Height == renderedImage.Height;
			Assert.IsTrue(sameWidth && sameHeight);
			Assert.IsTrue(masterImage.BitDepth == renderedImage.BitDepth);
			int unused;
			byte[] masterBuffer = masterImage.GetBuffer(out unused);
			byte[] renderedBuffer = renderedImage.GetBuffer(out unused);
			Assert.IsTrue(masterBuffer.Length == renderedBuffer.Length);
			for (int i = 0; i < masterBuffer.Length; i++)
			{
				if (masterBuffer[i] != renderedBuffer[i])
				{
					Assert.IsTrue(false);
				}
			}
		}
Example #8
0
        public FloodFillDemo()
        {
            BackgroundColor = RGBA_Bytes.White;
            imageToFillOn = new ImageBuffer(400, 300, 32, new BlenderBGRA());
            Graphics2D imageToFillGraphics = imageToFillOn.NewGraphics2D();
            imageToFillGraphics.Clear(RGBA_Bytes.White);
            imageToFillGraphics.DrawString("Click to fill", 20, 30);
            imageToFillGraphics.Circle(new Vector2(200, 150), 35, RGBA_Bytes.Black);
            imageToFillGraphics.Circle(new Vector2(200, 150), 30, RGBA_Bytes.Green);
            imageToFillGraphics.Rectangle(20, 50, 210, 280, RGBA_Bytes.Black);
            imageToFillGraphics.Rectangle(imageToFillOn.GetBounds(), RGBA_Bytes.Blue);

            Random rand = new Random();
            for (int i = 0; i < 20; i++)
            {
                Ellipse elipse = new Ellipse(rand.Next(imageToFillOn.Width), rand.Next(imageToFillOn.Height), rand.Next(10, 60), rand.Next(10, 60));
                Stroke outline = new Stroke(elipse);
                imageToFillGraphics.Render(outline, RGBA_Bytes.Black);
            }
            

            m_slider1 = new Slider(new Vector2(80, 10), 510);
            m_slider2 = new Slider(new Vector2(80, 10 + 20), 510);

            m_slider1.ValueChanged += new EventHandler(NeedsRedraw);
            m_slider2.ValueChanged += new EventHandler(NeedsRedraw);

            AddChild(m_slider1);
            AddChild(m_slider2);

            m_slider1.Text = "Pixel size={0:F3}";
            m_slider1.SetRange(8, 100);
            m_slider1.NumTicks = 23;
            m_slider1.Value = 32;

            m_slider2.Text = "gamma={0:F3}";
            m_slider2.SetRange(0.0, 3.0);
            m_slider2.Value = 1.0;
        }
Example #9
0
        public static CCSprite CreateText(string text, CCColor4B fill, CCColor4B stroke, TypeFace font, double emSizeInPoints, bool underline = false, bool flatenCurves = true, double strokeThickness = 1)
        {
            TypeFacePrinter printer = new TypeFacePrinter(text, new StyledTypeFace(font, emSizeInPoints, underline, flatenCurves));
            double width = printer.LocalBounds.Width;
            double height = printer.LocalBounds.Height;

            RectangleDouble rect = new RectangleDouble();
            bounding_rect.bounding_rect_single(printer, 0, ref rect);
            VertexSourceApplyTransform path = new VertexSourceApplyTransform(printer, Affine.NewTranslation(-rect.Left, -rect.Bottom));

            ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA());
            Graphics2D g = buffer.NewGraphics2D();

            if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A));
            if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A));

            Texture2D xnaTexture = XnaTexture((int)width, (int)height);
            xnaTexture.SetData<byte>(buffer.GetBuffer());
            CCTexture2D ccTexture = new CCTexture2D();
            ccTexture.InitWithTexture(xnaTexture);
            return new CCSprite(ccTexture);
        }
		private void AddAFloor()
		{
			ImageBuffer testImage = new ImageBuffer(200, 200, 32, new BlenderBGRA());
			Graphics2D graphics = testImage.NewGraphics2D();
			Random rand = new Random(0);
			for (int i = 0; i < 100; i++)
			{
				RGBA_Bytes color = new RGBA_Bytes(rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
				graphics.Circle(new Vector2(rand.NextDouble() * testImage.Width, rand.NextDouble() * testImage.Height), rand.NextDouble() * 40 + 10, color);
			}
			scene.shapes.Add(new PlaneShape(new Vector3(0, 0, 1), 0, new TextureMaterial(testImage, 0, 0, .2, 1)));
			//scene.shapes.Add(new PlaneShape(new Vector3(0, 0, 1), 0, new ChessboardMaterial(new RGBA_Floats(1, 1, 1), new RGBA_Floats(0, 0, 0), 0, 0, 1, 0.7)));
		}
		protected GuiWidget GetThumbnailWidget(LibraryProvider parentProvider, PrintItemCollection printItemCollection, ImageBuffer imageBuffer)
		{
			Vector2 expectedSize = new Vector2((int)(50 * TextWidget.GlobalPointSizeScaleRatio), (int)(50 * TextWidget.GlobalPointSizeScaleRatio));
			if (imageBuffer.Width != expectedSize.x)
			{
				ImageBuffer scaledImageBuffer = new ImageBuffer((int)expectedSize.x, (int)expectedSize.y, 32, new BlenderBGRA());
				scaledImageBuffer.NewGraphics2D().Render(imageBuffer, 0, 0, scaledImageBuffer.Width, scaledImageBuffer.Height);
				imageBuffer = scaledImageBuffer;
			}

			ImageWidget folderThumbnail = new ImageWidget(imageBuffer);
			folderThumbnail.BackgroundColor = ActiveTheme.Instance.PrimaryAccentColor;

			Button clickThumbnail = new Button(0, 0, folderThumbnail);
			clickThumbnail.Cursor = Cursors.Hand;

			clickThumbnail.Click += (sender, e) =>
			{
				if (parentProvider == null)
				{
					this.CurrentLibraryProvider = this.CurrentLibraryProvider.GetProviderForCollection(printItemCollection);
				}
				else
				{
					this.CurrentLibraryProvider = parentProvider;
				}
			};

			return clickThumbnail;
		}
		void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
		{
			try // if we get a bad result we can get a target invocation exception. In that case just don't show anything
			{
				byte[] raw = e.Result;
				Stream stream = new MemoryStream(raw);
				ImageBuffer unScaledImage = new ImageBuffer(10, 10, 32, new BlenderBGRA());
				StaticData.Instance.LoadImageData(stream, unScaledImage);
				// If the source image (the one we downloaded) is more than twice as big as our dest image.
				while (unScaledImage.Width > Image.Width * 2)
				{
					// The image sampler we use is a 2x2 filter so we need to scale by a max of 1/2 if we want to get good results.
					// So we scale as many times as we need to to get the Image to be the right size.
					// If this were going to be a non-uniform scale we could do the x and y separately to get better results.
					ImageBuffer halfImage = new ImageBuffer(unScaledImage.Width / 2, unScaledImage.Height / 2, 32, scalingBlender);
					halfImage.NewGraphics2D().Render(unScaledImage, 0, 0, 0, halfImage.Width / (double)unScaledImage.Width, halfImage.Height / (double)unScaledImage.Height);
					unScaledImage = halfImage;
				}
				Image.NewGraphics2D().Render(unScaledImage, 0, 0, 0, Image.Width / (double)unScaledImage.Width, Image.Height / (double)unScaledImage.Height);
				Image.MarkImageChanged();
				Invalidate();

				if (LoadComplete != null)
				{
					LoadComplete(this, null);
				}
			}
			catch (Exception)
			{
				GuiWidget.BreakInDebugger();
			}
		}
Example #13
0
        public void SingleItemVisibleTest()
        {
            {
                ListBox containerListBox = new ListBox(new RectangleDouble(0, 0, 100, 100));
                ListBoxTextItem itemToAddToList = new ListBoxTextItem("test Item", "test data for item");
                itemToAddToList.Name = "list item";
                containerListBox.AddChild(itemToAddToList);
                containerListBox.DoubleBuffer = true;
                containerListBox.BackBuffer.NewGraphics2D().Clear(RGBA_Bytes.White);
                containerListBox.OnDraw(containerListBox.BackBuffer.NewGraphics2D());

                ImageBuffer textImage = new ImageBuffer(80, 16, 32, new BlenderBGRA());
                textImage.NewGraphics2D().Clear(RGBA_Bytes.White);
                textImage.NewGraphics2D().DrawString("test Item", 1, 1);

                OutputImage(containerListBox.BackBuffer, "test.tga");
                OutputImage(textImage, "control.tga");

                double maxError = 20000000;
                Vector2 bestPosition;
                double leastSquares;
                containerListBox.BackBuffer.FindLeastSquaresMatch(textImage, out bestPosition, out leastSquares, maxError);

                Assert.IsTrue(leastSquares < maxError, "The list box need to be showing the item we added to it.");
            }

            {
                GuiWidget container = new GuiWidget(202, 302);
                container.DoubleBuffer = true;
                container.NewGraphics2D().Clear(RGBA_Bytes.White);
                FlowLayoutWidget leftToRightLayout = new FlowLayoutWidget();
                leftToRightLayout.AnchorAll();
                {
                    {
                        ListBox listBox = new ListBox(new RectangleDouble(0, 0, 200, 300));
                        //listBox.BackgroundColor = RGBA_Bytes.Red;
                        listBox.Name = "listBox";
                        listBox.VAnchor = UI.VAnchor.ParentTop;
                        listBox.ScrollArea.Margin = new BorderDouble(15);
                        leftToRightLayout.AddChild(listBox);

                        for (int i = 0; i < 1; i++)
                        {
                            ListBoxTextItem newItem = new ListBoxTextItem("hand" + i.ToString() + ".stl", "c:\\development\\hand" + i.ToString() + ".stl");
                            newItem.Name = "ListBoxItem" + i.ToString();
                            listBox.AddChild(newItem);
                        }
                    }
                }

                container.AddChild(leftToRightLayout);
                container.OnDraw(container.NewGraphics2D());

                ImageBuffer textImage = new ImageBuffer(80, 16, 32, new BlenderBGRA());
                textImage.NewGraphics2D().Clear(RGBA_Bytes.White);
                textImage.NewGraphics2D().DrawString("hand0.stl", 1, 1);

                OutputImage(container.BackBuffer, "control.tga");
                OutputImage(textImage, "test.tga");

                double maxError = 1000000;
                Vector2 bestPosition;
                double leastSquares;
                container.BackBuffer.FindLeastSquaresMatch(textImage, out bestPosition, out leastSquares, maxError);

                Assert.IsTrue(leastSquares < maxError, "The list box need to be showing the item we added to it.");
            }
        }
		private static ImageBuffer BuildImageFromMeshGroups(List<MeshGroup> loadedMeshGroups, string stlHashCode, Point2D size)
		{
			if (loadedMeshGroups != null
				&& loadedMeshGroups.Count > 0
				&& loadedMeshGroups[0].Meshes != null
				&& loadedMeshGroups[0].Meshes[0] != null)
			{
				ImageBuffer tempImage = new ImageBuffer(size.x, size.y);
				Graphics2D partGraphics2D = tempImage.NewGraphics2D();
				partGraphics2D.Clear(new RGBA_Bytes());

				AxisAlignedBoundingBox aabb = loadedMeshGroups[0].GetAxisAlignedBoundingBox();
				for (int meshGroupIndex = 1; meshGroupIndex < loadedMeshGroups.Count; meshGroupIndex++)
				{
					aabb = AxisAlignedBoundingBox.Union(aabb, loadedMeshGroups[meshGroupIndex].GetAxisAlignedBoundingBox());
				}
				double maxSize = Math.Max(aabb.XSize, aabb.YSize);
				double scale = size.x / (maxSize * 1.2);
				RectangleDouble bounds2D = new RectangleDouble(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.x, aabb.maxXYZ.y);
				foreach (MeshGroup meshGroup in loadedMeshGroups)
				{
					foreach (Mesh loadedMesh in meshGroup.Meshes)
					{
						PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, loadedMesh,
							new Vector2((size.x / scale - bounds2D.Width) / 2 - bounds2D.Left,
								(size.y / scale - bounds2D.Height) / 2 - bounds2D.Bottom),
							scale, RGBA_Bytes.White);
					}
				}

				if (File.Exists("RunUnitTests.txt"))
				{
					foreach (Mesh loadedMesh in loadedMeshGroups[0].Meshes)
					{
						List<MeshEdge> nonManifoldEdges = loadedMesh.GetNonManifoldEdges();
						if (nonManifoldEdges.Count > 0)
						{
							partGraphics2D.Circle(size.x / 4, size.x / 4, size.x / 8, RGBA_Bytes.Red);
						}
					}
				}

				tempImage.SetRecieveBlender(new BlenderPreMultBGRA());
				AllWhite.DoAllWhite(tempImage);

				// and give it back
				return tempImage;
			}

			return null;
		}
		private void CreateThumbnail()
		{
			string stlHashCode = this.ItemWrapper.FileHashCode.ToString();

			ImageBuffer bigRender = new ImageBuffer();
			if (!File.Exists(this.ItemWrapper.FileLocation))
			{
				return;
			}

			List<MeshGroup> loadedMeshGroups = MeshFileIo.Load(this.ItemWrapper.FileLocation);

			RenderType renderType = GetRenderType(this.ItemWrapper.FileLocation);

			switch (renderType)
			{
				case RenderType.RAY_TRACE:
					{
						ThumbnailTracer tracer = new ThumbnailTracer(loadedMeshGroups, BigRenderSize.x, BigRenderSize.y);
						tracer.DoTrace();

						bigRender = tracer.destImage;
					}
					break;

				case RenderType.PERSPECTIVE:
					{
						ThumbnailTracer tracer = new ThumbnailTracer(loadedMeshGroups, BigRenderSize.x, BigRenderSize.y);
						this.thumbnailImage = new ImageBuffer(this.buildingThumbnailImage);
						this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));

						bigRender = new ImageBuffer(BigRenderSize.x, BigRenderSize.y);

						foreach (MeshGroup meshGroup in loadedMeshGroups)
						{
							double minZ = double.MaxValue;
							double maxZ = double.MinValue;
							foreach (Mesh loadedMesh in meshGroup.Meshes)
							{
								tracer.GetMinMaxZ(loadedMesh, ref minZ, ref maxZ);
							}

							foreach (Mesh loadedMesh in meshGroup.Meshes)
							{
								tracer.DrawTo(bigRender.NewGraphics2D(), loadedMesh, RGBA_Bytes.White, minZ, maxZ);
							}
						}

						if (bigRender == null)
						{
							bigRender = new ImageBuffer(this.noThumbnailImage);
						}
					}
					break;

				case RenderType.NONE:
				case RenderType.ORTHOGROPHIC:

					this.thumbnailImage = new ImageBuffer(this.buildingThumbnailImage);
					this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));
					bigRender = BuildImageFromMeshGroups(loadedMeshGroups, stlHashCode, BigRenderSize);
					if (bigRender == null)
					{
						bigRender = new ImageBuffer(this.noThumbnailImage);
					}
					break;
			}

			// and save it to disk
			string imageFileName = GetImageFileName(stlHashCode);

			if (partExtension == ".png")
			{
				ImageIO.SaveImageData(imageFileName, bigRender);
			}
			else
			{
				ImageTgaIO.SaveImageData(imageFileName, bigRender);
			}

			bigRender.SetRecieveBlender(new BlenderPreMultBGRA());

			this.thumbnailImage = ImageBuffer.CreateScaledImage(bigRender, (int)Width, (int)Height);

			UiThread.RunOnIdle(this.EnsureImageUpdated);

			OnDoneRendering();
		}
Example #16
0
		private void CreateRectangularBedGridImage(Vector3 displayVolumeToBuild, Vector2 bedCenter)
		{
			int linesInX = (int)Math.Ceiling(displayVolumeToBuild.x / 10);
			int linesInY = (int)Math.Ceiling(displayVolumeToBuild.y / 10);

			lock(lastCreatedBedImage)
			{
				Vector2 bedImageCentimeters = new Vector2(linesInX, linesInY);

				BedImage = new ImageBuffer(1024, 1024, 32, new BlenderBGRA());
				Graphics2D graphics2D = BedImage.NewGraphics2D();
				graphics2D.Clear(bedBaseColor);
				{
					double lineDist = BedImage.Width / (displayVolumeToBuild.x / 10.0);

					double xPositionCm = (-(displayVolume.x / 2.0) + bedCenter.x) / 10.0;
					int xPositionCmInt = (int)Math.Round(xPositionCm);
					double fraction = xPositionCm - xPositionCmInt;
					int pointSize = 20;
					graphics2D.DrawString(xPositionCmInt.ToString(), 4, 4, pointSize, color: bedMarkingsColor);
					for (double linePos = lineDist * (1 - fraction); linePos < BedImage.Width; linePos += lineDist)
					{
						xPositionCmInt++;
						int linePosInt = (int)linePos;
						int lineWidth = 1;
						if (xPositionCmInt == 0)
						{
							lineWidth = 2;
						}
						graphics2D.Line(linePosInt, 0, linePosInt, BedImage.Height, bedMarkingsColor, lineWidth);
						graphics2D.DrawString(xPositionCmInt.ToString(), linePos + 4, 4, pointSize, color: bedMarkingsColor);
					}
				}
				{
					double lineDist = BedImage.Height / (displayVolumeToBuild.y / 10.0);

					double yPositionCm = (-(displayVolume.y / 2.0) + bedCenter.y) / 10.0;
					int yPositionCmInt = (int)Math.Round(yPositionCm);
					double fraction = yPositionCm - yPositionCmInt;
					int pointSize = 20;
					for (double linePos = lineDist * (1 - fraction); linePos < BedImage.Height; linePos += lineDist)
					{
						yPositionCmInt++;
						int linePosInt = (int)linePos;
						int lineWidth = 1;
						if (yPositionCmInt == 0)
						{
							lineWidth = 2;
						}
						graphics2D.Line(0, linePosInt, BedImage.Height, linePosInt, bedMarkingsColor, lineWidth);

						graphics2D.DrawString(yPositionCmInt.ToString(), 4, linePos + 4, pointSize, color: bedMarkingsColor);
					}
				}

				lastCreatedBedImage = BedImage;
				lastLinesCount = new Point2D(linesInX, linesInY);
			}
		}
Example #17
0
		public static ImageBuffer CreateScaledImage(ImageBuffer unscaledSourceImage, int width, int height)
		{
			ImageBuffer destImage = new ImageBuffer(width, height, 32, unscaledSourceImage.GetRecieveBlender());

			// If the source image is more than twice as big as our dest image.
			while (unscaledSourceImage.Width > destImage.Width * 2)
			{
				// The image sampler we use is a 2x2 filter so we need to scale by a max of 1/2 if we want to get good results.
				// So we scale as many times as we need to get the Image to be the right size.
				// If this were going to be a non-uniform scale we could do the x and y separately to get better results.
				ImageBuffer halfImage = new ImageBuffer(unscaledSourceImage.Width / 2, unscaledSourceImage.Height / 2, 32, unscaledSourceImage.GetRecieveBlender());
				halfImage.NewGraphics2D().Render(unscaledSourceImage, 0, 0, 0, halfImage.Width / (double)unscaledSourceImage.Width, halfImage.Height / (double)unscaledSourceImage.Height);
				unscaledSourceImage = halfImage;
			}

			Graphics2D renderGraphics = destImage.NewGraphics2D();
			renderGraphics.ImageRenderQuality = Graphics2D.TransformQuality.Best;

			renderGraphics.Render(unscaledSourceImage, 0, 0, 0, destImage.Width / (double)unscaledSourceImage.Width, destImage.Height / (double)unscaledSourceImage.Height);

			destImage.MarkImageChanged();

			return destImage;
        }
        public void SavingFunction()
        {
            currentlySaving = true;
            countThatHaveBeenSaved = 0;
            // first create images for all the parts
            foreach (FileNameAndPresentationName stlFileNames in stlFilesToPrint)
            {
                Mesh loadedMesh = StlProcessing.Load(stlFileNames.fileName);
                if (loadedMesh != null)
                {
                    AxisAlignedBoundingBox aabb = loadedMesh.GetAxisAlignedBoundingBox();
                    RectangleDouble bounds2D = new RectangleDouble(aabb.minXYZ.x, aabb.minXYZ.y, aabb.maxXYZ.x, aabb.maxXYZ.y);
                    double widthInMM = bounds2D.Width + PartMarginMM * 2;
                    double textSpaceMM = 5;
                    double heightMM = textSpaceMM + bounds2D.Height + PartMarginMM * 2;

                    TypeFacePrinter typeFacePrinter = new TypeFacePrinter(stlFileNames.presentationName, 28, Vector2.Zero, Justification.Center, Baseline.BoundsCenter);
                    double sizeOfNameX = typeFacePrinter.GetSize().x + PartMarginPixels * 2;
                    Vector2 sizeOfRender = new Vector2(widthInMM * PixelPerMM, heightMM * PixelPerMM);

                    ImageBuffer imageOfPart = new ImageBuffer((int)(Math.Max(sizeOfNameX, sizeOfRender.x)), (int)(sizeOfRender.y), 32, new BlenderBGRA());
                    typeFacePrinter.Origin = new Vector2(imageOfPart.Width / 2, (textSpaceMM / 2) * PixelPerMM);

                    Graphics2D partGraphics2D = imageOfPart.NewGraphics2D();

                    RectangleDouble rectBounds = new RectangleDouble(0, 0, imageOfPart.Width, imageOfPart.Height);
                    double strokeWidth = .5 * PixelPerMM;
                    rectBounds.Inflate(-strokeWidth / 2);
                    RoundedRect rect = new RoundedRect(rectBounds, PartMarginMM * PixelPerMM);
                    partGraphics2D.Render(rect, RGBA_Bytes.LightGray);
                    Stroke rectOutline = new Stroke(rect, strokeWidth);
                    partGraphics2D.Render(rectOutline, RGBA_Bytes.DarkGray);

                    PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partGraphics2D, loadedMesh, new Vector2(-bounds2D.Left + PartMarginMM, -bounds2D.Bottom + textSpaceMM + PartMarginMM), PixelPerMM, RGBA_Bytes.Black);
                    partGraphics2D.Render(typeFacePrinter, RGBA_Bytes.Black);

                    partImagesToPrint.Add(new PartImage(imageOfPart));
                }
                countThatHaveBeenSaved++;
                if (UpdateRemainingItems != null)
                {
                    UpdateRemainingItems(this, new StringEventArgs(Path.GetFileName(stlFileNames.presentationName)));
                }
            }

            partImagesToPrint.Sort(BiggestToLittlestImages);

            PdfDocument document = new PdfDocument();
            document.Info.Title = "MatterHackers Parts Sheet";
            document.Info.Author = "MatterHackers Inc.";
            document.Info.Subject = "This is a list of the parts that are in a queue from MatterControl.";
            document.Info.Keywords = "MatterControl, STL, 3D Printing";

            int nextPartToPrintIndex = 0;
            int plateNumber = 1;
            bool done = false;
            while (!done && nextPartToPrintIndex < partImagesToPrint.Count)
            {
                PdfPage pdfPage = document.AddPage();
                CreateOnePage(plateNumber++, ref nextPartToPrintIndex, pdfPage);
            }
			try
			{
                // save the final document
            	document.Save(pathAndFileToSaveTo);
                // Now try and open the document. This will lanch whatever PDF viewer is on the system and ask it 
                // to show the file (at least on Windows).
            	Process.Start(pathAndFileToSaveTo);
			}
			catch (Exception)
            {
			}

            OnDoneSaving();
            currentlySaving = false;
        }
Example #19
0
		public static void Main(string[] args)
		{
			// first we will show how to use the simple drawing functions in graphics 2D
			{
				ImageBuffer simpleImage = new ImageBuffer(640, 480, 32, new BlenderBGRA());
				Graphics2D simpleImageGraphics2D = simpleImage.NewGraphics2D();
				// clear the image to white
				simpleImageGraphics2D.Clear(RGBA_Bytes.White);
				// draw a circle
				simpleImageGraphics2D.Circle(50, 50, 30, RGBA_Bytes.Blue);
				// draw a line
				simpleImageGraphics2D.Line(10, 100, 520, 50, new RGBA_Bytes(20, 200, 200));
				// draw a filled box
				simpleImageGraphics2D.FillRectangle(60, 260, 200, 280, RGBA_Bytes.Yellow);
				// and an outline around it
				simpleImageGraphics2D.Rectangle(60, 260, 200, 280, RGBA_Bytes.Magenta);
				// draw some text
				simpleImageGraphics2D.DrawString("A Simple Example", 300, 400, 20);

				// and save this image out
				ImageTgaIO.Save(simpleImage, "SimpleDrawAndSave.tga");
			}

			// now we will we will show how to use the render function to draw more complex things
			{
				ImageBuffer lessSimpleImage = new ImageBuffer(640, 480, 32, new BlenderBGRA());
				Graphics2D lessSimpleImageGraphics2D = lessSimpleImage.NewGraphics2D();
				// clear the image to white
				lessSimpleImageGraphics2D.Clear(RGBA_Bytes.White);
				// draw a circle
				Ellipse ellipseTest = new Ellipse(0, 0, 100, 50);
				for (double angleDegrees = 0; angleDegrees < 180; angleDegrees += 22.5)
				{
					VertexSourceApplyTransform rotatedTransform = new VertexSourceApplyTransform(ellipseTest, Affine.NewRotation(MathHelper.DegreesToRadians(angleDegrees)));
					VertexSourceApplyTransform rotatedAndTranslatedTransform = new VertexSourceApplyTransform(rotatedTransform, Affine.NewTranslation(lessSimpleImage.Width / 2, 150));
					lessSimpleImageGraphics2D.Render(rotatedAndTranslatedTransform, RGBA_Bytes.Yellow);
					Stroke ellipseOutline = new Stroke(rotatedAndTranslatedTransform, 3);
					lessSimpleImageGraphics2D.Render(ellipseOutline, RGBA_Bytes.Blue);
				}

				// and a little polygon
				PathStorage littlePoly = new PathStorage();
				littlePoly.MoveTo(50, 50);
				littlePoly.LineTo(150, 50);
				littlePoly.LineTo(200, 200);
				littlePoly.LineTo(50, 150);
				littlePoly.LineTo(50, 50);
				lessSimpleImageGraphics2D.Render(littlePoly, RGBA_Bytes.Cyan);

				// draw some text
				TypeFacePrinter textPrinter = new TypeFacePrinter("Printing from a printer", 30, justification: Justification.Center);
				IVertexSource translatedText = new VertexSourceApplyTransform(textPrinter, Affine.NewTranslation(new Vector2(lessSimpleImage.Width / 2, lessSimpleImage.Height / 4 * 3)));
				lessSimpleImageGraphics2D.Render(translatedText, RGBA_Bytes.Red);
				Stroke strokedText = new Stroke(translatedText);
				lessSimpleImageGraphics2D.Render(strokedText, RGBA_Bytes.Black);

				IVertexSource rotatedText = new VertexSourceApplyTransform(textPrinter, Affine.NewRotation(MathHelper.DegreesToRadians(90)));
				IVertexSource rotatedTranslatedText = new VertexSourceApplyTransform(rotatedText, Affine.NewTranslation(new Vector2(40, lessSimpleImage.Height / 2)));
				lessSimpleImageGraphics2D.Render(rotatedTranslatedText, RGBA_Bytes.Black);

				// and save this image out
				ImageTgaIO.Save(lessSimpleImage, "LessSimpleDrawAndSave.tga");
			}
		}
Example #20
0
		private void CreateGlDataForImage(ImageBuffer bufferedImage, bool TextureMagFilterLinear)
		{
			//Next we expand the image into an openGL texture
			int imageWidth = bufferedImage.Width;
			int imageHeight = bufferedImage.Height;
			int bufferOffset;
			byte[] imageBuffer = bufferedImage.GetBuffer(out bufferOffset);
			int hardwareWidth = SmallestHardwareCompatibleTextureSize(imageWidth);
			int hardwareHeight = SmallestHardwareCompatibleTextureSize(imageHeight);
			byte[] hardwareExpandedPixelBuffer = imageBuffer;
			if (hardwareWidth != imageWidth || hardwareHeight != imageHeight)
			{
				// we have to put the data on a buffer that GL can handle.
				hardwareExpandedPixelBuffer = new byte[4 * hardwareWidth * hardwareHeight];
				switch (bufferedImage.BitDepth)
				{
					case 32:
						for (int y = 0; y < hardwareHeight; y++)
						{
							for (int x = 0; x < hardwareWidth; x++)
							{
								int pixelIndex = 4 * (x + y * hardwareWidth);
								if (x >= imageWidth || y >= imageHeight)
								{
									hardwareExpandedPixelBuffer[pixelIndex + 0] = 0;
									hardwareExpandedPixelBuffer[pixelIndex + 1] = 0;
									hardwareExpandedPixelBuffer[pixelIndex + 2] = 0;
									hardwareExpandedPixelBuffer[pixelIndex + 3] = 0;
								}
								else
								{
									hardwareExpandedPixelBuffer[pixelIndex + 0] = imageBuffer[4 * (x + y * imageWidth) + 2];
									hardwareExpandedPixelBuffer[pixelIndex + 1] = imageBuffer[4 * (x + y * imageWidth) + 1];
									hardwareExpandedPixelBuffer[pixelIndex + 2] = imageBuffer[4 * (x + y * imageWidth) + 0];
									hardwareExpandedPixelBuffer[pixelIndex + 3] = imageBuffer[4 * (x + y * imageWidth) + 3];
								}
							}
						}
						break;

					default:
						throw new NotImplementedException();
				}
			}

			GL.Enable(EnableCap.Texture2D);
			// Create the texture handle
			GL.GenTextures(1, out glData.glTextureHandle);

			// Set up some texture parameters for openGL
			GL.BindTexture(TextureTarget.Texture2D, glData.glTextureHandle);
			if (TextureMagFilterLinear)
			{
				GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
			}
			else
			{
				GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
			}

			if (createdWithMipMaps)
			{
				GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
			}
			else
			{
				GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
			}

			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
			GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);

			// Create the texture
			switch (bufferedImage.BitDepth)
			{
#if false // not implemented in our gl wrapper and never used in our current code
                case 8:
                    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance, hardwareWidth, hardwareHeight,
                        0, PixelFormat.Luminance, PixelType.UnsignedByte, hardwareExpandedPixelBuffer);
                    break;

                case 24:
                    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, hardwareWidth, hardwareHeight,
                        0, PixelFormat.Rgb, PixelType.UnsignedByte, hardwareExpandedPixelBuffer);
                    break;
#endif

				case 32:
#if __ANDROID__
					GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, hardwareWidth, hardwareHeight,
						0, PixelFormat.Rgba, PixelType.UnsignedByte, hardwareExpandedPixelBuffer);
#else
					GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, hardwareWidth, hardwareHeight,
						0, PixelFormat.Bgra, PixelType.UnsignedByte, hardwareExpandedPixelBuffer);
#endif
					break;

				default:
					throw new NotImplementedException();
			}
			hardwareExpandedPixelBuffer = null;

			if (createdWithMipMaps)
			{
				switch (bufferedImage.BitDepth)
				{
					case 32:
						{
							ImageBuffer sourceImage = new ImageBuffer(bufferedImage);
							ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA());
							tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5);
							int mipLevel = 1;
							while (sourceImage.Width > 1 && sourceImage.Height > 1)
							{
#if __ANDROID__
                                GL.TexImage2D(TextureTarget.Texture2D, mipLevel++, PixelInternalFormat.Rgba, tempImage.Width, tempImage.Height,
									0, PixelFormat.Rgba, PixelType.UnsignedByte, tempImage.GetBuffer());
#else
								GL.TexImage2D(TextureTarget.Texture2D, mipLevel++, PixelInternalFormat.Rgba, tempImage.Width, tempImage.Height,
									0, PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer());
#endif
								sourceImage = new ImageBuffer(tempImage);
								tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA());
								tempImage.NewGraphics2D().Render(sourceImage, 0, 0,
									0,
									(double)tempImage.Width / (double)sourceImage.Width,
									(double)tempImage.Height / (double)sourceImage.Height);
							}
						}
						break;

					default:
						throw new NotImplementedException();
				}
			}

			float texCoordX = imageWidth / (float)hardwareWidth;
			float texCoordY = imageHeight / (float)hardwareHeight;

			float OffsetX = (float)bufferedImage.OriginOffset.x;
			float OffsetY = (float)bufferedImage.OriginOffset.y;

			glData.textureUVs = new float[8];
			glData.positions = new float[8];

			glData.textureUVs[0] = 0; glData.textureUVs[1] = 0; glData.positions[0] = 0 - OffsetX; glData.positions[1] = 0 - OffsetY;
			glData.textureUVs[2] = 0; glData.textureUVs[3] = texCoordY; glData.positions[2] = 0 - OffsetX; glData.positions[3] = imageHeight - OffsetY;
			glData.textureUVs[4] = texCoordX; glData.textureUVs[5] = texCoordY; glData.positions[4] = imageWidth - OffsetX; glData.positions[5] = imageHeight - OffsetY;
			glData.textureUVs[6] = texCoordX; glData.textureUVs[7] = 0; glData.positions[6] = imageWidth - OffsetX; glData.positions[7] = 0 - OffsetY;
		}
Example #21
0
        //矩形
        public static CCSprite CreateRectangle(
            double width, double height,
            double radiusX, double radiusY,
            CCColor4B fill, CCColor4B stroke,
            double strokeThickness = 1
            )
        {
            ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA());
            Graphics2D g = buffer.NewGraphics2D();
            RoundedRect path;
            if (stroke.A > 0) //有border
            {
                //border是以线的中间对齐,所以转换成int,如果是1个像素,正好变成零
                int halfThickness = (int)(strokeThickness / 2);
                path = new RoundedRect(halfThickness, halfThickness, width - halfThickness, height - halfThickness, Math.Min(radiusX, radiusY));
            }
            else
            {
                path = new RoundedRect(0, 0, width, height, Math.Min(radiusX, radiusY));
            }
            if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A));
            if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A));

            Texture2D xnaTexture = XnaTexture((int)width, (int)height);
            xnaTexture.SetData<byte>(buffer.GetBuffer());
            CCTexture2D ccTexture = new CCTexture2D();
            ccTexture.InitWithTexture(xnaTexture);
            return new CCSprite(ccTexture);
        }
Example #22
0
        //路径
        public static CCSprite CreatePath(
            double width, double height,
            string[] paths,
            double contentX, double contentY,
            double contentWidth, double contentHeight,
            CCColor4B fill, CCColor4B stroke,
            double strokeThickness = 1,
            UIGraphic.Stretch stretch = UIGraphic.Stretch.StretchNone
            )
        {
            if (width == 0) width = contentWidth;
            if (height == 0) height = contentHeight;

            ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA());
            Graphics2D g = buffer.NewGraphics2D();

            double scalex = 0;
            double scaley = 0;
            //if (stretch == Stretch.StretchNone) { } else
            if (stretch == UIGraphic.Stretch.StretchFill)
            {
                if (width != contentWidth || height != contentHeight)
                {
                    scalex = width / contentWidth;
                    scaley = height / contentHeight;
                }
            }
            else if (stretch == UIGraphic.Stretch.StretchUniformToFill)
            {
                scalex = scaley = Math.Min(width / contentWidth, height / contentHeight);
            }

            foreach (string path in paths)
            {
                IVertexSource vertexs = MiniLanguage.CreatePathStorage(path);
                if (contentX != 0 || contentY != 0)
                    vertexs = new VertexSourceApplyTransform(vertexs, Affine.NewTranslation(-contentX, -contentY));

                if (scalex != 0 || scaley != 0)
                    vertexs = new VertexSourceApplyTransform(vertexs, Affine.NewScaling(scalex, scaley));

                if (fill.A > 0) g.Render(vertexs, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A));
                if (stroke.A > 0) g.Render(new Stroke(vertexs, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A));
            }

            Texture2D xnaTexture = XnaTexture((int)width, (int)height);
            xnaTexture.SetData<byte>(buffer.GetBuffer());
            CCTexture2D ccTexture = new CCTexture2D();
            ccTexture.InitWithTexture(xnaTexture);
            return new CCSprite(ccTexture);
        }
Example #23
0
 public static CCSprite CreateLine(
     int width, int height,
     CCColor4B stroke,
     double strokeThickness = 1
     )
 {
     ImageBuffer buffer = new ImageBuffer(width, height, 32, new BlenderRGBA());
     Graphics2D g = buffer.NewGraphics2D();
     if (stroke.A > 0)
     {
         //g.Line没有厚度
         PathStorage linesToDraw = new PathStorage();
         linesToDraw.remove_all();
         linesToDraw.MoveTo(0, 0);
         linesToDraw.LineTo(width, height);
         Stroke StrockedLineToDraw = new Stroke(linesToDraw, strokeThickness);
         g.Render(StrockedLineToDraw, new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A));
     }
     Texture2D xnaTexture = XnaTexture((int)width, (int)height);
     xnaTexture.SetData<byte>(buffer.GetBuffer());
     CCTexture2D ccTexture = new CCTexture2D();
     ccTexture.InitWithTexture(xnaTexture);
     return new CCSprite(ccTexture);
 }
Example #24
0
 //圆形
 public static CCSprite CreateEllipse(
     double width, double height,
     CCColor4B fill, CCColor4B stroke,
     double strokeThickness = 1
     )
 {
     ImageBuffer buffer = new ImageBuffer((int)width, (int)height, 32, new BlenderRGBA());
     Graphics2D g = buffer.NewGraphics2D();
     MatterHackers.Agg.VertexSource.Ellipse path;
     if (stroke.A > 0) //有border
     {
         //border是以线的中间对齐,所以转换成int,如果是1个像素,正好变成零
         int halfThickness = (int)(strokeThickness / 2);
         path = new MatterHackers.Agg.VertexSource.Ellipse(width / 2, height / 2, width / 2 - halfThickness, height / 2 - halfThickness);
     }
     else
     {
         path = new MatterHackers.Agg.VertexSource.Ellipse(width / 2, height / 2, width / 2, height / 2);
     }
     if (fill.A > 0) g.Render(path, new RGBA_Bytes(fill.R, fill.G, fill.B, fill.A));
     if (stroke.A > 0) g.Render(new Stroke(path, strokeThickness), new RGBA_Bytes(stroke.R, stroke.G, stroke.B, stroke.A));
     Texture2D xnaTexture = XnaTexture((int)width, (int)height);
     xnaTexture.SetData<byte>(buffer.GetBuffer());
     CCTexture2D ccTexture = new CCTexture2D();
     ccTexture.InitWithTexture(xnaTexture);
     return new CCSprite(ccTexture);
 }
Example #25
0
		static public ImageGlPlugin GetImageGlPlugin(ImageBuffer imageToGetDisplayListFor, bool createAndUseMipMaps, bool TextureMagFilterLinear = true)
		{
			ImageGlPlugin plugin;
			imagesWithCacheData.TryGetValue(imageToGetDisplayListFor.GetBuffer(), out plugin);

			using (TimedLock.Lock(glDataNeedingToBeDeleted, "GetImageGlPlugin"))
			{
				// We run this in here to ensure that we are on the correct thread and have the correct
				// glcontext realized.
				for (int i = glDataNeedingToBeDeleted.Count - 1; i >= 0; i--)
				{
					int textureToDelete = glDataNeedingToBeDeleted[i].glTextureHandle;
					if (glDataNeedingToBeDeleted[i].refreshCountCreatedOn == currentGlobalRefreshCount)
					{
						GL.DeleteTextures(1, ref textureToDelete);
					}
					glDataNeedingToBeDeleted.RemoveAt(i);
				}
			}

#if ON_IMAGE_CHANGED_ALWAYS_CREATE_IMAGE
			if (plugin != null
				&& (imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount
				|| plugin.glData.refreshCountCreatedOn != currentGlobalRefreshCount))
			{
				int textureToDelete = plugin.GLTextureHandle;
				if (plugin.glData.refreshCountCreatedOn == currentGlobalRefreshCount)
				{
					GL.DeleteTextures(1, ref textureToDelete);
				}
				plugin.glData.glTextureHandle = 0;
				imagesWithCacheData.Remove(imageToGetDisplayListFor.GetBuffer());
				plugin = null;
			}

			if (plugin == null)
			{
				ImageGlPlugin newPlugin = new ImageGlPlugin();
				imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin);
				newPlugin.createdWithMipMaps = createAndUseMipMaps;
				newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear);
				newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount;
				newPlugin.glData.refreshCountCreatedOn = currentGlobalRefreshCount;
				return newPlugin;
			}
#else
            if (plugin == null)
            {
                ImageGlPlugin newPlugin = new ImageGlPlugin();
                imagesWithCacheData.Add(imageToGetDisplayListFor.GetBuffer(), newPlugin);
                newPlugin.createdWithMipMaps = createAndUseMipMaps;
                newPlugin.CreateGlDataForImage(imageToGetDisplayListFor, TextureMagFilterLinear);
                newPlugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount;
				newPlugin.refreshCountCreatedOn = currentGlobalRefreshCount;
                return newPlugin;
            }

            if(imageToGetDisplayListFor.ChangedCount != plugin.imageUpdateCount
				|| plugin.refreshCountCreatedOn != currentGlobalRefreshCount)
            {
                plugin.imageUpdateCount = imageToGetDisplayListFor.ChangedCount;
				plugin.refreshCountCreatedOn = currentGlobalRefreshCount;
                GL.BindTexture(TextureTarget.Texture2D, plugin.GLTextureHandle);
                // Create the texture
                switch (imageToGetDisplayListFor.BitDepth)
                {
                    case 8:
                        GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height,
                            PixelFormat.Luminance, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer());
                        break;

                    case 24:
                        // our bitmaps are not padded and GL is having a problem with them so don't use 24 bit unless you fix this.
                        GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height,
                            PixelFormat.Bgr, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer());
                        break;

                    case 32:
                        GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, imageToGetDisplayListFor.Width, imageToGetDisplayListFor.Height,
                            PixelFormat.Bgra, PixelType.UnsignedByte, imageToGetDisplayListFor.GetBuffer());
                        break;

                    default:
                        throw new NotImplementedException();
                }

                if (plugin.createdWithMipMaps)
                {
                    if (GLMajorVersion < 3)
                    {
                        switch (imageToGetDisplayListFor.BitDepth)
                        {
                            case 32:
                                {
                                    ImageBuffer sourceImage = new ImageBuffer(imageToGetDisplayListFor);
                                    ImageBuffer tempImage = new ImageBuffer(sourceImage.Width / 2, sourceImage.Height / 2, 32, new BlenderBGRA());
                                    tempImage.NewGraphics2D().Render(sourceImage, 0, 0, 0, .5, .5);
                                    int mipLevel = 1;
                                    while (sourceImage.Width > 1 && sourceImage.Height > 1)
                                    {
                                        GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel++, 0, 0, tempImage.Width, tempImage.Height,
                                            PixelFormat.Bgra, PixelType.UnsignedByte, tempImage.GetBuffer());

                                        sourceImage = new ImageBuffer(tempImage);
                                        tempImage = new ImageBuffer(Math.Max(1, sourceImage.Width / 2), Math.Max(1, sourceImage.Height / 2), 32, new BlenderBGRA());
                                        tempImage.NewGraphics2D().Render(sourceImage, 0, 0,
                                            0,
                                            (double)tempImage.Width / (double)sourceImage.Width,
                                            (double)tempImage.Height / (double)sourceImage.Height);
                                    }
                                }
                                break;

                            default:
                                throw new NotImplementedException();
                        }
                    }
                    else
                    {
                        GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
                    }
                }
            }
#endif
			return plugin;
		}
Example #26
0
		public ImageBuffer GetImageForCharacter(char character, double xFraction, double yFraction, RGBA_Bytes color)
		{
			if (xFraction > 1 || xFraction < 0 || yFraction > 1 || yFraction < 0)
			{
				throw new ArgumentException("The x and y fractions must both be between 0 and 1.");
			}

			ImageBuffer imageForCharacter;
			Dictionary<char, ImageBuffer> characterImageCache = StyledTypeFaceImageCache.GetCorrectCache(this.TypeFace, color, this.emSizeInPixels);
			characterImageCache.TryGetValue(character, out imageForCharacter);
			if (imageForCharacter != null)
			{
				return imageForCharacter;
			}

			IVertexSource glyphForCharacter = GetGlyphForCharacter(character);
			if (glyphForCharacter == null)
			{
				return null;
			}

			glyphForCharacter.rewind(0);
			double x, y;
			ShapePath.FlagsAndCommand curCommand = glyphForCharacter.vertex(out x, out y);
			RectangleDouble bounds = new RectangleDouble(x, y, x, y);
			while (curCommand != ShapePath.FlagsAndCommand.CommandStop)
			{
				bounds.ExpandToInclude(x, y);
				curCommand = glyphForCharacter.vertex(out x, out y);
			}

			int descentExtraHeight = (int)(-DescentInPixels + .5);
			ImageBuffer charImage = new ImageBuffer(Math.Max((int)(bounds.Width + .5), 1) + 1, Math.Max((int)(EmSizeInPixels + descentExtraHeight + .5), 1) + 1, 32, new BlenderPreMultBGRA());
			charImage.OriginOffset = new VectorMath.Vector2(0, descentExtraHeight);
			Graphics2D graphics = charImage.NewGraphics2D();
			graphics.Render(glyphForCharacter, xFraction, yFraction + descentExtraHeight, color);
			characterImageCache[character] = charImage;

			return charImage;
		}
        void CreateOnePage(int plateNumber, ref int nextPartToPrintIndex, PdfPage pdfPage)
        {
            ImageBuffer plateInventoryImage = new ImageBuffer((int)(300 * 8.5), 300 * 11, 32, new BlenderBGRA());
            Graphics2D plateGraphics = plateInventoryImage.NewGraphics2D();
            double currentlyPrintingHeightPixels = PrintTopOfPage(plateInventoryImage, plateGraphics);

            Vector2 offset = new Vector2(PageMarginPixels.Left, currentlyPrintingHeightPixels);
            double tallestHeight = 0;
            List<PartImage> partsOnLine = new List<PartImage>();
            while (nextPartToPrintIndex < partImagesToPrint.Count)
            {
                ImageBuffer image = partImagesToPrint[nextPartToPrintIndex].image;
                tallestHeight = Math.Max(tallestHeight, image.Height);

                if (partsOnLine.Count > 0 && offset.x + image.Width > plateInventoryImage.Width - PageMarginPixels.Right)
                {
                    if (partsOnLine.Count == 1)
                    {
                        plateGraphics.Render(partsOnLine[0].image, plateInventoryImage.Width / 2 - partsOnLine[0].image.Width / 2, offset.y - tallestHeight);
                    }
                    else
                    {
                        foreach (PartImage partToDraw in partsOnLine)
                        {
                            plateGraphics.Render(partToDraw.image, partToDraw.xOffset, offset.y - tallestHeight);
                        }
                    }

                    offset.x = PageMarginPixels.Left;
                    offset.y -= (tallestHeight + PartPaddingPixels * 2);
                    tallestHeight = 0;
                    partsOnLine.Clear();
                    if (offset.y - image.Height < PageMarginPixels.Bottom)
                    {
                        break;
                    }
                }
                else
                {
                    partImagesToPrint[nextPartToPrintIndex].xOffset = offset.x;
                    partsOnLine.Add(partImagesToPrint[nextPartToPrintIndex]);
                    //plateGraphics.Render(image, offset.x, offset.y - image.Height);
                    offset.x += image.Width + PartPaddingPixels * 2;
                    nextPartToPrintIndex++;
                }
            }

            // print the last line of parts
            foreach (PartImage partToDraw in partsOnLine)
            {
                plateGraphics.Render(partToDraw.image, partToDraw.xOffset, offset.y - tallestHeight);
            }

            TypeFacePrinter printer = new TypeFacePrinter(string.Format("{0}", Path.GetFileNameWithoutExtension(pathAndFileToSaveTo)), 32, justification: Justification.Center);
            printer.Origin = new Vector2(plateGraphics.DestImage.Width/2, 110);
            plateGraphics.Render(printer, RGBA_Bytes.Black);

            printer = new TypeFacePrinter(string.Format("Page {0}", plateNumber), 28, justification: Justification.Center);
            printer.Origin = new Vector2(plateGraphics.DestImage.Width / 2, 60);
            plateGraphics.Render(printer, RGBA_Bytes.Black);

            string applicationUserDataPath = ApplicationDataStorage.Instance.ApplicationUserDataPath;
            string folderToSavePrintsTo = Path.Combine(applicationUserDataPath, "data", "temp", "plateImages");
            string jpegFileName = Path.Combine(folderToSavePrintsTo, plateNumber.ToString() + ".jpeg");

            if (!Directory.Exists(folderToSavePrintsTo))
            {
                Directory.CreateDirectory(folderToSavePrintsTo);
            }
            ImageIO.SaveImageData(jpegFileName, plateInventoryImage);

            XGraphics gfx = XGraphics.FromPdfPage(pdfPage);
            XImage jpegImage = XImage.FromFile(jpegFileName);
            //double width = jpegImage.PixelWidth * 72 / jpegImage.HorizontalResolution;
            //double height = jpegImage.PixelHeight * 72 / jpegImage. .HorizontalResolution;

            gfx.DrawImage(jpegImage, 0, 0, pdfPage.Width, pdfPage.Height);
        }
		private void CreateThumbnail()
		{
			string stlHashCode = this.ItemWrapper.FileHashCode.ToString();

			ImageBuffer bigRender = new ImageBuffer();
			if (!File.Exists(this.ItemWrapper.FileLocation))
			{
				return;
			}

			List<MeshGroup> loadedMeshGroups = MeshFileIo.Load(this.ItemWrapper.FileLocation);

			RenderType renderType = GetRenderType(this.ItemWrapper.FileLocation);

			switch (renderType)
			{
				case RenderType.RAY_TRACE:
					{
						ThumbnailTracer tracer = new ThumbnailTracer(loadedMeshGroups, BigRenderSize.x, BigRenderSize.y);
						tracer.DoTrace();

						bigRender = tracer.destImage;
					}
					break;

				case RenderType.PERSPECTIVE:
					{
						ThumbnailTracer tracer = new ThumbnailTracer(loadedMeshGroups, BigRenderSize.x, BigRenderSize.y);
						this.thumbnailImage = new ImageBuffer(this.buildingThumbnailImage);
						this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));

						bigRender = new ImageBuffer(BigRenderSize.x, BigRenderSize.y, 32, new BlenderBGRA());

						foreach (MeshGroup meshGroup in loadedMeshGroups)
						{
							double minZ = double.MaxValue;
							double maxZ = double.MinValue;
							foreach (Mesh loadedMesh in meshGroup.Meshes)
							{
								tracer.GetMinMaxZ(loadedMesh, ref minZ, ref maxZ);
							}

							foreach (Mesh loadedMesh in meshGroup.Meshes)
							{
								tracer.DrawTo(bigRender.NewGraphics2D(), loadedMesh, RGBA_Bytes.White, minZ, maxZ);
							}
						}

						if (bigRender == null)
						{
							bigRender = new ImageBuffer(this.noThumbnailImage);
						}
					}
					break;

				case RenderType.NONE:
				case RenderType.ORTHOGROPHIC:

					this.thumbnailImage = new ImageBuffer(this.buildingThumbnailImage);
					this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));
					bigRender = BuildImageFromMeshGroups(loadedMeshGroups, stlHashCode, BigRenderSize);
					if (bigRender == null)
					{
						bigRender = new ImageBuffer(this.noThumbnailImage);
					}
					break;
			}

			// and save it to disk
			string imageFileName = GetImageFileName(stlHashCode);

			if (partExtension == ".png")
			{
				ImageIO.SaveImageData(imageFileName, bigRender);
			}
			else
			{
				ImageTgaIO.SaveImageData(imageFileName, bigRender);
			}

			ImageBuffer unScaledImage = new ImageBuffer(bigRender.Width, bigRender.Height, 32, new BlenderBGRA());
			unScaledImage.NewGraphics2D().Render(bigRender, 0, 0);
			// If the source image (the one we downloaded) is more than twice as big as our dest image.
			while (unScaledImage.Width > Width * 2)
			{
				// The image sampler we use is a 2x2 filter so we need to scale by a max of 1/2 if we want to get good results.
				// So we scale as many times as we need to to get the Image to be the right size.
				// If this were going to be a non-uniform scale we could do the x and y separatly to get better results.
				ImageBuffer halfImage = new ImageBuffer(unScaledImage.Width / 2, unScaledImage.Height / 2, 32, new BlenderBGRA());
				halfImage.NewGraphics2D().Render(unScaledImage, 0, 0, 0, halfImage.Width / (double)unScaledImage.Width, halfImage.Height / (double)unScaledImage.Height);
				unScaledImage = halfImage;
			}

			this.thumbnailImage = new ImageBuffer((int)Width, (int)Height, 32, new BlenderBGRA());
			this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));
			this.thumbnailImage.NewGraphics2D().Render(unScaledImage, 0, 0, 0, (double)this.thumbnailImage.Width / unScaledImage.Width, (double)this.thumbnailImage.Height / unScaledImage.Height);

			UiThread.RunOnIdle(this.EnsureImageUpdated);

			OnDoneRendering();
		}
		public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress)
		{
			// check if the part is bigger than the build plate (if it is we need to use that as our size)
			AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox();

			buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2);
			buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2);
			buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2);

			// Find all the separate objects that are on the plate
			// Create a 2D image the size of the printer bed at some scale with the parts draw on it top down

			double scaleFactor = 5;
			ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA());
			Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y);

			PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White);

			bool continueProcessin = true;
			if (reportProgress != null)
			{
				reportProgress(.2, "", out continueProcessin);
			}

			//ImageIO.SaveImageData("test part plate 0.png", partPlate);
			// expand the bounds a bit so that we can collect all the vertices and polygons within each bound
			Dilate.DoDilate3x3Binary(partPlate, 1);
			//ImageIO.SaveImageData("test part plate 1.png", partPlate);

			// trace all the bounds of the objects on the plate
			PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate);
			if (polyTreeForPlate == null)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			// get all the discrete areas that are polygons so we can search them
			Polygons discreteAreas = new Polygons();
			GetAreasRecursive(polyTreeForPlate, discreteAreas);
			if (discreteAreas.Count == 0)
			{
				return null;
			}
			else if (discreteAreas.Count == 1)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			Graphics2D graphics2D = partPlate.NewGraphics2D();
			graphics2D.Clear(RGBA_Bytes.Black);
			Random rand = new Random();
			foreach (Polygon polygon in discreteAreas)
			{
				graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255)));
			}
			if (reportProgress != null)
			{
				reportProgress(.5, "", out continueProcessin);
			}
			//ImageIO.SaveImageData("test part plate 2.png", partPlate);

			// add each of the separate bounds polygons to new meshes
			Mesh[] discreteMeshes = new Mesh[discreteAreas.Count];
			for (int i = 0; i < discreteAreas.Count; i++)
			{
				discreteMeshes[i] = new Mesh();
			}

			foreach (Face face in meshToSplit.Faces)
			{
				bool faceDone = false;
				// figure out which area one or more of the vertices are in add the face to the right new mesh
				foreach (FaceEdge faceEdge in face.FaceEdges())
				{
					Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y);
					position += renderOffset;
					position *= scaleFactor;

					for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--)
					{
						if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y)))
						{
							List<Vertex> faceVertices = new List<Vertex>();
							foreach (FaceEdge faceEdgeToAdd in face.FaceEdges())
							{
								Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position);
								faceVertices.Add(newVertex);
							}

							discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray());
							faceDone = true;
							break;
						}
					}

					if (faceDone)
					{
						break;
					}
				}
			}

			if (reportProgress != null)
			{
				reportProgress(.8, "", out continueProcessin);
			}

			for (int i = 0; i < discreteMeshes.Count(); i++)
			{
				Mesh mesh = discreteMeshes[i];
			}

			return discreteMeshes;
		}
		private bool SetImageFast()
		{
			if (this.ItemWrapper == null)
			{
				this.thumbnailImage = new ImageBuffer(this.noThumbnailImage);
				this.Invalidate();
				return true;
			}

			if (this.ItemWrapper.FileLocation == QueueData.SdCardFileName)
			{
				switch (this.Size)
				{
					case ImageSizes.Size115x115:
						{
							StaticData.Instance.LoadIcon(Path.ChangeExtension("icon_sd_card_115x115", partExtension), this.thumbnailImage);
						}
						break;

					case ImageSizes.Size50x50:
						{
							StaticData.Instance.LoadIcon(Path.ChangeExtension("icon_sd_card_50x50", partExtension), this.thumbnailImage);
						}
						break;

					default:
						throw new NotImplementedException();
				}
				this.thumbnailImage.SetRecieveBlender(new BlenderPreMultBGRA());
				Graphics2D graphics = this.thumbnailImage.NewGraphics2D();
				Ellipse outline = new Ellipse(new Vector2(Width / 2.0, Height / 2.0), Width / 2 - Width / 12);
				graphics.Render(new Stroke(outline, Width / 12), RGBA_Bytes.White);

				UiThread.RunOnIdle(this.EnsureImageUpdated);
				return true;
			}
			else if (Path.GetExtension(this.ItemWrapper.FileLocation).ToUpper() == ".GCODE")
			{
				CreateImage(this, Width, Height);
				this.thumbnailImage.SetRecieveBlender(new BlenderPreMultBGRA());
				Graphics2D graphics = this.thumbnailImage.NewGraphics2D();
				Vector2 center = new Vector2(Width / 2.0, Height / 2.0);
				Ellipse outline = new Ellipse(center, Width / 2 - Width / 12);
				graphics.Render(new Stroke(outline, Width / 12), RGBA_Bytes.White);
				graphics.DrawString("GCode", center.x, center.y, 8 * Width / 50, Agg.Font.Justification.Center, Agg.Font.Baseline.BoundsCenter, color: RGBA_Bytes.White);

				UiThread.RunOnIdle(this.EnsureImageUpdated);
				return true;
			}
			else if (!File.Exists(this.ItemWrapper.FileLocation))
			{
				CreateImage(this, Width, Height);
				this.thumbnailImage.SetRecieveBlender(new BlenderPreMultBGRA());
				Graphics2D graphics = this.thumbnailImage.NewGraphics2D();
				Vector2 center = new Vector2(Width / 2.0, Height / 2.0);
				graphics.DrawString("Missing", center.x, center.y, 8 * Width / 50, Agg.Font.Justification.Center, Agg.Font.Baseline.BoundsCenter, color: RGBA_Bytes.White);

				UiThread.RunOnIdle(this.EnsureImageUpdated);
				return true;
			}
			else if (MeshIsTooBigToLoad(this.ItemWrapper.FileLocation))
			{
				CreateImage(this, Width, Height);
				this.thumbnailImage.SetRecieveBlender(new BlenderPreMultBGRA());
				Graphics2D graphics = this.thumbnailImage.NewGraphics2D();
				Vector2 center = new Vector2(Width / 2.0, Height / 2.0);
				double yOffset = 8 * Width / 50 * TextWidget.GlobalPointSizeScaleRatio * 1.5;
				graphics.DrawString("Too Big\nto\nRender", center.x, center.y + yOffset, 8 * Width / 50, Agg.Font.Justification.Center, Agg.Font.Baseline.BoundsCenter, color: RGBA_Bytes.White);

				UiThread.RunOnIdle(this.EnsureImageUpdated);
				return true;
			}

			string stlHashCode = this.ItemWrapper.FileHashCode.ToString();

			if (stlHashCode != "0")
			{
				ImageBuffer bigRender = LoadImageFromDisk(this, stlHashCode);
				if (bigRender == null)
				{
					this.thumbnailImage = new ImageBuffer(buildingThumbnailImage);
					return false;
				}

				ImageBuffer unScaledImage = new ImageBuffer(bigRender.Width, bigRender.Height, 32, new BlenderBGRA());
				unScaledImage.NewGraphics2D().Render(bigRender, 0, 0);
				// If the source image (the one we downloaded) is more than twice as big as our dest image.
				while (unScaledImage.Width > Width * 2)
				{
					// The image sampler we use is a 2x2 filter so we need to scale by a max of 1/2 if we want to get good results.
					// So we scale as many times as we need to to get the Image to be the right size.
					// If this were going to be a non-uniform scale we could do the x and y separatly to get better results.
					ImageBuffer halfImage = new ImageBuffer(unScaledImage.Width / 2, unScaledImage.Height / 2, 32, new BlenderBGRA());
					halfImage.NewGraphics2D().Render(unScaledImage, 0, 0, 0, halfImage.Width / (double)unScaledImage.Width, halfImage.Height / (double)unScaledImage.Height);
					unScaledImage = halfImage;
				}

				this.thumbnailImage = new ImageBuffer((int)Width, (int)Height, 32, new BlenderBGRA());
				this.thumbnailImage.NewGraphics2D().Clear(new RGBA_Bytes(255, 255, 255, 0));
				this.thumbnailImage.NewGraphics2D().Render(unScaledImage, 0, 0, 0, (double)this.thumbnailImage.Width / unScaledImage.Width, (double)this.thumbnailImage.Height / unScaledImage.Height);

				UiThread.RunOnIdle(this.EnsureImageUpdated);

				return true;
			}

			return false;
		}