Pregunta

Tengo un formulario que va a permitir a un usuario para crear custom "sellos" para colocar en un PDF.El formulario se muestra con una imagen de la primera página del pdf y quiero que el usuario básicamente, haga clic en la pantalla donde desea que su sello y ser capaz de ver lo que va a ver.No te preocupes acerca de cualquiera de los PDF de cosas, tengo que manejan.

Para hacer las cosas elegantes, tengo dos copias de la imagen, el normal y uno con brillo reducido.Puedo mostrar la baja el brillo de la imagen y a medida que el usuario mueve el ratón por encima, un trozo de la imagen original se revela o de relieve.Yo, a continuación, mostrar que en esa zona el texto que el usuario se va a poner en el PDF.

Yo permitir que el usuario utilice la rueda del ratón para desplazarse y cambiar el ángulo del texto están en la colocación (de -45 grados a +45 grados).

Aquí está mi problema:No puedo calcular la adecuada rectángulos/coordenadas.A veces todo se ve muy bien, otras veces (como tamaños de letra de cambio) que no encajan del todo.

¿Cómo puedo calcular las coordenadas x e y para:la colocación del texto girado Y un rectángulo delimitador relleno de texto en su anchura y altura con 10px

El siguiente código funciona, hasta que empiezo a subir el tamaño de la fuente, entonces todo lo que sale de sesgo.

Las dos primeras imágenes muestran texto + rectángulo delimitador en fuentes más pequeñas.Se ve bien:

enter image description here enter image description here

La siguiente imagen muestra que a medida que el tamaño del texto se hace más grande, mi píxeles se mueve todo y se pone cortados.Incluso en un texto más grande, el ancho/alturas final fuera así.

enter image description here enter image description here

Lo siento el ejemplo de las imágenes no muestran mucho detalle.Tengo datos reales que no puedo compartir.

        Private Sub PanelMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) '// handles the mouse move (handler added elsehwere)

        With CType(sender, PictureBox)

            .Image.Dispose() '// get rid of old image

            Dim b As Bitmap = _curGray.Clone '// the low brightness image as the base image

            '// stamp font and text values are initiated from another form
            Using g As Graphics = Graphics.FromImage(b),
                f As New Font(DefaultFont.FontFamily, CSng(_stmpTools.StampTextSize), If(_stmpTools.StampBold, FontStyle.Bold, FontStyle.Regular))

                Const borderWidth As Integer = 10
                Const borderPadding As Integer = 5

                '// measure the string
                Dim szx As SizeF = g.MeasureString(_stmpTools.StampText, f, Integer.MaxValue, StringFormat.GenericDefault)
                Dim strLength As Single = szx.Width
                Dim strHeight As Single = szx.Height

                Dim x As Single = e.X - borderWidth - borderPadding,
                    y As Single = e.Y

                Dim w As Double, h As Double

                If Math.Abs(_angle) > Double.Epsilon Then
                    h = CDbl(strLength) * Math.Sin(CDbl(Math.Abs(_angle)) * Math.PI / 180.0F)
                    w = Math.Sqrt(CDbl(strLength) * CDbl(strLength) - h * h)
                Else
                    '// its zero. so use calculated values
                    h = strHeight
                    w = strLength
                End If

                '// add space for the 10px border plus 5px of padding
                Dim r As New Rectangle(0, 0, w, h)
                r.Inflate(borderWidth + borderPadding, borderWidth + borderPadding)

                h = r.Height
                w = r.Width

                '// keep box from moving off the left
                If x < .Location.X Then
                    x = .Location.X
                End If

                '// keep box from moving off the right
                If x > .Location.X + .Width - w Then
                    x = .Location.X + .Width - w
                End If

                '// I don't know, but these values work for most smaller fonts, but
                '// it has got to be a fluke
                If _angle > 0 Then
                    y = y - h + borderWidth + borderWidth
                Else
                    y = y - borderWidth
                End If

                '// can't go off the top
                If y < .Location.Y Then
                    y = .Location.Y
                End If

                '// can't go off the bottom
                If y > .Location.Y + .Height - h Then
                    y = .Location.Y + .Height - h
                End If

                Dim rect As New Rectangle(x, y, w, h)
                g.DrawImage(_curImg, rect, rect, GraphicsUnit.Pixel)

                Using br As New SolidBrush(_stmpTools.StampTextColor)
                    RotateString(_stmpTools.StampText, _angle, e.X, e.Y, f, g, br)
                End Using

                '//draw bounding rectangle
                Using p As New Pen(Color.Black, borderWidth)
                    g.DrawRectangle(p, rect)
                End Using

            End Using
            '// set the picture box to show the new image
            .Image = b
        End With

    End Sub

    Private Sub RotateString(ByVal Text As String, ByVal angle As Integer, _
                      ByVal x As Integer, ByVal y As Integer, myfont As Font, mydrawing As Graphics, myColor As Brush)
        Dim myMatrix As New Matrix
        myMatrix.RotateAt(angle * -1, New Point(x, y)) 'Rotate drawing 
        mydrawing.Transform = myMatrix
        mydrawing.DrawString(Text, myFont, myColor, x, y) 'Draw the text string 
        myMatrix.RotateAt(angle, New Point(x, y)) 'Rotate back 
        mydrawing.Transform = myMatrix
    End Sub

