def _prepara_impresion(self, seleccion): """ Método que se encarga de imprimir efectivamente la boleta debug voto""" self.seleccion = seleccion if USAR_BUFFER_IMPRESION: if not USA_ARMVE: sesion.logger.debug("iniciando buffer de impresion") start = datetime.now() # dibujo boleta imagen = seleccion.a_imagen() # genero imagen PIL para impresión: im = imagen.output() # imprimo: dpi = get_dpi_boletas() sesion.impresora.imprimir_image(im, dpi=dpi, transpose=True, only_buffer=True) end = datetime.now() txt_t = "tiempo total de buffer de impresion %s" % \ str(end - start) sesion.logger.debug(txt_t) else: self._imprimir_serializado(self.seleccion, transpose=True, only_buffer=True)
def imprimir_image(self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False): raise NotImplementedError
def imprimir_image( self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False ): """Decide el metodo de impresion segun las settings y en caso de que sea necesario prepara la imagen. """ if USAR_CYTHON: if transpose: image = image.transpose(Image.ROTATE_270) self.imprimir_image_fast(image, only_buffer=only_buffer) else: self.imprimir_image_slow(image, dpi, transpose, compress, only_buffer)
def imprimir_image(self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False): image_file = NamedTemporaryFile(prefix="imagen_impresion", dir="/tmp", bufsize=0, delete=False) data = image.tostring() image_file.write(data) image_file.flush() filepath = image_file.name mode = image.mode size = image.size dbus_method = self.printer.get_dbus_method('imprimir_image') return dbus_method(filepath, mode, size, dpi, transpose, compress, only_buffer)
def imprimir_image(self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False): """Decide el metodo de impresion segun las settings y en caso de que sea necesario prepara la imagen. """ if USAR_CYTHON: if transpose: image = image.transpose(Image.ROTATE_270) self.imprimir_image_fast(image, only_buffer=only_buffer) else: self.imprimir_image_slow(image, dpi, transpose, compress, only_buffer)
def run(args): printer = obtener_impresora() if args.serialized is None or not args.serialized: logger.debug("Corriendo proceso de impresion o cache de impresion") logger.debug(args) image_file = open(args.filepath) data = image_file.read() size = [int(num) for num in args.size.split(",")] dpi = tuple([int(num) for num in args.dpi.split(",")]) image = Image.fromstring(args.mode, size, data) printer.imprimir_image(image, dpi, args.transpose, args.compress, args.only_buffer) else: extra_data = loads(b64decode(args.extra_data)) if args.tipo_tag == "Seleccion": boleta = Seleccion.desde_string(args.tag) image = boleta.a_imagen() dpi = get_dpi_boletas() elif args.tipo_tag == "Apertura": boleta = Apertura.desde_tag(b64decode(args.tag)) autoridades = boleta.autoridades image = boleta.a_imagen() dpi = DPI_VOTO_ALTA if IMPRESION_HD_APERTURA else DPI_VOTO_BAJA elif args.tipo_tag == "Recuento": boleta = Recuento.desde_tag(b64decode(args.tag)) autoridades = extra_data.get('autoridades') if autoridades is not None: for autoridad in autoridades: boleta.autoridades.append(Autoridad.desde_dict(autoridad)) boleta.hora = extra_data['hora'] image = boleta.a_imagen(extra_data['tipo_acta']) dpi = DPI_VOTO_ALTA if IMPRESION_HD_CIERRE else DPI_VOTO_BAJA elif args.tipo_tag == "Prueba": dpi = DPI_VOTO_ALTA image = ImagenPrueba(hd=True).render_image() printer.imprimir_image(image, dpi, args.transpose, args.compress, args.only_buffer)
def imprimir_image_slow(self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False): """Imprime la imagen en velocidad lenta.""" self._isprinting = True #borro la data self.write('\x18') # des-activo modo comprimido en baja calidad (para pruebas) if compress and dpi != DPI_VOTO_ALTA: compress = False t0 = time.time() # tiempo inicial im = image if im.mode != "1": logger.debug("Convirtiendo a B/N...") im = im.convert("1") # convertir B/W (1 bit) t1 = time.time() # tiempo apertura/conversion if transpose: logger.debug("Rotando 270º (apaisado)...") im = im.transpose(Image.ROTATE_270) # landscape if dpi == (67, 67): logger.debug("Ajustando aspecto a 100x67 dpi (redimensionando)...") logger.debug("Tamaño anterior: %s" % im.size) im = im.resize( (im.size[0] * 100 / 67, im.size[1])) # aspecto ratio dpi = DPI_VOTO_BAJA logger.debug("Tamaño actual: %s" % im.size) # bit verticales (manual pp. 28 "Select image mode") if dpi == DPI_VOTO_BAJA: v = 8 # (baja calidad) elif dpi == DPI_VOTO_ALTA: v = 24 # (alta calidad) else: # 67x200 y 200x100 DPI se complica armar el bitmap raise RuntimeError( "Calidad de impresión requerida no soportada: %s" % str(dpi)) buf = [] t2 = time.time() logger.debug("Iniciando buffering: %s" % t2) # recorro pixels, armo buffer de bits para enviar a la impresora # obtengo los datos internos de PIL para optimizar (en vez de getpixel) data = list(im.getdata()) xmax = im.size[0] if not compress: # buferring sin compresión: recorre de arriba a abajo, izq a der # en baja: transpone 8 pixeles verticales (1 byte) # en alta: transpone 24 pixeles verticales (3 bytes) for y in range(0, im.size[1], v): d = [] for x in range(im.size[0]): for k in range(0, v / 8): b = 0 for j in range(0, 8): try: b = b | ((0 if data[ (x + (y + j + 8 * k) * xmax)] else 1) << (7 - j)) except IndexError: # ultimo boundary != 8bits! (completar con blancos) #logger.debug("IndexError: alto debe ser múltiplo de 8 bits") pass d.append(chr(b)) buf.append(d) else: # buffering para compresion: recorre de arriba a abjo, izq a der # en alta: empaqueta de a 8 pixeles horizontales (1 byte) for y in range(0, im.size[1]): d = "" for x in range(0, im.size[0], 8): b = 0 i0 = x + y * xmax # optimización para bajar 50% el tiempo de buffering: try: if not data[i0 + 0]: b += 128 if not data[i0 + 1]: b += 64 if not data[i0 + 2]: b += 32 if not data[i0 + 3]: b += 16 if not data[i0 + 4]: b += 8 if not data[i0 + 5]: b += 4 if not data[i0 + 6]: b += 2 if not data[i0 + 7]: b += 1 d += chr(b) except IndexError: pass buf.append(d) t3 = time.time() logger.debug("Inicio impresion: %s" % t3) if not only_buffer: self.write("\x1D\xF9\x04") # return 4 lines if compress: # sets the page lenght in dots self.write("\x1b\xa5\x6c%s\x50" % 100) #im.size[1]) # Enable data compression ("Graphics Advanced Mode Commands" p19) self.write("\x1b\xa5\x62\x31\x4d") # Set absolute positioning on the x axis (origin) self.write("\x1b\xa5\x70%s\x58" % 0) # Set absolute positioning on the y axis (origin) self.write("\x1b\xa5\x70%s\x59" % 0) # recorro buffer de bits, armo bytes y envio a la impresora: # TODO: optimizar con struct o similar? saved = 0 for li, d in enumerate(buf): if not compress: m = v == 8 and '\x00' or '\x21' # 24 dot double density (200DPI) n = len(d) / (v / 8) #logger.debug("line %s length %s" % (li, n)) self.write("\x1b\x2A%s%s%s" % (m, ("%04x" % n).decode("hex")[::-1], ''.join(d))) self.write("\x0a\x0d") else: cant_bytes = len(d) ##assert 0 <= cant_byte <= 110 # máximo 1 bit por pixel # Receive graphic data ("Graphics Advanced Mode Commands" p20) self.write("\x1b\xa5\x62%s\x57" % cant_bytes) buf = '' for char, group in itertools.groupby(d): group_len = len(list(group)) if char < '\xc0' and group_len == 1: # envio el caracter sin comprimir buf += char else: # comprimo por RLE en hasta 63 repeticiones por vez while group_len: if group_len > 63: multiplication_factor = 63 else: multiplication_factor = group_len saved = saved + multiplication_factor - 1 # envio cantidad de repeticiones y caracter: buf += chr(0xc0 + multiplication_factor) + char group_len -= multiplication_factor self.write(buf) if compress and not only_buffer: self.do_print() logger.debug("compressed, bytes saved: %s" % saved) t4 = time.time() logger.info("Fin impresion: %s" % t4) logger.info("Total apertura: %s" % (t1 - t0)) logger.info("Total tranform: %s" % (t2 - t1)) logger.info("Total buffering: %s" % (t3 - t2)) logger.info("Total impresion: %s" % (t4 - t3)) logger.info("Total general: %s" % (t4 - t0)) # expulso la hoja: if not only_buffer: self.expulsar_boleta() if self.is_dummy(): im.save("customtpt-dummy.png", "PNG") os.system("eog customtpt-dummy.png") self._isprinting = False
def imprimir_image_slow( self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False ): """Imprime la imagen en velocidad lenta.""" self._isprinting = True # borro la data self.write("\x18") # des-activo modo comprimido en baja calidad (para pruebas) if compress and dpi != DPI_VOTO_ALTA: compress = False t0 = time.time() # tiempo inicial im = image if im.mode != "1": logger.debug("Convirtiendo a B/N...") im = im.convert("1") # convertir B/W (1 bit) t1 = time.time() # tiempo apertura/conversion if transpose: logger.debug("Rotando 270º (apaisado)...") im = im.transpose(Image.ROTATE_270) # landscape if dpi == (67, 67): logger.debug("Ajustando aspecto a 100x67 dpi (redimensionando)...") logger.debug("Tamaño anterior: %s" % im.size) im = im.resize((im.size[0] * 100 / 67, im.size[1])) # aspecto ratio dpi = DPI_VOTO_BAJA logger.debug("Tamaño actual: %s" % im.size) # bit verticales (manual pp. 28 "Select image mode") if dpi == DPI_VOTO_BAJA: v = 8 # (baja calidad) elif dpi == DPI_VOTO_ALTA: v = 24 # (alta calidad) else: # 67x200 y 200x100 DPI se complica armar el bitmap raise RuntimeError("Calidad de impresión requerida no soportada: %s" % str(dpi)) buf = [] t2 = time.time() logger.debug("Iniciando buffering: %s" % t2) # recorro pixels, armo buffer de bits para enviar a la impresora # obtengo los datos internos de PIL para optimizar (en vez de getpixel) data = list(im.getdata()) xmax = im.size[0] if not compress: # buferring sin compresión: recorre de arriba a abajo, izq a der # en baja: transpone 8 pixeles verticales (1 byte) # en alta: transpone 24 pixeles verticales (3 bytes) for y in range(0, im.size[1], v): d = [] for x in range(im.size[0]): for k in range(0, v / 8): b = 0 for j in range(0, 8): try: b = b | ((0 if data[(x + (y + j + 8 * k) * xmax)] else 1) << (7 - j)) except IndexError: # ultimo boundary != 8bits! (completar con blancos) # logger.debug("IndexError: alto debe ser múltiplo de 8 bits") pass d.append(chr(b)) buf.append(d) else: # buffering para compresion: recorre de arriba a abjo, izq a der # en alta: empaqueta de a 8 pixeles horizontales (1 byte) for y in range(0, im.size[1]): d = "" for x in range(0, im.size[0], 8): b = 0 i0 = x + y * xmax # optimización para bajar 50% el tiempo de buffering: try: if not data[i0 + 0]: b += 128 if not data[i0 + 1]: b += 64 if not data[i0 + 2]: b += 32 if not data[i0 + 3]: b += 16 if not data[i0 + 4]: b += 8 if not data[i0 + 5]: b += 4 if not data[i0 + 6]: b += 2 if not data[i0 + 7]: b += 1 d += chr(b) except IndexError: pass buf.append(d) t3 = time.time() logger.debug("Inicio impresion: %s" % t3) if not only_buffer: self.write("\x1D\xF9\x04") # return 4 lines if compress: # sets the page lenght in dots self.write("\x1b\xa5\x6c%s\x50" % 100) # im.size[1]) # Enable data compression ("Graphics Advanced Mode Commands" p19) self.write("\x1b\xa5\x62\x31\x4d") # Set absolute positioning on the x axis (origin) self.write("\x1b\xa5\x70%s\x58" % 0) # Set absolute positioning on the y axis (origin) self.write("\x1b\xa5\x70%s\x59" % 0) # recorro buffer de bits, armo bytes y envio a la impresora: # TODO: optimizar con struct o similar? saved = 0 for li, d in enumerate(buf): if not compress: m = v == 8 and "\x00" or "\x21" # 24 dot double density (200DPI) n = len(d) / (v / 8) # logger.debug("line %s length %s" % (li, n)) self.write("\x1b\x2A%s%s%s" % (m, ("%04x" % n).decode("hex")[::-1], "".join(d))) self.write("\x0a\x0d") else: cant_bytes = len(d) ##assert 0 <= cant_byte <= 110 # máximo 1 bit por pixel # Receive graphic data ("Graphics Advanced Mode Commands" p20) self.write("\x1b\xa5\x62%s\x57" % cant_bytes) buf = "" for char, group in itertools.groupby(d): group_len = len(list(group)) if char < "\xc0" and group_len == 1: # envio el caracter sin comprimir buf += char else: # comprimo por RLE en hasta 63 repeticiones por vez while group_len: if group_len > 63: multiplication_factor = 63 else: multiplication_factor = group_len saved = saved + multiplication_factor - 1 # envio cantidad de repeticiones y caracter: buf += chr(0xC0 + multiplication_factor) + char group_len -= multiplication_factor self.write(buf) if compress and not only_buffer: self.do_print() logger.debug("compressed, bytes saved: %s" % saved) t4 = time.time() logger.info("Fin impresion: %s" % t4) logger.info("Total apertura: %s" % (t1 - t0)) logger.info("Total tranform: %s" % (t2 - t1)) logger.info("Total buffering: %s" % (t3 - t2)) logger.info("Total impresion: %s" % (t4 - t3)) logger.info("Total general: %s" % (t4 - t0)) # expulso la hoja: if not only_buffer: self.expulsar_boleta() if self.is_dummy(): im.save("customtpt-dummy.png", "PNG") os.system("eog customtpt-dummy.png") self._isprinting = False
def imprimir_image( self, image, dpi=get_dpi_boletas(), transpose=False, compress=COMPRESION_IMPRESION, only_buffer=False ): raise NotImplementedError