예제 #1
0
		public override void Render(IImageByte source,
			double destX, double destY,
			double angleRadians,
			double inScaleX, double inScaleY)
		{
			{ // exit early if the dest and source bounds don't touch.
				// TODO: <BUG> make this do rotation and scalling
				RectangleInt sourceBounds = source.GetBounds();
				RectangleInt destBounds = this.destImageByte.GetBounds();
				sourceBounds.Offset((int)destX, (int)destY);

				if (!RectangleInt.DoIntersect(sourceBounds, destBounds))
				{
					if (inScaleX != 1 || inScaleY != 1 || angleRadians != 0)
					{
						throw new NotImplementedException();
					}
					return;
				}
			}

			double scaleX = inScaleX;
			double scaleY = inScaleY;

			Affine graphicsTransform = GetTransform();
			if (!graphicsTransform.is_identity())
			{
				if (scaleX != 1 || scaleY != 1 || angleRadians != 0)
				{
					throw new NotImplementedException();
				}
				graphicsTransform.transform(ref destX, ref destY);
			}

#if false // this is an optomization that eliminates the drawing of images that have their alpha set to all 0 (happens with generated images like explosions).
	        MaxAlphaFrameProperty maxAlphaFrameProperty = MaxAlphaFrameProperty::GetMaxAlphaFrameProperty(source);

	        if((maxAlphaFrameProperty.GetMaxAlpha() * color.A_Byte) / 256 <= ALPHA_CHANNEL_BITS_DIVISOR)
	        {
		        m_OutFinalBlitBounds.SetRect(0,0,0,0);
	        }
#endif
			bool IsScaled = (scaleX != 1 || scaleY != 1);

			bool IsRotated = true;
			if (Math.Abs(angleRadians) < (0.1 * MathHelper.Tau / 360))
			{
				IsRotated = false;
				angleRadians = 0;
			}

			//bool IsMipped = false;
			double sourceOriginOffsetX = source.OriginOffset.x;
			double sourceOriginOffsetY = source.OriginOffset.y;
			bool CanUseMipMaps = IsScaled;
			if (scaleX > 0.5 || scaleY > 0.5)
			{
				CanUseMipMaps = false;
			}

			bool renderRequriesSourceSampling = IsScaled || IsRotated || destX != (int)destX || destY != (int)destY;

			// this is the fast drawing path
			if (renderRequriesSourceSampling)
			{
#if false // if the scalling is small enough the results can be improved by using mip maps
	        if(CanUseMipMaps)
	        {
		        CMipMapFrameProperty* pMipMapFrameProperty = CMipMapFrameProperty::GetMipMapFrameProperty(source);
		        double OldScaleX = scaleX;
		        double OldScaleY = scaleY;
		        const CFrameInterface* pMippedFrame = pMipMapFrameProperty.GetMipMapFrame(ref scaleX, ref scaleY);
		        if(pMippedFrame != source)
		        {
			        IsMipped = true;
			        source = pMippedFrame;
			        sourceOriginOffsetX *= (OldScaleX / scaleX);
			        sourceOriginOffsetY *= (OldScaleY / scaleY);
		        }

			    HotspotOffsetX *= (inScaleX / scaleX);
			    HotspotOffsetY *= (inScaleY / scaleY);
	        }
#endif
				Affine destRectTransform;
				DrawImageGetDestBounds(source, destX, destY, sourceOriginOffsetX, sourceOriginOffsetY, scaleX, scaleY, angleRadians, out destRectTransform);

				Affine sourceRectTransform = new Affine(destRectTransform);
				// We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004]
				sourceRectTransform.invert();

				span_image_filter spanImageFilter;
				span_interpolator_linear interpolator = new span_interpolator_linear(sourceRectTransform);
				ImageBufferAccessorClip sourceAccessor = new ImageBufferAccessorClip(source, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());

				spanImageFilter = new span_image_filter_rgba_bilinear_clip(sourceAccessor, RGBA_Floats.rgba_pre(0, 0, 0, 0), interpolator);

				DrawImage(source, spanImageFilter, destRectTransform);
#if false // this is some debug you can enable to visualize the dest bounding box
		        LineFloat(BoundingRect.left, BoundingRect.top, BoundingRect.right, BoundingRect.top, WHITE);
		        LineFloat(BoundingRect.right, BoundingRect.top, BoundingRect.right, BoundingRect.bottom, WHITE);
		        LineFloat(BoundingRect.right, BoundingRect.bottom, BoundingRect.left, BoundingRect.bottom, WHITE);
		        LineFloat(BoundingRect.left, BoundingRect.bottom, BoundingRect.left, BoundingRect.top, WHITE);
#endif
			}
			else // TODO: this can be even faster if we do not use an intermediat buffer
			{
				Affine destRectTransform;
				DrawImageGetDestBounds(source, destX, destY, sourceOriginOffsetX, sourceOriginOffsetY, scaleX, scaleY, angleRadians, out destRectTransform);

				Affine sourceRectTransform = new Affine(destRectTransform);
				// We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004]
				sourceRectTransform.invert();

				span_interpolator_linear interpolator = new span_interpolator_linear(sourceRectTransform);
				ImageBufferAccessorClip sourceAccessor = new ImageBufferAccessorClip(source, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());

				span_image_filter spanImageFilter = null;
				switch (source.BitDepth)
				{
					case 32:
						spanImageFilter = new span_image_filter_rgba_nn_stepXby1(sourceAccessor, interpolator);
						break;

					case 24:
						spanImageFilter = new span_image_filter_rgb_nn_stepXby1(sourceAccessor, interpolator);
						break;

					case 8:
						spanImageFilter = new span_image_filter_gray_nn_stepXby1(sourceAccessor, interpolator);
						break;

					default:
						throw new NotImplementedException();
				}
				//spanImageFilter = new span_image_filter_rgba_nn(sourceAccessor, interpolator);

				DrawImage(source, spanImageFilter, destRectTransform);
				DestImage.MarkImageChanged();
			}
		}