Yo no soy el mayor cuando se trata de dibujo.Así que cualquier ayuda sería genial

El uso de la solución por debajo de @LarsTech.He sustituido la g.FillRectangle con:

g.DrawImage(_curImg, r, r, GraphicsUnit.Pixel)

_curImg es una copia de la imagen original con el brillo ajustado.Cuando me cambie el código de abajo me terminan con:

enter image description here Nota las líneas dobles.Giran con el sello, incluso a pesar de que están actuando como una imagen de fondo y se debe rotar

Por sugerencia, he cambiado el DrawStamp de @LarsTech a la siguiente:

        Private Sub DrawStamp(g As Graphics, text As String,
                  f As Font, center As Point, angle As Integer, backImg As Image)

        Dim s As Size = g.MeasureString(text, f).ToSize
        Dim r As New Rectangle(center.X - (s.Width / 2) - 16,
                                 center.Y - (s.Height / 2) - 16,
                                 s.Width + 32,
                                 s.Height + 32)

        g.DrawImage(backImg, r, r, GraphicsUnit.Pixel)

        Using m As New Matrix
            m.RotateAt(angle, center)
            g.Transform = m

            Using p As New Pen(Color.Black, 6)
                g.DrawRectangle(p, r)
            End Using
            Using sf As New StringFormat
                sf.LineAlignment = StringAlignment.Center
                sf.Alignment = StringAlignment.Center
                g.DrawString(text, f, Brushes.Black, r, sf)
            End Using
            g.ResetTransform()
        End Using
    End Sub

Sin embargo, ahora estoy a la izquierda con enter image description here

Aviso que se trazó el fondo, entonces, ¿la rotación y sacó el sello.CASI funciona.En este ejemplo, las líneas rectas, muestran la intención de comportamiento...sin embargo, yo estoy buscando para llenar todo el sello con el fondo.Que extra blanco en los lados habría sido lo que fue girada en el sello del fondo.Estoy confundido porque el 'gris' porciones entonces yo les sospechoso recorte partes de la imagen, pero no son (si se me mueve a través de otras áreas de las que yo por desgracia no se puede publicar aquí) aviso de sesgar excepto por el hecho de que los lados del rectángulo de la pintura como tal.

Otra Edición esperemos que con algo más de información

Aquí es de esperar que una mejor explicación de lo que estoy tratando de hacer.Yo uso un tercero visor de PDF y necesito para permitir al usuario agregar una imagen al PDF.El espectador no permitir que me refiera a los eventos de clic en él, así que con el fin de aprovechar usuario de clics de ratón, hago lo siguiente:

  1. Tomar un screen grab de forma
  2. Ocultar el Visor de PDF
  3. Agregar un control PictureBox a mi forma, en sustitución de la zona donde el visor de PDF se
  4. Con la pantalla de mi agarre, puedo hacer una copia de la imagen con el brillo reducido
  5. Visualización de la escala de grises copia de la imagen y dibujar directamente sobre la imagen con el ratón sobre los acontecimientos en el picturebox
  6. Me dibuja un sello en el picturebox, pero quiero que el fondo de la original (no ajustar el brillo de la imagen).Sin embargo, ya que la zona podría ser transformado mediante una rotación, no puedo agarrar la imagen de fondo.Si no hay ningún ángulo, el rectángulo de origen de los partidos.Sin embargo, si su girado, no puedo agarrar el mismo rectángulo girado fuera de la imagen de origen.

