Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

232
Vistas
¿Cuál es la mejor forma sin pérdidas de escalar una imagen de código de barras en C#?

Me he encontrado con este problema muchas veces a lo largo de los años y todavía vivo con la esperanza de que haya una manera fácil de hacerlo que se me haya escapado. Trabajo mucho con códigos de barras. Suelen estar formados por puntos o líneas negras sobre un fondo blanco. Los lectores de códigos de barras generalmente funcionan más rápido y con mayor precisión cuando los bordes son nítidos y el tamaño de las líneas o puntos es preciso.

La mayoría de los algoritmos de generación de códigos de barras le darán un código de barras compacto, generalmente con el tamaño de elemento más pequeño de un píxel. Un código QR típico podría caber en una cuadrícula de 21 x 21. Esto sería demasiado pequeño para ver si se imprimiera píxel a píxel en la mayoría de las impresoras y, por lo general, se ampliaría. El resultado de escalarlo depende del método utilizado y, aunque a veces se le da a elegir, a menudo no tiene opciones que hagan que la imagen sea adecuada. Incluso la impresión directa a menudo le dará artefactos grises esperados o formas de difuminado. La forma más consistente que he encontrado es escalar las imágenes antes de que se usen a diario en otros lugares como Microsoft Word, Lightburn y algunos otros que uso y que todavía me dan dolor de cabeza.

A continuación, repasaré lo que he probado y mostraré los resultados. Estoy limitando esto a mapas de bits solo porque usar vectores aquí no es algo que necesito en mi proyecto actual.

Mi mejor resolución actual no es bonita, es lenta y, aunque podría mejorar la velocidad bloqueando los bits en el mapa de bits, espero que alguien tenga una respuesta realmente simple que me había perdido por completo en mi búsqueda esta vez.

Aquí hay una imagen de un código QR simple ampliado en GIMP.

Imagen del código QR

El problema es que, si se amplía, a menudo terminará luciendo así: Imagen después de escalar

A continuación, creé un pequeño programa de prueba para pasar por todos los diferentes modos que conozco y luego generar una matriz de imágenes que he reproducido a continuación. La versión que uso actualmente es el Modo 99, que consiste en inspeccionar cada píxel y dibujar un cuadrado.

