Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="angle"></param>
        /// <returns></returns>
        /// <remarks>
        /// Code and logic from http://www.codeproject.com/KB/custom-controls/RotatedTextImageControl.aspx
        /// </remarks>
        protected RotationSize CalculateRotationSize(int width, int height, int angle)
        {
            int verticalOffset, horizontalOffset;
            int rotatedHeight, rotatedWidth;

            // convert the rotation angle to radians
            double radians = ((double)angle / 180) * Math.PI;

            // work out what the transalation offsets will need to be once the text is rotated
            // to make sure the containning rectangle fits on completely on the image
            if (angle <= 90)
            {
                verticalOffset   = 0;
                horizontalOffset = (int)Math.Abs(Math.Ceiling((double)height * Math.Sin(radians)));
            }
            else if (angle <= 180)
            {
                horizontalOffset = (int)Math.Ceiling(Math.Abs(width * Math.Sin(radians - (Math.PI / 2))) + Math.Abs(height * Math.Cos(radians - (Math.PI / 2))));
                verticalOffset   = (int)Math.Ceiling(Math.Abs(height * Math.Sin(radians - (Math.PI / 2))));
            }
            else if (angle <= 270)
            {
                verticalOffset   = (int)Math.Ceiling(Math.Abs(width * Math.Sin(radians - (Math.PI))) + Math.Abs(height * Math.Cos(radians - (Math.PI))));
                horizontalOffset = (int)Math.Ceiling(Math.Abs(width * Math.Cos(radians - (Math.PI))));
            }
            else
            {
                verticalOffset   = (int)Math.Ceiling(Math.Abs(width * Math.Cos(radians - (Math.PI * 1.5))));
                horizontalOffset = 0;
            }

            // work out the size of the containing rectangle
            rotatedHeight = (int)Math.Ceiling(Math.Abs(height * Math.Cos(radians)) + (Math.Abs(width * Math.Sin(radians))));
            rotatedWidth  = (int)Math.Ceiling(Math.Abs(width * Math.Cos(radians)) + (Math.Abs(height * Math.Sin(radians))));

            RotationSize rs = new RotationSize()
            {
                VerticalOffset   = verticalOffset,
                HorizontalOffset = horizontalOffset,
                RotatedWidth     = rotatedWidth,
                RotatedHeight    = rotatedHeight
            };

            return(rs);
        }
        // TODO examine to add text to a transparent GIF image still works.
        public override Image ProcessImage(Image input, ProjectSetting ps)
        {
            try {
                if (ps.WatermarkCollection.Count < watermarkIndex)
                {
                    return(input);
                }

                WatermarkText wt = ps.WatermarkCollection[this.watermarkIndex] as WatermarkText;

                if (wt == null)
                {
                    return(input);
                }

#if DEBUG
                Debug.WriteLine("Current Thread: "
                                + Thread.CurrentThread.ManagedThreadId + ","
                                + " Image File Name: " + this.ImageFileName + ","
                                + " Watermark Text index: " + watermarkIndex);
#endif

                int   iHOffset          = 0;
                int   iVOffset          = 0;
                int   rotatedTextHeight = 0;
                int   rotatedTextWidth  = 0;
                int   iBmpHeight        = 0;
                int   iBmpWidth         = 0;
                float fHRes             = 0;
                float fVRes             = 0;
                int   textWidth         = 0;
                int   textHeight        = 0;
                int   xAfterOffset      = 0;
                int   yAfterOffset      = 0;

                string textToDraw = wt.Text;
                List <ExifContainerItem> tagsFound = this.FindExifTags(textToDraw);

                if (tagsFound != null && tagsFound.Count > 0 && !string.IsNullOrEmpty(this.ImageFileName))
                {
                    // at least one Exif tag is found
                    textToDraw = ConvertExifTagsToText(textToDraw, tagsFound);
                }

                textToDraw = this.ConvertControlTagsToText(textToDraw);

                // create a bitmap we can use to work out the size of the text,
                // we will then create a new bitmap that is the right size.
                // we also use this to record the default resolution
                Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
                fHRes = bmp.HorizontalResolution;
                fVRes = bmp.VerticalResolution;
                Graphics     g      = Graphics.FromImage(bmp);
                StringFormat format = new StringFormat();
                format.Alignment = wt.WatermarkTextAlignment;
                SizeF sf = g.MeasureString(textToDraw, wt.WatermarkTextFont,
                                           Int32.MaxValue, format);
                g.Dispose();
                bmp.Dispose();

                // get the width and height of the text
                textWidth  = Math.Max(2, (int)Math.Ceiling(sf.Width));
                textHeight = Math.Max(2, (int)Math.Ceiling(sf.Height));

                RotationSize rs = CalculateRotationSize(textWidth, textHeight, wt.WatermarkRotateAngle);
                iHOffset          = rs.HorizontalOffset;
                iVOffset          = rs.VerticalOffset;
                rotatedTextWidth  = rs.RotatedWidth;
                rotatedTextHeight = rs.RotatedHeight;

                bmp        = new Bitmap(input);
                iBmpWidth  = bmp.Width;
                iBmpHeight = bmp.Height;
                g          = Graphics.FromImage(bmp);

                // determine the offset needed to position the text in the right place
                // in the background if it is not the same size as we calculate was needed for the text
                // adding in the padding where necessary and
                // remembering to adjust for differences in padding between left/right top/bottom etc.
                switch (wt.WatermarkPosition)
                {
                case ContentAlignment.TopLeft:
                case ContentAlignment.TopCenter:
                case ContentAlignment.TopRight:
                    //yAfterOffset = definition.TextPadding.Top;
                    yAfterOffset = wt.Padding;
                    break;

                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleRight:
                    //yAfterOffset = (bmp.Height - rotatedHeight) / 2 + definition.TextPadding.Top - definition.TextPadding.Bottom;
                    yAfterOffset = (bmp.Height - rotatedTextHeight) / 2 + wt.Padding - wt.Padding;
                    break;

                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomRight:
                    //yAfterOffset = (bmp.Height - rotatedHeight) - definition.TextPadding.Bottom;
                    yAfterOffset = (bmp.Height - rotatedTextHeight) - wt.Padding;
                    break;
                }
                switch (wt.WatermarkPosition)
                {
                case ContentAlignment.TopLeft:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.BottomLeft:
                    //xAfterOffset = definition.TextPadding.Left;
                    xAfterOffset = wt.Padding;
                    break;

                case ContentAlignment.TopCenter:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.BottomCenter:
                    //xAfterOffset = (bmp.Width - rotatedWidth) / 2 + definition.TextPadding.Left - definition.TextPadding.Right;
                    xAfterOffset = (bmp.Width - rotatedTextWidth) / 2 + wt.Padding - wt.Padding;
                    break;

                case ContentAlignment.TopRight:
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                    //xAfterOffset = (bmp.Width - rotatedWidth) - definition.TextPadding.Right;
                    xAfterOffset = (bmp.Width - rotatedTextWidth) - wt.Padding;
                    break;
                }

                // create a new transformation matrix to do the rotation and corresponding translation
                Matrix matrix = new Matrix();
                // translation to position the text as required by HAlignment and VAlignment
                matrix.Translate(xAfterOffset, yAfterOffset);
                // translation to bring the rotation back to view
                matrix.Translate(iHOffset, iVOffset);
                // transformation to rotate the text
                matrix.Rotate(wt.WatermarkRotateAngle);
                if (wt.WatermarkTextAlignment == StringAlignment.Center)
                {
                    // transformation to cope with non left aligned text
                    matrix.Translate(textWidth / 2, 0);
                }
                else if (wt.WatermarkTextAlignment == StringAlignment.Far)
                {
                    matrix.Translate(textWidth, 0);
                }

                // apply the transformation to the graphics object and write out the text
                g.Transform         = matrix;
                g.SmoothingMode     = SmoothingMode.HighQuality;
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
                // draw a shadow with semi transparent black
                g.DrawString(textToDraw,
                             wt.WatermarkTextFont,
                             new SolidBrush(Color.FromArgb(153, 0, 0, 0)), 1, 1, format);
                // draw the sctual text
                g.DrawString(textToDraw,
                             wt.WatermarkTextFont,
                             new SolidBrush(wt.WatermarkTextColor), 0, 0, format);
                g.Transform = matrix;
                g.Dispose();

                return(bmp);
            } catch (Exception ex) {
                Trace.TraceError(ex.ToString());
                return(input);
            }
        }