Estoy tratando de generar con Crystal Reports (el que viene en VS.Net 2003) un carnet de cliente. La foto del cliente tiene que ir en un marco que mide como máximo 1290 twips de ancho por 1600 twips de alto (20 twips = 1/72'' = 1 punto <> 1 pixel). Las imágenes están digitalizadas generalmente a 300 ppp (dpi) pero son cada una de un tamaño diferente. La idea es encuadrar esta imagen, comprobando primero cuál de las dimensiones es la que hay que marcar como, digamos, variable independiente. Para ello, dividiendo al alto entre el ancho del marco de Crystal Reports es obtiene una proporción. Haciendo lo mismo con la imagen (aunque tengamos las medidas en píxeles) sacamos otra proporción. Comparando ambas proporciones podremos saber si tenemos que fijar la anchura o la altura de la imagen.
El problema me surge a la hora de, una vez definida cuál es la dimensión a fijar, redimensionar la imagen en píxeles al marco en twips. Os dejo el código que he modificado por activa y por pasiva sin obtener buenos resultados. Entiendo que habría que tener en cuenta la resolución
de la imagen al hacer el paso de píxeles a twips.
Código:
Llevo varias días liado con esto y no lo consigo a lo que hay que añadir que al usar una impresora de tarjetas debría salir el reporte con este tamaño y el de un A4. Pero vamos, esto es menos problema.Private Sub imgbCarne_Click(ByVal sender As System.Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles imgbCarne.Click Try Dim rpt As New CrystalDecisions.CrystalReports.Engine.ReportDocument Dim dt As New DataTable("datos") Dim dr As DataRow Dim ds As New DataSet Try rpt.Load(Server.MapPath("../Reportes/CarneCliente.rpt"), CrystalDecisions.[Shared].OpenReportMethod.OpenReportByTempCopy) Catch ex As Exception mens("No se ha podido cargar el reporte<br>" & ex.Message) Exit Sub End Try Dim img As Drawing.Image = Image.FromFile("\\192.168.0.31\FotosClientes\" & Me.lblNumCliente.Text.Trim & ".JPG") Dim redImg As Drawing.Image Dim byteImg() As Byte Dim maxAncho As Single = 1290 Dim maxAlto As Single = 1600 Dim maxProp As Double = maxAlto / maxAncho Dim ancho As Double = img.Width Dim alto As Double = img.Width Dim prop As Double = alto / ancho If prop / maxProp < 1 Then 'Limitante la altura alto = CInt(maxAlto) 'alto = maxAlto * img.VerticalResolution / 1440 ancho = 0 'tam = New Drawing.Size((maxAlto * img.VerticalResolution / 1440) / maxProp, maxAlto * img.VerticalResolution / 1440) 'nImg = New Bitmap(img, tam) Else 'Limitante la anchura ancho = CInt(maxAncho) 'ancho = maxAncho * img.HorizontalResolution / 1440 alto = 0 'tam = New Drawing.Size(maxAncho * img.HorizontalResolution / 1440, maxProp * maxAncho * img.VerticalResolution / 1440) 'nImg = New Bitmap(img, tam) End If Try redImg = RedimensionarImagen(img, ancho, alto) 'redImg.Save("\\192.168.0.31\FotosClientes\BMP___" & Me.lblNumCliente.Text.Trim & ".JPG", Drawing.Imaging.ImageFormat.Jpeg) 'Exit Sub byteImg = ImageToByte(redImg) Catch ex As Exception mens("Error al redimensionar la imagen original.<br>" & ex.Message) Exit Sub End Try dt.Columns.Add(New DataColumn("NumCliente", GetType(Short))) dt.Columns.Add(New DataColumn("Nombre", GetType(String))) dt.Columns.Add(New DataColumn("Apellidos", GetType(String))) dt.Columns.Add(New DataColumn("DNI", GetType(String))) dt.Columns.Add(New DataColumn("Fecha", GetType(String))) dt.Columns.Add(New DataColumn("Imagen", GetType(Byte()))) dr = dt.NewRow() dr("NumCliente") = Me.lblNumCliente.Text.ToUpper dr("Nombre") = Me.txtNombre.Text.Trim.ToUpper dr("Apellidos") = Me.txtApellido1.Text.Trim.ToUpper & " " & Me.txtApellido2.Text.Trim.ToUpper dr("DNI") = Me.txtNIF.Text.Trim.ToUpper dr("Fecha") = Me.txtFechaAlta.Text dr("Imagen") = byteImg dt.Rows.Add(dr) ds.Tables.Add(dt) rpt.SetDataSource(ds) 'rpt.PrintOptions.PrinterName = "\\BRAVENAP\Smart Driver" 'rpt.PrintOptions.PaperSize = CrystalDecisions.[Shared].PaperSize.DefaultPaperSize Try rpt.ReportDefinition.Sections("Section3").ReportObjects("Foto").Width = redImg.Width rpt.ReportDefinition.Sections("Section3").ReportObjects("Foto").Height = redImg.Height Catch ex As Exception mens("Error al dimensionar la imagen en el reporte." & ex.message) Exit Sub End Try rpt.Refresh() Dim rptStream As New IO.MemoryStream Try rptStream = rpt.ExportToStream(CrystalDecisions.[Shared].ExportFormatType.WordForWindows) Catch ex As Exception mens("No se ha podido exportar el reporte<br>" & ex.Message) Exit Sub Catch ex As CrystalDecisions.CrystalReports.Engine.EngineException mens("EngineException: No se ha podido exportar el reporte<br>" & ex.Message) Exit Sub Catch ex As CrystalDecisions.CrystalReports.Engine.ExportException mens("ExportException: No se ha podido exportar el reporte<br>" & ex.Message) Exit Sub End Try Response.Clear() Response.Buffer = True Response.ContentType = "application/msword" Response.AddHeader("Content-Disposition", "attachment;filename=" & "CarneCliente" & Me.txtNumCliente.Text & ".doc") Response.BinaryWrite(rptStream.ToArray()) Response.End() Catch ex As Exception mens("Error genérico: " & ex.Message) End Try End Sub Private Function RedimensionarImagen(ByVal imagen As Drawing.Image, ByVal ancho As Integer, ByVal alto As Integer) As Drawing.Image ' throw an exception if both arguments are not positive integers If ancho <= 0 AndAlso alto <= 0 Then Throw New Exception("Ancho y/o alto deben tener argumentos positivos") End If Dim img As Drawing.Image = imagen ' Mantiene la proporción If ancho <= 0 OrElse alto <= 0 Then If ancho <= 0 Then ancho = img.Width / (img.Height / alto) ElseIf alto <= 0 Then alto = img.Height / (img.Width / ancho) End If End If ' Nuevo mapa de bits con el tamaño especificado Dim bmp As New System.Drawing.Bitmap(ancho, alto) ' Lienzo para rellenar el mapa de bits Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage( _ DirectCast(bmp, System.Drawing.Image)) ' Copia la imagen original sobre el lienzo g.DrawImage(img, 0, 0, ancho, alto) ' Cierra la imagen original img.Dispose() ' Guarda la nueva imagen con el formato correcto Dim stream As New IO.MemoryStream Try bmp.Save(stream, Drawing.Imaging.ImageFormat.Jpeg) Catch ex As Exception Throw New Exception("Error al convertir la nueva imagen.<br>" & ex.Message) End Try bmp.Dispose() Return Drawing.Image.FromStream(stream) End Function
Gracias y un saludo.