Alguien tiene mejores ideas?

 using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace PSWpfCommon.Images { public partial class WPFImageHelper { public class Test { public int smode = 0; public int imode = 0; public int mode = 0; public string title = ""; public Test(int s, int i, int m, string t) { smode = s; imode = i; mode = m; title = t; } } public static Bitmap TestImage() { byte[] img = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x08, 0x06, 0x00, 0x00, 0x00, 0xA9, 0x17, 0xA5, 0x96, 0x00, 0x00, 0x00, 0xCF, 0x49, 0x44, 0x41, 0x54, 0x38, 0xCB, 0x9D, 0x54, 0x5B, 0x0E, 0xC3, 0x30, 0x08, 0xB3, 0xAB, 0xDC, 0xFF, 0xCA, 0xDE, 0xC7, 0xD4, 0x88, 0x7A, 0x3C, 0xD2, 0x21, 0x55, 0xAD, 0x48, 0xA0, 0xC6, 0x80, 0x09, 0x40, 0x28, 0x4C, 0x12, 0x48, 0xEE, 0x6F, 0x00, 0x20, 0xF9, 0xF0, 0x67, 0xB6, 0x62, 0x40, 0xB4, 0x98, 0xAC, 0x4A, 0x50, 0xC5, 0x2D, 0x4F, 0xE2, 0x97, 0x23, 0xB2, 0xEE, 0xE7, 0x31, 0xEE, 0xC2, 0xA1, 0x75, 0x89, 0xD3, 0xF2, 0x27, 0x73, 0x5E, 0x8F, 0x93, 0x56, 0x01, 0x53, 0xA2, 0xEC, 0x7C, 0x39, 0x2F, 0x19, 0xCA, 0x58, 0x7A, 0xA4, 0xA0, 0x8A, 0xA3, 0x0E, 0x6A, 0x7A, 0x5B, 0xFE, 0x45, 0x12, 0xF1, 0xF1, 0x44, 0x59, 0x73, 0xFC, 0x5E, 0x8C, 0x25, 0xF9, 0xED, 0xBE, 0xA4, 0x47, 0x49, 0xDD, 0x18, 0x79, 0xF9, 0x25, 0xA7, 0xD9, 0xA6, 0x74, 0xE3, 0xE3, 0x48, 0x9D, 0xE3, 0x55, 0xA1, 0x98, 0xB8, 0xCC, 0x16, 0xE4, 0xF6, 0x5F, 0xBE, 0xDF, 0x8E, 0x74, 0x42, 0x9F, 0x4D, 0xC0, 0x0F, 0xA7, 0xFE, 0x76, 0x14, 0x5D, 0x65, 0xDB, 0x3F, 0xA9, 0x54, 0xC7, 0x9D, 0x8B, 0xCD, 0x7D, 0x3E, 0xAA, 0xD4, 0x24, 0x77, 0x99, 0x7F, 0x54, 0xA9, 0xAA, 0x69, 0x7E, 0x3F, 0xCE, 0xEA, 0xFA, 0x67, 0x9B, 0x3A, 0x2A, 0x24, 0x9D, 0x49, 0x9F, 0x23, 0x99, 0x64, 0x71, 0x9D, 0xA8, 0x51, 0xC5, 0x6F, 0x36, 0x21, 0x5B, 0xF9, 0x3B, 0x95, 0xAA, 0x1A, 0x52, 0xAD, 0xB1, 0x24, 0x7C, 0x00, 0x22, 0x8E, 0xDE, 0x4C, 0xC4, 0x8F, 0x11, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, }; Bitmap qr; using (var ms = new MemoryStream(img)) { qr = new Bitmap(ms); } int factor = 4; var l = new List<Test>(); for (int i = 0; i <= 7; i++) for (int s = 0; s <= 4; s++) l.Add(new Test(s, i, 0, $"s={s} i={i}")); l.Add(new Test(2, 8, 99, $"Mode 99")); Bitmap fullimage = new Bitmap(((qr.Width * factor) + 20) * 5, ((qr.Height * factor) + 20) * 9); fullimage.SetResolution(72, 72); var font = new Font("Arial", 10); using (var grPhoto = Graphics.FromImage(fullimage)) using (var blackbrush = new SolidBrush(System.Drawing.Color.Black)) using (var whitebrush = new SolidBrush(System.Drawing.Color.White)) { grPhoto.InterpolationMode = InterpolationMode.High; grPhoto.FillRectangle(whitebrush, 0, 0, fullimage.Width, fullimage.Height); foreach (var t in l) { var newqr = GrowImage(qr, factor: 4, mode: t.mode, imode: t.imode, smode: t.smode); grPhoto.DrawImage(newqr, t.smode * ((qr.Width * factor) + 20), t.imode * ((qr.Height * factor) + 20)); grPhoto.DrawString(t.title, font, blackbrush, t.smode * ((qr.Width * factor) + 20), (t.imode + 1) * ((qr.Height * factor) + 20) - 20); } } fullimage.Save(@"c:\temp\newqr.png", ImageFormat.Png); return null; } public static Bitmap GrowImage(Bitmap im, int factor = 4, int mode = 1, int imode = 0, int smode = 0, int border = 2) { bool translate = true; var bmPhoto = new Bitmap(im.Width * factor + 2 * border, im.Height * factor + border * 2, PixelFormat.Format24bppRgb); bmPhoto.SetResolution(72, 72); using (var grPhoto = Graphics.FromImage(bmPhoto)) using (var blackbrush = new SolidBrush(System.Drawing.Color.Black)) using (var whitebrush = new SolidBrush(System.Drawing.Color.White)) { grPhoto.FillRectangle(whitebrush, 0, 0, bmPhoto.Width, bmPhoto.Height); switch (smode) { case 0: grPhoto.SmoothingMode = SmoothingMode.Default; break; case 1: grPhoto.SmoothingMode = SmoothingMode.AntiAlias; break; case 2: grPhoto.SmoothingMode = SmoothingMode.HighQuality; break; case 3: grPhoto.SmoothingMode = SmoothingMode.HighSpeed; break; case 4: grPhoto.SmoothingMode = SmoothingMode.None; break; default: break; } switch (imode) { case 0: grPhoto.InterpolationMode = InterpolationMode.Default; break; case 1: grPhoto.InterpolationMode = InterpolationMode.Bicubic; break; case 2: grPhoto.InterpolationMode = InterpolationMode.Bilinear; break; case 3: grPhoto.InterpolationMode = InterpolationMode.High; break; case 4: grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic; break; case 5: grPhoto.InterpolationMode = InterpolationMode.HighQualityBilinear; break; case 6: grPhoto.InterpolationMode = InterpolationMode.Low; break; case 7: grPhoto.InterpolationMode = InterpolationMode.NearestNeighbor; break; default: break; } switch (mode) { case 99: // These are what worked best for me... grPhoto.SmoothingMode = SmoothingMode.None; grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; for (int x = 0; x < im.Width; x++) for (int y = 0; y < im.Height; y++) { var g = im.GetPixel(x, y); if (gR < 120 && gB < 120) // Just being really lazy here... if the pixel has not much blue and not much red I'll treat it as black { grPhoto.FillRectangle(blackbrush, border + factor * x, border + factor * y, factor, factor); } } translate = false; break; default: break; } if (translate) // If we used mode 99, don't draw the image grPhoto.DrawImage(im, new System.Drawing.Rectangle(border, border, im.Width * factor, im.Height * factor), 0, 0, im.Width, im.Height, System.Drawing.GraphicsUnit.Pixel); } return bmPhoto; } } }

Matriz final de imágenes renderizadas usando el programa de prueba

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Puede usar una biblioteca como ImageTracer.NET para convertir la imagen en una imagen vectorial, luego se escalará tan grande como necesite:

https://github.com/MiYanni/ImageTracer.NET

over 4 years ago · Santiago Trujillo Denunciar

0

En primer lugar, me parece extraño que sus generadores no solo le permitan especificar el tamaño/módulo de celda. Verifique dos veces los manuales.

Para obtener lo que desea de celdas/módulos de un solo píxel, puede usar cualquier función de ampliación de imagen con un tamaño que sea un múltiplo exacto de su imagen original, usando la regla de remuestreo del vecino más cercano y ninguna otra.

Si no puede encontrar tal función, es fácil escribir una que copie una imagen mientras replica cada píxel como un cuadrado NxN (bajo lockbits).

over 4 years ago · Santiago Trujillo Denunciar

0

Así es como cambio el tamaño de un Bitmap de bits de una sola vez con DrawImage y el muestreo del vecino más cercano.

En su caso, prepararía el mapa de bits original con un píxel por punto lógico con respecto a las dimensiones geométricas de su patrón (por ejemplo, a 21 x 21) Luego cambiaría el tamaño de ese mapa de bits a un formato de salida imprimible/visualizable usando el modo de Interpolationmode.NearestNeighbor Muestreo de Interpolationmode.NearestNeighbor usando el código que proporciono a continuación.

Es importante configurar PixelOffsetMode.HighQuality . (A menos que desee ajustar sus coordenadas en -0.5f, -0.5f, lo cual es molesto, así que no se moleste).

 public static Bitmap Resize(this Bitmap oldBitmap, int newWidth, int newHeight) { Bitmap newBitmap = new Bitmap(newWidth, newHeight, oldBitmap.PixelFormat); using (Graphics g = Graphics.FromImage(newBitmap)) { RectangleF dst = new RectangleF(0, 0, newWidth, newHeight); RectangleF src = new RectangleF(0, 0, oldBitmap.Width, oldBitmap.Height); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; g.DrawImage(oldBitmap, dst, src, GraphicsUnit.Pixel); } return newBitmap; }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda