Source code for imagecat.operator.render

# Copyright 2020 Timothy M. Shead
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Functions that generate new :ref:`image<images>` data.
"""

import logging

import numpy

import imagecat.data
import imagecat.operator.util
import imagecat.units

log = logging.getLogger(__name__)


[docs]def text(graph, name, inputs): """Generate an image containing text. Parameters ---------- graph: :ref:`graph`, required Graph that owns this task. name: hashable object, required Name of the task executing this function. inputs: :ref:`named-inputs`, required Inputs for this operator. Named Inputs ------------ anchor: :class:`str`, optional Anchor point for text placement, defined at https://pillow.readthedocs.io/en/latest/handbook/text-anchors.html#text-anchors. Defaults to `"mm"`. fontindex: integer, optional Index of the font to use within a multi-font file. Defaults to `0`. fontname: :class:`str`, optional Path to a font file. Defaults to :func:`imagecat.data.default_font`. fontsize: Size of the rendered font, optional Default: `"0.33h"`, which is one-third the height of the output image. layer: :class:`str`, optional Name of the generated layer. Default: `["A"]`. position: (x, y) tuple, optional Position of the text anchor relative to the output image. Default: `["0.5w", "0.5h"]`, which is centered vertically and horizontally. res: (width, height) tuple, optional Resolution of the output image. Default: [256, 256]. string: :class:`str`, optional String to be rendered. Default: `"Text"`. Returns ------- image: :class:`imagecat.data.Image` New image containing rendered text. """ import PIL.Image import PIL.ImageDraw import PIL.ImageFont anchor = imagecat.operator.util.optional_input(name, inputs, "anchor", type=str, default="mm") fontindex = imagecat.operator.util.optional_input(name, inputs, "fontindex", type=int, default=0) fontname = imagecat.operator.util.optional_input(name, inputs, "fontname", type=str, default=imagecat.data.default_font()) fontsize = imagecat.operator.util.optional_input(name, inputs, "fontsize", default="0.33h") layer = imagecat.operator.util.optional_input(name, inputs, "layer", type=str, default="A") position = imagecat.operator.util.optional_input(name, inputs, "position", default=("0.5w", "0.5h")) res = imagecat.operator.util.optional_input(name, inputs, "res", type=imagecat.operator.util.array(shape=(2,), dtype=int), default=[256, 256]) string = imagecat.operator.util.optional_input(name, inputs, "string", type=str, default="Text") fontsize_px = int(imagecat.units.length(fontsize, res)) x = imagecat.units.length(position[0], res) y = res[1] - imagecat.units.length(position[1], res) # +Y = up pil_image = PIL.Image.new("L", (res[0], res[1]), 0) font = PIL.ImageFont.truetype(fontname, fontsize_px, fontindex) draw = PIL.ImageDraw.Draw(pil_image) draw.text((x, y), string, font=font, fill=255, anchor=anchor) data = numpy.array(pil_image, dtype=numpy.float16)[:,:,None] / 255.0 output = imagecat.data.Image({layer: imagecat.data.Layer(data=data, role=imagecat.data.Role.ALPHA)}) imagecat.operator.util.log_result(log, name, "text", output, anchor=anchor, fontindex=fontindex, fontname=fontname, fontsize=fontsize, layer=layer, position=position, res=res, string=string) return output