public override void Render(IImageByte source, double x, double y, double angleRadians, double scaleX, double scaleY) { #if true Affine transform = GetTransform(); if (!transform.is_identity()) { if (scaleX != 1 || scaleY != 1) // || angleDegrees != 0) { throw new NotImplementedException(); } // TODO: <BUG> make this do rotation and scaling transform.transform(ref x, ref y); scaleX *= transform.sx; scaleY *= transform.sy; } #endif #if true // TODO: <BUG> make this do rotation and scaling RectangleInt sourceBounds = source.GetBounds(); sourceBounds.Offset((int)x, (int)y); RectangleInt destBounds = new RectangleInt((int)cachedClipRect.Left, (int)cachedClipRect.Bottom, (int)cachedClipRect.Right, (int)cachedClipRect.Top); if (!RectangleInt.DoIntersect(sourceBounds, destBounds)) { if (scaleX != 1 || scaleY != 1) // || angleDegrees != 0) { //throw new NotImplementedException(); } //return; } #endif ImageBuffer sourceAsImageBuffer = (ImageBuffer)source; ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(sourceAsImageBuffer, false); // Prepare openGL for rendering PushOrthoProjection(); GL.Disable(EnableCap.Lighting); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Translate(x, y, 0); GL.Rotate(MathHelper.RadiansToDegrees(angleRadians), 0, 0, 1); GL.Scale(scaleX, scaleY, 1); RGBA_Bytes color = RGBA_Bytes.White; GL.Color4((byte)color.Red0To255, (byte)color.Green0To255, (byte)color.Blue0To255, (byte)color.Alpha0To255); glPlugin.DrawToGL(); //Restore openGL state PopOrthoProjection(); }
public void CopyFrom(IImageByte sourceImage) { Allocate(sourceImage.Width, sourceImage.Height, sourceImage.StrideInBytesAbs(), sourceImage.BitDepth); // make sure we make an exact copy SetRecieveBlender(new BlenderBGRAExactCopy()); CopyFrom(sourceImage, sourceImage.GetBounds(), 0, 0); // then set the blender to what we expect SetRecieveBlender(sourceImage.GetRecieveBlender()); }
public void CopyFrom(IImageByte sourceImage, RectangleInt sourceImageRect, int destXOffset, int destYOffset) { RectangleInt sourceImageBounds = sourceImage.GetBounds(); RectangleInt clippedSourceImageRect = new RectangleInt(); if (clippedSourceImageRect.IntersectRectangles(sourceImageRect, sourceImageBounds)) { RectangleInt destImageRect = clippedSourceImageRect; destImageRect.Offset(destXOffset, destYOffset); RectangleInt destImageBounds = GetBounds(); RectangleInt clippedDestImageRect = new RectangleInt(); if (clippedDestImageRect.IntersectRectangles(destImageRect, destImageBounds)) { // we need to make sure the source is also clipped to the dest. So, we'll copy this back to source and offset it. clippedSourceImageRect = clippedDestImageRect; clippedSourceImageRect.Offset(-destXOffset, -destYOffset); CopyFromNoClipping(sourceImage, clippedSourceImageRect, destXOffset, destYOffset); } } }
public override void OnParentChanged(EventArgs e) { Button parentButton = (Button)Parent; RectangleInt imageBounds = normalImage.GetBounds(); parentButton.OriginRelativeParent += new Vector2(imageBounds.Left, imageBounds.Bottom); RectangleDouble bounds = parentButton.LocalBounds; bounds.Right += imageBounds.Width; bounds.Top += imageBounds.Height; this.LocalBounds = bounds; parentButton.LocalBounds = bounds; parentButton.MouseEnter += redrawButtonIfRequired; parentButton.MouseDown += redrawButtonIfRequired; parentButton.MouseUp += redrawButtonIfRequired; parentButton.MouseLeave += new EventHandler(parentButton_MouseLeave); base.OnParentChanged(null); }
public override void Render(IImageByte source, double destX, double destY, double angleRadians, double inScaleX, double inScaleY) { Affine graphicsTransform = GetTransform(); // exit early if the dest and source bounds don't touch. // TODO: <BUG> make this do rotation and scaling RectangleInt sourceBounds = source.GetBounds(); RectangleInt destBounds = this.destImageByte.GetBounds(); sourceBounds.Offset((int)(destX + graphicsTransform.tx), (int)(destY + graphicsTransform.ty)); if (!RectangleInt.DoIntersect(sourceBounds, destBounds)) { if (inScaleX != 1 || inScaleY != 1 || angleRadians != 0) { //throw new NotImplementedException(); } //return; } double scaleX = inScaleX; double scaleY = inScaleY; 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 optimization 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 scaling 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 switch (ImageRenderQuality) { case TransformQuality.Fastest: { DrawImageGetDestBounds(source, destX, destY, sourceOriginOffsetX, sourceOriginOffsetY, scaleX, scaleY, angleRadians, out Affine destRectTransform); var 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; var interpolator = new span_interpolator_linear(sourceRectTransform); var sourceAccessor = new ImageBufferAccessorClip(source, ColorF.rgba_pre(0, 0, 0, 0).ToColor()); spanImageFilter = new span_image_filter_rgba_bilinear_clip(sourceAccessor, ColorF.rgba_pre(0, 0, 0, 0), interpolator); DrawImage(spanImageFilter, destRectTransform); } break; case TransformQuality.Best: { DrawImageGetDestBounds(source, destX, destY, sourceOriginOffsetX, sourceOriginOffsetY, scaleX, scaleY, angleRadians, out Affine destRectTransform); var 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(); var interpolator = new span_interpolator_linear(sourceRectTransform); var sourceAccessor = new ImageBufferAccessorClip(source, ColorF.rgba_pre(0, 0, 0, 0).ToColor()); // spanImageFilter = new span_image_filter_rgba_bilinear_clip(sourceAccessor, RGBA_Floats.rgba_pre(0, 0, 0, 0), interpolator); IImageFilterFunction filterFunction = null; filterFunction = new image_filter_blackman(4); var filter = new ImageFilterLookUpTable(); filter.calculate(filterFunction, true); span_image_filter spanGenerator = new span_image_filter_rgba(sourceAccessor, interpolator, filter); DrawImage(spanGenerator, destRectTransform); } break; } #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 intermediate buffer { DrawImageGetDestBounds(source, destX, destY, sourceOriginOffsetX, sourceOriginOffsetY, scaleX, scaleY, angleRadians, out Affine destRectTransform); var 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(); var interpolator = new span_interpolator_linear(sourceRectTransform); var sourceAccessor = new ImageBufferAccessorClip(source, ColorF.rgba_pre(0, 0, 0, 0).ToColor()); 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(spanImageFilter, destRectTransform); DestImage.MarkImageChanged(); } }
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(); } }
public void CopyFrom(IImageByte sourceImage) { CopyFrom(sourceImage, sourceImage.GetBounds(), 0, 0); }
public virtual RectangleInt GetBounds() { return(linkedImage.GetBounds()); }
public override void Render(IImageByte source, double x, double y, double angleRadians, double scaleX, double scaleY) { #if true Affine transform = GetTransform(); if (!transform.is_identity()) { if (scaleX != 1 || scaleY != 1)// || angleDegrees != 0) { throw new NotImplementedException(); } // TODO: <BUG> make this do rotation and scalling transform.transform(ref x, ref y); scaleX *= transform.sx; scaleY *= transform.sy; } #endif #if true // TODO: <BUG> make this do rotation and scalling RectangleInt sourceBounds = source.GetBounds(); sourceBounds.Offset((int)x, (int)y); RectangleInt destBounds = new RectangleInt((int)cachedClipRect.Left, (int)cachedClipRect.Bottom, (int)cachedClipRect.Right, (int)cachedClipRect.Top); if (!RectangleInt.DoIntersect(sourceBounds, destBounds)) { if (scaleX != 1 || scaleY != 1)// || angleDegrees != 0) { //throw new NotImplementedException(); } //return; } #endif ImageBuffer sourceAsImageBuffer = (ImageBuffer)source; ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(sourceAsImageBuffer, false); // Prepare openGL for rendering PushOrthoProjection(); GL.Disable(EnableCap.Lighting); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Translate(x, y, 0); GL.Rotate(MathHelper.RadiansToDegrees(angleRadians), 0, 0, 1); GL.Scale(scaleX, scaleY, 1); RGBA_Bytes color = RGBA_Bytes.White; GL.Color4((byte)color.Red0To255, (byte)color.Green0To255, (byte)color.Blue0To255, (byte)color.Alpha0To255); glPlugin.DrawToGL(); //Restore openGL state PopOrthoProjection(); }