Files
TSpdfUtils/tsPDFUtilsCore/Imagenes.cs
2026-05-27 17:48:50 +02:00

581 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using TSpdf.Kernel.Font;
using TSpdf.IO.Font.Constants;
using static tsPDFUtilsCore.Imagenes;
using static tsPDFUtilsCore.Enums;
namespace tsPDFUtilsCore
{
public class Imagenes
{
public static Bitmap RedimensionaImagen(Bitmap Original, int NuevoAlto, int NuevoAncho, int CoordenadaX, int CoordenadaY)
{
Bitmap newImage = new Bitmap(NuevoAncho, NuevoAlto);
using (Graphics g = Graphics.FromImage(newImage))
{
g.Clear(Color.Transparent);
g.DrawImage(Original, CoordenadaX, CoordenadaY, Original.Width, Original.Height);
}
return newImage;
}
public static Bitmap crearBitMapFirmas(List<DatosTextos> listadoTextos, List<DatosImagenFirma> listadoImagenes, List<DatosFuente> ListadoFuentes, TSpdf.Kernel.Geom.Rectangle medidas)
{
int dpi = 600;
int anchoPixeles = (int)medidas.GetWidth() * dpi / 72;
int altoPixeles = (int)medidas.GetHeight() * dpi / 72;
Bitmap bmp = new Bitmap(anchoPixeles, altoPixeles, PixelFormat.Format32bppArgb);
bmp.SetResolution(dpi, dpi);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.Clear(Color.Transparent);
// Dibujar textos
foreach (var texto in listadoTextos)
{
Font font = null;
if (FontFamily.Families.Any(x => x.Name == texto.NombreFuente))
font = new Font(FontFamily.Families.Where(x => x.Name == texto.NombreFuente).First(), texto.size, texto.estiloTexto, GraphicsUnit.Point);
else if (ListadoFuentes != null && ListadoFuentes.Any(x => x.NombreFuente == texto.NombreFuente))
{
var fuente = ListadoFuentes.Where(x => x.NombreFuente == texto.NombreFuente).First();
int dataLength = fuente.memoryFont.Length;
IntPtr ptrData = Marshal.AllocCoTaskMem(dataLength);
Marshal.Copy(fuente.memoryFont, 0, ptrData, dataLength);
PrivateFontCollection privateFontCollection = new PrivateFontCollection();
privateFontCollection.AddMemoryFont(ptrData, dataLength);
font = new Font(privateFontCollection.Families.FirstOrDefault(), texto.size, texto.estiloTexto, GraphicsUnit.Point);
}
else
throw new Exception("Fuente " + texto.NombreFuente + " no encontrada");
var sizeTexto = g.MeasureString(texto.texto, font);
var coordenadaX = calcularX(texto.distanciaX, texto.distanciaY, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height);
var coordenadaY = calcularY(texto.distanciaY, texto.distanciaX, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height);
PointF rotationPoint = new PointF(texto.distanciaX, texto.distanciaY);
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
StringFormat stringFormat = new StringFormat();
g.TranslateTransform(0, 0);
g.RotateTransform(texto.anguloRotacion);
if (texto.AlineacionTexto != AlineamientoEnum.JUSTIFICADO)
g.DrawString(texto.texto, font, texto.colorTexto, new PointF(coordenadaX, coordenadaY));
else
DrawJustifiedString(ref g, texto.texto, font, texto.colorTexto, new RectangleF(coordenadaX, coordenadaY, altoPixeles, sizeTexto.Height), stringFormat);
g.ResetTransform();
}
foreach (var imagen in listadoImagenes)
{
MemoryStream stream = new MemoryStream();
stream.Write(imagen.Imagen, 0, imagen.Imagen.Length);
System.Drawing.Image myImage = System.Drawing.Image.FromStream(stream);
g.TranslateTransform(0, 0);
g.RotateTransform(imagen.AnguloRotacion);
int coordenadaX = calcularX(imagen.PosicionX, imagen.PosicionY, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height);
int coordenadaY = calcularY(imagen.PosicionY, imagen.PosicionX, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height);
if (altoPixeles > anchoPixeles)
g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, altoPixeles, anchoPixeles));
else
g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, anchoPixeles, altoPixeles));
g.ResetTransform();
}
return bmp;
}
public static byte[] BitMapAByteArray(Bitmap bmp)
{
MemoryStream msSalida = new MemoryStream();
bmp.Save(msSalida, ImageFormat.Png);
byte[] byteArray = msSalida.ToArray();
msSalida.Close();
return byteArray;
}
public static void DrawJustifiedString(ref Graphics g, string txt, Font font, Brush brush, RectangleF destination, StringFormat format)
{
using (StringFormat fmt = (StringFormat)format.Clone())
{
fmt.FormatFlags = fmt.FormatFlags | StringFormatFlags.MeasureTrailingSpaces;
CharacterRange[] cr = { new CharacterRange(0, 1) };
fmt.SetMeasurableCharacterRanges(cr);
fmt.Alignment = StringAlignment.Center;
float txtWidth = g.MeasureString(txt, font, destination.Location, fmt).Width;
float spacing = (destination.Width - txtWidth) / (txt.Length - 1);
RectangleF dest = new RectangleF(destination.X, destination.Y, 0, destination.Height);
foreach (char c in txt.AsEnumerable())
{
// Graphics#MeasureString is too inaccurate for character placement
dest.Width = g.MeasureCharacterRanges(c.ToString(), font, destination, fmt)[0].GetBounds(g).Width;
g.DrawString(c.ToString(), font, brush, dest, fmt);
dest.X += dest.Width + spacing;
}
}
}
private static int calcularX(int coordenadaX, int coordenadaY, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento)
{
int anchoFirma = medidasFirma.Width;
int altoFirma = medidasFirma.Height;
int ejeX = 0;
switch (PosicionEsquina)
{
case EsquinaEnum.SUPERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = coordenadaY;
break;
}
case 180:
{
ejeX = -coordenadaX - anchoElemento;
break;
}
case 270:
{
ejeX = -coordenadaY - anchoElemento;
break;
}
default:
{
ejeX = coordenadaX;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = (altoFirma - (coordenadaY + anchoElemento));
break;
}
case 180:
{
ejeX = -coordenadaX - anchoElemento;
break;
}
case 270:
{
ejeX = coordenadaY - altoFirma;
break;
}
default:
{
ejeX = coordenadaX;
break;
}
}
break;
}
case EsquinaEnum.SUPERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = coordenadaY;
break;
}
case 180:
{
ejeX = -anchoFirma + coordenadaX;
break;
}
case 270:
{
ejeX = -coordenadaY - anchoElemento;
break;
}
default:
{
ejeX = anchoFirma - (anchoElemento + coordenadaX);
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = (altoFirma - (coordenadaY + anchoElemento));
break;
}
case 180:
{
ejeX = -anchoFirma + coordenadaX;
break;
}
case 270:
{
ejeX = coordenadaY - altoFirma;
break;
}
default:
{
ejeX = anchoFirma - (anchoElemento + coordenadaX);
break;
}
}
break;
}
}
return ejeX;
}
private static int calcularY(int coordenadaY, int coordenadaX, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento)
{
int anchoFirma = medidasFirma.Width;
int altoFirma = medidasFirma.Height;
int ejeY = 0;
switch (PosicionEsquina)
{
case EsquinaEnum.SUPERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = -coordenadaX - altoElemento;
break;
}
case 180:
{
ejeY = -coordenadaY - altoElemento;
break;
}
case 270:
{
ejeY = coordenadaX;
break;
}
default:
{
ejeY = coordenadaY;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = -coordenadaX - altoElemento;
break;
}
case 180:
{
ejeY = -altoFirma + coordenadaY;
break;
}
case 270:
{
ejeY = coordenadaX;
break;
}
default:
{
ejeY = altoFirma - (altoElemento + coordenadaY);
break;
}
}
break;
}
case EsquinaEnum.SUPERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = coordenadaX - (anchoFirma);
break;
}
case 180:
{
ejeY = -coordenadaY - altoElemento;
break;
}
case 270:
{
ejeY = anchoFirma - (altoElemento + coordenadaX);
break;
}
default:
{
ejeY = coordenadaY;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = coordenadaX - (anchoFirma);
break;
}
case 180:
{
ejeY = -altoFirma + coordenadaY;
break;
}
case 270:
{
ejeY = anchoFirma - (altoElemento + coordenadaX);
break;
}
default:
{
ejeY = altoFirma - (altoElemento + coordenadaY);
break;
}
}
break;
}
}
return ejeY;
}
private static TSpdf.Kernel.Font.PdfFont devolverTipoFuente(string nombreFuente)
{
TSpdf.Kernel.Font.PdfFont tipoFuente;
switch (nombreFuente)
{
case "COURIER":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER);
break;
}
case "COURIER_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLD);
break;
}
case "COURIER_BOLDOBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLDOBLIQUE);
break;
}
case "COURIER_OBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_OBLIQUE);
break;
}
case "HELVETICA":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
break;
}
case "HELVETICA_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
break;
}
case "HELVETICA_BOLDOBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLDOBLIQUE);
break;
}
case "HELVETICA_OBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_OBLIQUE);
break;
}
case "SYMBOL":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.SYMBOL);
break;
}
case "TIMES_ROMAN":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
break;
}
case "TIMES_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD);
break;
}
case "TIMES_BOLDITALIC":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLDITALIC);
break;
}
case "TIMES_ITALIC":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ITALIC);
break;
}
case "ZAPFDINGBATS":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.ZAPFDINGBATS);
break;
}
default:
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
break;
}
}
return tipoFuente;
}
}
}
public enum EsquinaEnum : int
{
INFERIOR_IZQUIERDA = 0,
INFERIOR_DERECHA = 1,
SUPERIOR_IZQUIERDA = 2,
SUPERIOR_DERECHA = 3
}
public enum AlineamientoEnum : int
{
IZQUIERDA = 0,
DERECHA = 1,
CENTRO = 2,
JUSTIFICADO = 3,
JUSTIFICADO_ALL = 4
}
public enum TipoTextoEnum : int
{
NORMAL = 0,
NUMERO_PAGINA = 1,
NUMERO_PAGINA_TOTAL_PAGINAS = 2,
}
public enum FuenteEnum
{
COURIER,
COURIER_BOLD,
COURIER_BOLDOBLIQUE,
COURIER_OBLIQUE,
HELVETICA,
HELVETICA_BOLD,
HELVETICA_BOLDOBLIQUE,
HELVETICA_OBLIQUE,
SYMBOL,
TIMES_ROMAN,
TIMES_BOLD,
TIMES_BOLDITALIC,
TIMES_ITALIC,
ZAPFDINGBATS
}