Example #1
0
def build_thumbnail(source_skin, photo_offset_x, photo_offset_y):
    """
    Build a photo of the source_skin by applying the transformation with the mappings/source image reversed.
    This is useful to visualise how the source_skin will look when uploaded to Minecraft.
    The photo is the source_skin unwrapped (e.g. head top unfolds at the top, back arms on the left/right etc).

    :param source_skin: Image representing the skin
    :param photo_offset_x: x-offset to start creating the photo
    :param photo_offset_y: y-offset to start creating the photo
    :return an Image representing the thumbnail
    """
    logger.info("Converting source_skin back to photo...")
    mapping_skin_to_photo = {}
    for part in parts:
        to_coords = get_photo_coords(parts[part], photo_offset_x,
                                     photo_offset_y)
        if to_coords is None:
            # if the body part doesn't appear on the photo, just skip it (no need to 'paint it' as before
            logger.debug("Skipping %s because to_coords are None", xstr(part))
            continue

        from_coords = get_skin_coords(parts[part])
        mapping_skin_to_photo[xstr(part)] = [
            source_skin, parts[part][2] - parts[part][0],
            parts[part][3] - parts[part][1], from_coords, to_coords
        ]
        logger.debug("Adding %s: %s", xstr(part),
                     xstr(mapping_skin_to_photo[xstr(part)]))

    photo = transform_image(source_skin.width, source_skin.height, 'white',
                            mapping_skin_to_photo)

    return photo
Example #2
0
def transform_image(new_width, new_height, background, mappings):
    """
    Create a new image based on the supplied mappings. Helper function to build images photo > skin > thumbnail

    :param new_width: width of the new image
    :param new_height: height of the new image
    :param background: colour of new image (None is transparent)
    :param mappings: a dictionary of mappings of the form key: [ sourceImage, widthToGrab, heightToGrab, fromTopLeftX, fromTopLeftY, toTopLeftX, toTopLeftY]
    :return the new Image
    """
    new_img = Image.new('RGBA', (new_width, new_height), background)

    for part in mappings:
        logger.debug("Processing mapping: %s", xstr(mappings[part]))
        src_img, width, height, (from_x, from_y), (to_x, to_y) = mappings[part]

        logger.debug("Slicing %s from (%d, %d),(%d, %d) to (%d, %d)",
                     xstr(part), from_x, from_y, from_x + width,
                     from_y + height, to_x, to_y)
        clipboard = src_img.crop(
            (from_x, from_y, from_x + width, from_y + height))
        new_img.paste(clipboard, (to_x, to_y, to_x + width, to_y + height))

    return new_img
Example #3
0
def build_skin(photo_filename, photo_offset_x, photo_offset_y):
    """
    Build a minecraft skin and a thumbnail from the provided photo image.

    :param photo_filename: the source photo
    :param photo_offset_x: x-offset to start building the skin
    :param photo_offset_y: y-offset to start building the skin
    :return a new Image of the skin
    """

    # open the reference images used to 'paint' body parts that are not available from the photo
    colours = {
        'lightGrey': Image.open(IMG_FOLDER + '/lightGrey.png'),
        'darkGrey': Image.open(IMG_FOLDER + '/darkGrey.png'),
        'blue': Image.open(IMG_FOLDER + '/blue.png'),
        'green': Image.open(IMG_FOLDER + '/green.png'),
        'black': Image.open(IMG_FOLDER + '/black.png')
    }

    logger.info("Converting photo '%s' to skin with offset (%d, %d)",
                photo_filename, photo_offset_x, photo_offset_y)

    photo = photos.pick_asset(photos.get_assets(), multi=False).get_image()

    # resize the photo to match the skin size (keep the aspect ratio to avoid stretching)
    photo_scale = min(photo.width / SKIN_WIDTH, photo.height / SKIN_HEIGHT)
    logger.debug("Scaling factor = %f", photo_scale)

    x = int(photo.width / photo_scale)
    y = int(photo.height / photo_scale)
    logger.info("Resizing the photo from %dx%d to %dx%d", photo.width,
                photo.height, x, y)
    photo = photo.resize((x, y))

    # Build the mappings to build the skin from the photo
    # by reading the position of each body part in the photo, and finding the location
    # in the Minecraft skin format.
    # If the part does not need to be taken from the photo,
    # use one of the reference images to 'paint' the part instead.
    # The image where the pixels are to be taken from are included in each
    # mapping entry (it is not always the photo - it is sometimes one of the reference images)
    mapping_photo_to_skin = {}
    for part in parts:
        from_coords = get_photo_coords(parts[part], photo_offset_x,
                                       photo_offset_y)
        if from_coords is None:
            # cannot use photo, so need to select another colour
            # colour = 'lightGrey'    # default (e.g. back)
            colour = 'green'
            if 'Leg' in xstr(part):
                colour = 'blue'
            if 'Arm' in xstr(part):
                colour = 'green'
            if 'Bottom' in xstr(part):  # takes priority over leg/arm
                colour = 'darkGrey'
            logger.debug("Painting %s with %s because from_coords are None",
                         xstr(part), xstr(colour))
            from_img = colours[colour]  # uncomment this if you want textures
            # from_img = colours['black'] # uncomment this if you want black
            from_coords = (0, 0)

        else:
            from_coords = (from_coords[0] + photo_offset_x,
                           from_coords[1] + photo_offset_y)
            from_img = photo

        to_coords = get_skin_coords(parts[part])
        mapping_photo_to_skin[xstr(part)] = [
            from_img, parts[part][2] - parts[part][0],
            parts[part][3] - parts[part][1], from_coords, to_coords
        ]
        logger.debug("Adding %s: %s", xstr(part),
                     xstr(mapping_photo_to_skin[xstr(part)]))

    # create the skin
    new_skin = transform_image(64, 64, None, mapping_photo_to_skin)
    photo.close()

    return new_skin