@alexey.noskov May I get an update on ticket WORDSPYTHON-114?
@AlainGyger Most likely, the issue will be resolved in the next 26.1 version of Aspose.Words for Python. We have already made the required changes in the main .NET code of Aspose.Words.
That’s excellent, thank you for the update!
1 Like
@AlainGyger We have released new 26.1 version of Aspose.Words for Python. Now, you can use IBarcodeGenerator. Here is code example:
doc = aw.Document("C:\\Temp\\in.docx")
doc.field_options.barcode_generator = CustomBarcodeGenerator()
doc.save("C:\\Temp\\out.pdf")
Implementation of IBarcodeGenerator:
import io
import aspose.words as aw
import aspose.barcode as ab
import aspose.pydrawing as pydraw
class CustomBarcodeGenerator(aw.fields.IBarcodeGenerator):
default_qr_x_dimension_in_pixels = 4.0
default_1_dx_dimension_in_pixels = 1.0
def twips_to_pixels(self, heightInTwips, defVal):
"""Converts a height value in twips to pixels using a default DPI of 96."""
return self.twips_to_pixels(heightInTwips, 96, defVal)
def twips_to_pixels(self, heightInTwips, resolution, def_val) :
"""Converts a height value in twips to pixels based on the given resolution."""
try :
lVal = int(heightInTwips)
return (lVal / 1440.0) * resolution
except Exception as e:
return def_val
def get_rotation_angle(self, rotationAngle, defVal):
"""Gets the rotation angle in degrees based on the given rotation angle string."""
match rotationAngle:
case "0": return 0
case "1": return 270
case "2": return 180
case "3": return 90
case _ : return defVal
def get_qr_correction_level(self, errorCorrectionLevel, def_val) -> ab.generation.QRErrorLevel:
"""Converts a string representation of an error correction level to a QRErrorLevel enum value."""
match errorCorrectionLevel:
case "0": return ab.generation.QRErrorLevel.LEVEL_L
case "1": return ab.generation.QRErrorLevel.LEVEL_M
case "2": return ab.generation.QRErrorLevel.LEVEL_Q
case "3": return ab.generation.QRErrorLevel.LEVEL_H
case _ : return def_val
def get_barcode_encode_type(self, encode_type_from_word) -> ab.generation.EncodeTypes:
"""Gets the barcode encode type based on the given encode type from Word."""
match encode_type_from_word:
case "QR":
return ab.generation.EncodeTypes.QR
case "CODE128":
return ab.generation.EncodeTypes.CODE128
case "CODE39":
return ab.generation.EncodeTypes.CODE39
case "JPPOST":
return ab.generation.EncodeTypes.RM4SCC
case "EAN8":
return ab.generation.EncodeTypes.EAN8
case "JAN8":
return ab.generation.EncodeTypes.EAN8
case "EAN13":
return ab.generation.EncodeTypes.EAN13
case "JAN13":
return ab.generation.EncodeTypes.EAN13
case "UPCA":
return ab.generation.EncodeTypes.UPCA
case "UPCE":
return ab.generation.EncodeTypes.UPCE
case "CASE":
return ab.generation.EncodeTypes.ITF14
case "ITF14":
return ab.generation.EncodeTypes.ITF14
case "NW7":
return ab.generation.EncodeTypes.CODABAR
case _:
return ab.generation.EncodeTypes.NONE
def convert_color(self, input_color, def_val) -> pydraw.Color:
"""Converts a hexadecimal color string to a Color object."""
if not input_color: return def_val
try:
color = int(input_color, base=16)
return pydraw.Color.from_argb((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
except Exception as e:
return def_val
def scale_factor(self, scaleFactor, def_val):
"""Calculates the scale factor based on the provided string representation."""
try :
scale = int(scaleFactor)
return scale / 100.0
except Exception as e:
return def_val
def set_pos_code_style(self, gen : ab.generation.BarcodeGenerator, pos_code_style, barcode_value):
"""Sets the position code style for a barcode generator."""
match pos_code_style:
# STD default and without changes.
case "SUP2":
gen.code_text = barcode_value[:-2]
gen.parameters.barcode.supplement.supplement_data = barcode_value[-2:]
case "SUP5":
gen.code_text = barcode_value[:-5]
gen.parameters.barcode.supplement.supplement_data = barcode_value[-5:]
case "CASE":
gen.parameters.border.visible = True
gen.parameters.border.color = gen.parameters.barcode.bar_color
gen.parameters.border.DashStyle = ab.BorderDashStyle.SOLID
gen.parameters.border.Width.Pixels = gen.parameters.barcode.x_dimension.pixels * 5
def draw_error_image(self, error) -> io.BytesIO:
"""Draws a simple error image with the given error text."""
# Create a simple image with the text "error"
from PIL import Image, ImageDraw, ImageFont
img = Image.new("RGB", (100, 100), color=(255, 255, 255))
d = ImageDraw.Draw(img)
font = ImageFont.load_default()
d.text((10, 40), error, font=font, fill=(255, 0, 0))
# Save image to a bytes buffer and return raw bytes
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format="PNG")
img_byte_arr.seek(0)
return img_byte_arr
def get_barcode_image(self, parameters: aw.fields.BarcodeParameters) -> io.BytesIO:
try:
gen = ab.generation.BarcodeGenerator(self.get_barcode_encode_type(parameters.barcode_type), parameters.barcode_value)
# Set color.
gen.parameters.barcode.bar_color = self.convert_color(parameters.foreground_color, gen.parameters.barcode.bar_color)
gen.parameters.back_color = self.convert_color(parameters.background_color, gen.parameters.back_color)
# Set display or hide text.
if not parameters.display_text:
gen.parameters.barcode.code_text_parameters.location = ab.generation.CodeLocation.NONE
else:
gen.parameters.barcode.code_text_parameters.location = ab.generation.CodeLocation.BELOW
# Set QR Code error correction level.s
gen.parameters.barcode.qr.error_level = ab.generation.QRErrorLevel.LEVEL_H
if parameters.error_correction_level:
gen.parameters.barcode.qr.error_level = self.get_qr_correction_level(parameters.error_correction_level, gen.parameters.barcode.qr.qr_error_level)
# Set rotation angle.
if parameters.symbol_rotation:
gen.parameters.rotation_angle = self.get_rotation_angle(parameters.symbol_rotation, gen.parameters.rotation_angle)
# Set scaling factor.
scalingFactor = 1
if parameters.scaling_factor:
scalingFactor = self.scale_factor(parameters.scaling_factor, scalingFactor)
# Set size.
if gen.barcode_type == ab.generation.EncodeTypes.QR:
gen.parameters.barcode.x_dimension.pixels = max(1.0, round(self.default_qr_x_dimension_in_pixels * scalingFactor))
else:
gen.parameters.barcode.x_dimension.pixels = max(1.0, round(self.default_1_dx_dimension_in_pixels * scalingFactor))
# Set height.
if parameters.symbol_height:
gen.parameters.barcode.bar_height.pixels = max(5.0, round(self.twips_to_pixels(parameters.symbol_height, gen.parameters.barcode.bar_height.pixels) * scalingFactor))
# Set style of a Point-of-Sale barcode.
if parameters.pos_code_style :
self.set_pos_code_style(gen, parameters.pos_code_style, parameters.barcode_value)
img_byte_arr = io.BytesIO()
gen.save(img_byte_arr, ab.generation.BarCodeImageFormat.PNG)
img_byte_arr.seek(0)
return img_byte_arr
except Exception as e:
print("Error generating barcode: " + str(e))
return self.draw_error_image(str(e))
def get_old_barcode_image(self, parameters: aw.fields.BarcodeParameters) -> io.BytesIO:
raise NotImplementedError()