Evento De Clic De Botón:

  Dim bds As Rectangle = AxDPVActiveX1.Bounds
  Dim pt As Point = AxDPVActiveX1.PointToScreen(bds.Location)

    Using bit As Bitmap = New Bitmap(bds.Width, bds.Height)
        Using g As Graphics = Graphics.FromImage(bit)
            g.CopyFromScreen(New Point(pt.X - AxDPVActiveX1.Location.X, pt.Y - AxDPVActiveX1.Location.Y), Point.Empty, bds.Size)
        End Using

        _angle = 0

        _curImg = bit.Clone
        _curGray = Utils.CopyImageAndAdjustBrightness(bit, -100)

 End Using

   Dim p As New PictureBox

        Utils.SetControlDoubleBuffered(p)

        p.Dock = DockStyle.Fill
        p.BackColor = Color.Transparent
        AxDPVActiveX1.Visible = False
        p.Image = _curImg.Clone

        AddHandler p.MouseClick, AddressOf PanelDownMouse
        AddHandler p.MouseMove, AddressOf PanelMouseMove
        AddHandler p.MouseWheel, Sub(s As Object, ee As MouseEventArgs)
                                     _angle = Math.Max(Math.Min(_angle + (ee.Delta / 30), 45), -45)
                                     PanelMouseMove(s, ee)
                                 End Sub
        AddHandler p.MouseEnter, Sub(s As Object, ee As EventArgs)
                                     CType(s, Control).Focus()
                                 End Sub


        AxDPVActiveX1.Parent.Controls.Add(p)

Después de que el código que termino con dos imágenes._curgray es una imagen con ajustar el brillo, y _curImg es original de mi screen grab.

_curGray: enter image description here _curImg: enter image description here

Un mouseMove mover evento se aplica a mi nuevo cuadro de imagen.Aquí es donde todo el código de antes en la pregunta entra en juego.

Utilizando el código anterior, mi evento mouseMove se mantiene la creación de un nuevo imageto mostrar en mi cuadro de imagen.Si no hay rotación de los involucrados, me da bastante lo que estoy buscando.Observe en la imagen de abajo cómo el fondo de la estampilla es más brillante que todo.La porción sobre el cuadrado azul es un poco más ligero.Yo estoy usando esta una manera de atraer a los espectadores ojo a esta área...es importante para lo que yo estoy haciendo.

enter image description here

Sin embargo, al aplicar una rotación a ella, no me parece copia de la imagen original.Mira la siguiente imagen, la backgroundisn no girar con él.Tengo que agarrar un rectángulo girado a partir de la imagen ORIGINAL.

enter image description here

http://msdn.microsoft.com/en-us/library/ms142040(v=vs 110).aspx Graphics.DrawImage() acepta

Public Sub DrawImage ( _
    image As Image, _
    destRect As Rectangle, _
    srcRect As Rectangle, _
    srcUnit As GraphicsUnit _
)

donde puedo especificar copia de este rectángulo de origen de mi imagen de origen (en este caso _curImg) y el lugar en mi nuevo dibujo.No me permite aplicar una transformación a la del rectángulo de origen.Básicamente quiero copiar de mi imagen de la fuente de un área equivalente al rectángulo girado (basado en la transformación de @larstech )

No sé cómo expresar este concepto más claro.Si aún así no tiene sentido solo voy a aceptar LarsTech respuesta como la mejor respuesta de rechazo y de mi idea.

¿Fue útil?

Solución

Me gustaría tratar de dibujar el rectángulo y el texto:

Private Sub DrawStamp(g As Graphics, text As String,
                      f As Font, center As Point, angle As Integer)
  Using m As New Matrix
    g.SmoothingMode = SmoothingMode.AntiAlias
    g.TextRenderingHint = TextRenderingHint.AntiAlias
    m.RotateAt(angle, center)
    g.Transform = m
    Dim s As Size = g.MeasureString(text, f).ToSize
    Dim r As New Rectangle(center.X - (s.Width / 2) - 16,
                           center.Y - (s.Height / 2) - 16,
                           s.Width + 32,
                           s.Height + 32)
    g.FillRectangle(Brushes.White, r)
    Using p As New Pen(Color.Black, 6)
      g.DrawRectangle(p, r)
    End Using
    Using sf As New StringFormat
      sf.LineAlignment = StringAlignment.Center
      sf.Alignment = StringAlignment.Center
      g.DrawString(text, f, Brushes.Black, r, sf)
    End Using
    g.ResetTransform()
  End Using
End Sub

La pintura de ejemplo:

Protected Overrides Sub OnPaint(e As PaintEventArgs)
  MyBase.OnPaint(e)
  e.Graphics.Clear(Color.LightGray)
  Using f As New Font("Calibri", 16, FontStyle.Bold)
    DrawStamp(e.Graphics,
              "Reviewed By Doctor Papa",
              f,
              New Point(Me.ClientSize.Width / 2, Me.ClientSize.Height / 2),
              -25)
  End Using
End Sub

Resultado:

enter image description here

Aquí he actualizado el código para "clip" el rectángulo girado de modo que puedo copiar la misma zona de la imagen original antes de aplicar el texto y el borde:

Private Sub DrawStamp(g As Graphics, text As String,
                      f As Font, center As Point, angle As Integer)

  Dim s As Size = g.MeasureString(text, f).ToSize
  Dim r As New Rectangle(center.X - (s.Width / 2) - 16,
                         center.Y - (s.Height / 2) - 16,
                         s.Width + 32,
                         s.Height + 32)

  Using bmp As New Bitmap(_curImg.Width, _curImg.Height)
    Using gx As Graphics = Graphics.FromImage(bmp)
      Using m As New Matrix
        m.RotateAt(angle, center)
        gx.Transform = m
        gx.SetClip(r)
        gx.ResetTransform()
      End Using
      gx.DrawImage(_curImg, Point.Empty)
    End Using
    g.DrawImage(bmp, Point.Empty)
  End Using

  Using m As New Matrix
    g.SmoothingMode = SmoothingMode.AntiAlias
    g.TextRenderingHint = TextRenderingHint.AntiAlias
    m.RotateAt(angle, center)
    g.Transform = m      
    Using p As New Pen(Color.Black, 6)
      g.DrawRectangle(p, r)
    End Using
    Using sf As New StringFormat
      sf.LineAlignment = StringAlignment.Center
      sf.Alignment = StringAlignment.Center
      g.DrawString(text, f, Brushes.Black, r, sf)
    End Using
    g.ResetTransform()
  End Using
End Sub

Nuevo Resultado:

enter image description here

Otros consejos

Es sólo la trigonometría:

enter image description here

Usted sabe c porque usted sabe cómo se amplia el texto original es, y usted sabe h porque usted sabe que la altura de su texto.Usted también necesita saber alfa, es el ángulo girado el texto.

Ahora lo que necesita para trabajar el poder de las matemáticas:Primero los pequeños rectángulos en la final.En la parte inferior izquierda se puede ver, que el ángulo derecho de la x es en realidad de 180°-90°-alfa, o 90°-alfa.Así que alfa es también en el sitio opuesto.Así que usted puede encontrar x:

x = h * sin(alpha)

Lo mismo va para y, pero es pecado(90°-alfa), o cos(alfa)

y = h * cos(alpha)

Lo siguiente que necesita para encontrar a y b para completar el rectángulo.El gran triángulo da

a = w * cos(alpha)

y

b = w * sin(alpha)

Luego, simplemente añade las piezas:

NewWidth = a + x
NewHeight = b + y

De esta manera se obtiene el tamaño del cuadro delimitador.Como para las coordenadas, depende de que punto es realmente define al imprimir el texto girado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top