예제 #2
0
		public override void OnDraw(Graphics2D graphics2D)
		{
			ImageBuffer widgetsSubImage = ImageBuffer.NewSubImageReference(graphics2D.DestImage, graphics2D.GetClippingRect());

			if (orignialSize.x == 0)
			{
				orignialSize.x = WindowSize.x;
				orignialSize.y = WindowSize.y;
			}

			ImageBuffer destImageWithPreMultBlender = new ImageBuffer();
			switch (widgetsSubImage.BitDepth)
			{
				case 24:
					destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGR());
					break;

				case 32:
					destImageWithPreMultBlender.Attach(widgetsSubImage, new BlenderPreMultBGRA());
					break;

				default:
					throw new Exception("Unknown bit depth");
			}

			ImageClippingProxy clippingProxy_pre = new ImageClippingProxy(destImageWithPreMultBlender);

			clippingProxy_pre.clear(new RGBA_Floats(1.0, 1.0, 1.0));

			Affine src_mtx = Affine.NewIdentity();
			src_mtx *= Affine.NewTranslation(-orignialSize.x / 2 - 10, -orignialSize.y / 2 - 20 - 10);
			src_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
			src_mtx *= Affine.NewScaling(drawScale.Value);
			src_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);

			Affine img_mtx = Affine.NewIdentity();
			img_mtx *= Affine.NewTranslation(-orignialSize.x / 2 + 10, -orignialSize.y / 2 + 20 + 10);
			img_mtx *= Affine.NewRotation(drawAngle.Value * Math.PI / 180.0);
			img_mtx *= Affine.NewScaling(drawScale.Value);
			img_mtx *= Affine.NewTranslation(orignialSize.x / 2, orignialSize.y / 2 + 20);
			img_mtx.invert();

			MatterHackers.Agg.span_allocator sa = new span_allocator();

			span_interpolator_linear interpolator = new span_interpolator_linear(img_mtx);

			span_image_filter sg;
			switch (sourceImage.BitDepth)
			{
				case 24:
					{
						ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
						sg = new span_image_filter_rgb_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
					}
					break;

				case 32:
					{
						ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImage, RGBA_Floats.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes());
						sg = new span_image_filter_rgba_bilinear_clip(source, RGBA_Floats.rgba_pre(0, 0.4, 0, 0.5), interpolator);
					}
					break;

				default:
					throw new Exception("Bad sourc depth");
			}

			ScanlineRasterizer ras = new ScanlineRasterizer();
			ras.SetVectorClipBox(0, 0, Width, Height);
			ScanlineCachePacked8 sl = new ScanlineCachePacked8();
			//scanline_unpacked_8 sl = new scanline_unpacked_8();

			double r = orignialSize.x;
			if (orignialSize.y - 60 < r)
			{
				r = orignialSize.y - 60;
			}

			VertexSource.Ellipse ell = new VertexSource.Ellipse(orignialSize.x / 2.0 + 10,
				orignialSize.y / 2.0 + 20 + 10,
				r / 2.0 + 16.0,
				r / 2.0 + 16.0, 200);

			VertexSourceApplyTransform tr = new VertexSourceApplyTransform(ell, src_mtx);

			ras.add_path(tr);
			//clippingProxy_pre.SetClippingBox(30, 0, (int)width(), (int)height());
			ScanlineRenderer scanlineRenderer = new ScanlineRenderer();
			scanlineRenderer.GenerateAndRender(ras, sl, clippingProxy_pre, sa, sg);

			base.OnDraw(graphics2D);
		}