Custom Colored Images with Badgeyay
Backend functionality of any Badge generator is to generate badges as per the requirements of the user. Currently Badgeyay is capable of generating badges by the following way: Adding or Selecting a Pre-defined Image from the given set Uploading a new image and then using it as a background Well, badgeyay has been missing a functionality of generating Custom Colored images. What is meant by Custom Colored Badges? Currently, there are a set of 7 different kind of pre-defined images to choose from. But let’s say that a user want to choose from the images but doesn’t like any of the color. Therefore we provide the user with an additional option of applying custom background-color for their badges. This allows Badgeyay to deliver a more versatile amount of badges than ever before. Adding the functionality to backend Lets see how this functionality has been implemented in the backend of the project. Step 1 : Adding a background-color route to backend Before generating badges, we need to know that what is the color that the user wants on the badge. Therefore we created a route that gathers the color and saves the user-defined.svg into that particular color. @router.route('/background_color', methods=['POST']) def background_color(): try: data = request.get_json()['data']['attributes'] bg_color = data['bg_color'] except Exception: return ErrorResponse(PayloadNotFound().message, 422, {'Content-Type': 'application/json'}).respond() svg2png = SVG2PNG() bg_color = '#' + str(bg_color) user_defined_path = svg2png.do_svg2png(1, bg_color) with open(user_defined_path, "rb") as image_file: image_data = base64.b64encode(image_file.read()) os.remove(user_defined_path) try: imageName = saveToImage(imageFile=image_data.decode('utf-8'), extension=".png") except Exception: return ErrorResponse(ImageNotFound().message, 422, {'Content-Type': 'application/json'}).respond() uid = data['uid'] fetch_user = User.getUser(user_id=uid) if fetch_user is None: return ErrorResponse(UserNotFound(uid).message, 422, {'Content-Type': 'application/json'}).respond() file_upload = File(filename=imageName, filetype='image', uploader=fetch_user) file_upload.save_to_db() return jsonify(ColorImageSchema().dump(file_upload).data) Step 2: Adding Schema for background-color to backend To get and save values from and to database, we need to have some layer of abstraction and so we use schemas created using marshmallow_jsonapi class ColorImageSchema(Schema): class Meta: type_ = 'bg-color' self_view = 'fileUploader.background_color' kwargs = {'id': '<id>'} id = fields.Str(required=True, dump_only=True) filename = fields.Str(required=True) filetype = fields.Str(required=True) user_id = fields.Relationship( self_url='/api/upload/background_color', self_url_kwargs={'file_id': '<id>'}, related_url='/user/register', related_url_kwargs={'id': '<id>'}, include_resource_linkage=True, type_='User' ) Now we have our schema and route done, So we can move forward with the logic of making badges. Step 3 : Converting the SVG to PNG and adding custom color Now we have the user-defined color for the badge background, but we still need a way to apply it to the badges. It is done using the following code below. def do_svg2png(self, opacity, fill): """ Module to convert svg to png :param `opacity` - Opacity for the output :param `fill` - Background fill for the output """ filename = os.path.join(self.APP_ROOT, 'svg', 'user_defined.svg') tree = parse(open(filename, 'r')) element = tree.getroot() # changing style using XPath. path = element.xpath('//*[@id="rect4504"]')[0] style_detail = path.get("style") style_detail = style_detail.split(";") style_detail[0] = "opacity:" + str(opacity) style_detail[1] = "fill:" + str(fill) style_detail = ';'.join(style_detail) path.set("style", style_detail) # changing text using XPath. path = element.xpath('//*[@id="tspan932"]')[0] # Saving in the original XML tree etree.ElementTree(element).write(filename, pretty_print=True) print("done") png_name = os.path.join(self.APP_ROOT, 'static', 'uploads', 'image', str(uuid.uuid4())) + ".png" svg2png(url=filename, write_to=png_name) return png_name Finally…
