예제 #1
0
    def writeBezelConfig(bezel, systemName, rom):
        romBase = os.path.splitext(
            os.path.basename(rom))[0]  # filename without extension

        tmpZipDir = "/var/run/mame_artwork/" + romBase  # ok, no need to zip, a folder is taken too
        # clean, in case no bezel is set, and in case we want to recreate it
        if os.path.exists(tmpZipDir):
            shutil.rmtree(tmpZipDir)

        if bezel is None:
            return

        # let's generate the zip file
        os.makedirs(tmpZipDir)

        # bezels infos
        bz_infos = bezelsUtil.getBezelInfos(rom, bezel, systemName)
        if bz_infos is None:
            return

        # copy the png inside
        os.symlink(bz_infos["png"], tmpZipDir + "/default.png")

        img_width, img_height = bezelsUtil.fast_image_size(bz_infos["png"])
        game_width, game_height = MameGenerator.getMameMachineSize(
            romBase, tmpZipDir)
        bz_width = (game_width * img_height) / game_height
        bz_height = img_height
        bz_x = int((img_width - bz_width) / 2)
        bz_y = 0

        f = open(tmpZipDir + "/default.lay", 'w')
        f.write("<mamelayout version=\"2\">")
        f.write(
            "<element name=\"bezel\"><image file=\"default.png\" /></element>")
        f.write("<view name=\"bezel\">")
        f.write("<screen index=\"0\"><bounds x=\"" + str(bz_x) + "\" y=\"" +
                str(bz_y) + "\" width=\"" + str(bz_width) + "\" height=\"" +
                str(bz_height) + "\" /></screen>")
        f.write("<bezel element=\"bezel\"><bounds x=\"0\" y=\"0\" width=\"" +
                str(img_width) + "\" height=\"" + str(img_height) +
                "\" /></bezel>")
        f.write("</view>")
        f.write("</mamelayout>")
        f.close()
예제 #2
0
def getHudBezel(system, rom, gameResolution):
    if 'bezel' not in system.config or system.config['bezel'] == "" or system.config['bezel'] == "none":
        return None

    eslog.debug("hud enabled. trying to apply the bezel {}".format(system.config['bezel']))

    if generators[system.config['emulator']].supportsInternalBezels():
        eslog.debug("skipping bezels for emulator {}".format(system.config['emulator']))
        return None

    bezel = system.config['bezel']
    bz_infos = bezelsUtil.getBezelInfos(rom, bezel, system.name)
    if bz_infos is None:
        eslog.debug("no bezel info file found")
        return None

    overlay_info_file = bz_infos["info"]
    overlay_png_file  = bz_infos["png"]

    # check the info file
    # bottom, top, left and right must not cover too much the image to be considered as compatible
    if os.path.exists(overlay_info_file):
        try:
            infos = json.load(open(overlay_info_file))
        except:
            eslog.warning("unable to read {}".format(overlay_info_file))
            infos = {}
    else:
        infos = {}

    if "width" in infos and "height" in infos:
        bezel_width  = infos["width"]
        bezel_height = infos["height"]
        eslog.info("bezel size read from {}".format(overlay_info_file))
    else:
        bezel_width, bezel_height = bezelsUtil.fast_image_size(overlay_png_file)
        eslog.info("bezel size read from {}".format(overlay_png_file))

    # max cover proportion and ratio distortion
    max_cover = 0.05 # 5%
    max_ratio_delta = 0.01

    screen_ratio = gameResolution["width"] / gameResolution["height"]
    bezel_ratio  = bezel_width / bezel_height

    # the screen and bezel ratio must be approximatly the same
    if abs(screen_ratio - bezel_ratio) > max_ratio_delta:
        eslog.debug("screen ratio ({}) is too far from the bezel one ({}) : {} - {} > {}".format(screen_ratio, bezel_ratio, screen_ratio, bezel_ratio, max_ratio_delta))
        return None

    # the ingame image and the bezel free space must feet
    ## the bezel top and bottom cover must be minimum
    if "top" in infos and infos["top"] / bezel_height > max_cover:
        eslog.debug("bezel top covers too much the game image : {} / {} > {}".format(infos["top"], bezel_height, max_cover))
        return None
    if "bottom" in infos and infos["bottom"] / bezel_height > max_cover:
        eslog.debug("bezel bottom covers too much the game image : {} / {} > {}".format(infos["bottom"], bezel_height, max_cover))
        return None

    # if there is no information about top/bottom, assume default is 0

    ## the bezel left and right cover must be maximum
    ingame_ratio = generators[system.config['emulator']].getInGameRatio(system.config, gameResolution)
    img_height = bezel_height
    img_width  = img_height * ingame_ratio

    if "left" not in infos:
        eslog.debug("bezel has no left info in {}".format(overlay_info_file))
        # assume default is 4/3 over 16/9
        infos_left = (bezel_width - (bezel_height / 3 * 4)) / 2
        if abs((infos_left  - ((bezel_width-img_width)/2.0)) / img_width) > max_cover:
            eslog.debug("bezel left covers too much the game image : {} / {} > {}".format(infos_left  - ((bezel_width-img_width)/2.0), img_width, max_cover))
            return None
        
    if "right" not in infos:
        eslog.debug("bezel has no right info in {}".format(overlay_info_file))
        # assume default is 4/3 over 16/9
        infos_right = (bezel_width - (bezel_height / 3 * 4)) / 2
        if abs((infos_right - ((bezel_width-img_width)/2.0)) / img_width) > max_cover:
            eslog.debug("bezel right covers too much the game image : {} / {} > {}".format(infos_right  - ((bezel_width-img_width)/2.0), img_width, max_cover))
            return None
    
    if "left"  in infos and abs((infos["left"]  - ((bezel_width-img_width)/2.0)) / img_width) > max_cover:
        eslog.debug("bezel left covers too much the game image : {} / {} > {}".format(infos["left"]  - ((bezel_width-img_width)/2.0), img_width, max_cover))
        return None
    if "right" in infos and abs((infos["right"] - ((bezel_width-img_width)/2.0)) / img_width) > max_cover:
        eslog.debug("bezel right covers too much the game image : {} / {} > {}".format(infos["right"]  - ((bezel_width-img_width)/2.0), img_width, max_cover))
        return None

    # if screen and bezel sizes doesn't match, resize
    if (bezel_width != gameResolution["width"] or bezel_height != gameResolution["height"]):
        eslog.debug("bezel needs to be resized")
        output_png_file = "/tmp/bezel.png"
        try:
            bezelsUtil.resizeImage(overlay_png_file, output_png_file, gameResolution["width"], gameResolution["height"])
        except Exception as e:
            eslog.error("failed to resize the image {}".format(e))
            return None
        overlay_png_file = output_png_file

    if system.isOptSet('bezel.tattoo') and system.config['bezel.tattoo'] != "0":
        output_png_file = "/tmp/bezel_tattooed.png"
        bezelsUtil.tatooImage(overlay_png_file, output_png_file, system)
        overlay_png_file = output_png_file

    eslog.debug("applying bezel {}".format(overlay_png_file))
    return overlay_png_file
예제 #3
0
def writeBezelConfig(bezel, retroarchConfig, systemName, rom, gameResolution,
                     bezel_stretch):
    # disable the overlay
    # if all steps are passed, enable them
    retroarchConfig['input_overlay_hide_in_menu'] = "false"
    overlay_cfg_file = batoceraFiles.overlayConfigFile

    # bezel are disabled
    # default values in case something wrong append
    retroarchConfig['input_overlay_enable'] = "false"
    retroarchConfig['video_message_pos_x'] = 0.05
    retroarchConfig['video_message_pos_y'] = 0.05

    if bezel is None:
        return

    bz_infos = bezelsUtil.getBezelInfos(rom, bezel, systemName)
    if bz_infos is None:
        return

    overlay_info_file = bz_infos["info"]
    overlay_png_file = bz_infos["png"]
    bezel_game = bz_infos["specific_to_game"]

    # only the png file is mandatory
    if os.path.exists(overlay_info_file):
        try:
            infos = json.load(open(overlay_info_file))
        except:
            infos = {}
    else:
        infos = {}

    # if image is not at the correct size, find the correct size
    bezelNeedAdaptation = False
    viewPortUsed = True
    if "width" not in infos or "height" not in infos or "top" not in infos or "left" not in infos or "bottom" not in infos or "right" not in infos:
        viewPortUsed = False

    gameRatio = float(gameResolution["width"]) / float(
        gameResolution["height"])

    if viewPortUsed:
        if gameResolution["width"] != infos["width"] or gameResolution[
                "height"] != infos["height"]:
            if gameRatio < 1.6:  # let's use bezels only for 16:10, 5:3, 16:9 and wider aspect ratios
                return
            else:
                bezelNeedAdaptation = True
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index(
                "custom"))  # overwritten from the beginning of this file
    else:
        # when there is no information about width and height in the .info, assume that the tv is HD 16/9 and infos are core provided
        if gameRatio < 1.6:  # let's use bezels only for 16:10, 5:3, 16:9 and wider aspect ratios
            return
        else:
            # No info on the bezel, let's get the bezel image width and height and apply the
            # ratios from usual 16:9 1920x1080 bezels (example: theBezelProject)
            try:
                infos["width"], infos["height"] = bezelsUtil.fast_image_size(
                    overlay_png_file)
                infos["top"] = int(infos["height"] * 2 / 1080)
                infos["left"] = int(
                    infos["width"] * 241 / 1920
                )  # 241 = (1920 - (1920 / (4:3))) / 2 + 1 pixel = where viewport start
                infos["bottom"] = int(infos["height"] * 2 / 1080)
                infos["right"] = int(infos["width"] * 241 / 1920)
                bezelNeedAdaptation = True
            except:
                pass  # outch, no ratio will be applied.
        if gameResolution["width"] == infos["width"] and gameResolution[
                "height"] == infos["height"]:
            bezelNeedAdaptation = False
        retroarchConfig['aspect_ratio_index'] = str(ratioIndexes.index("core"))

    retroarchConfig['input_overlay_enable'] = "true"
    retroarchConfig['input_overlay_scale'] = "1.0"
    retroarchConfig['input_overlay'] = overlay_cfg_file
    retroarchConfig['input_overlay_hide_in_menu'] = "true"

    if "opacity" not in infos:
        infos["opacity"] = 1.0
    if "messagex" not in infos:
        infos["messagex"] = 0.0
    if "messagey" not in infos:
        infos["messagey"] = 0.0

    retroarchConfig['input_overlay_opacity'] = infos["opacity"]

    if bezelNeedAdaptation:
        wratio = gameResolution["width"] / float(infos["width"])
        hratio = gameResolution["height"] / float(infos["height"])

        # If width or height < original, can't add black borders, need to stretch
        if gameResolution["width"] < infos["width"] or gameResolution[
                "height"] < infos["height"]:
            bezel_stretch = True

        if bezel_stretch:
            retroarchConfig['custom_viewport_x'] = infos["left"] * wratio
            retroarchConfig['custom_viewport_y'] = infos["top"] * hratio
            retroarchConfig['custom_viewport_width'] = (
                infos["width"] - infos["left"] - infos["right"]) * wratio
            retroarchConfig['custom_viewport_height'] = (
                infos["height"] - infos["top"] - infos["bottom"]) * hratio
            retroarchConfig['video_message_pos_x'] = infos["messagex"] * wratio
            retroarchConfig['video_message_pos_y'] = infos["messagey"] * hratio
        else:
            if bezel_game is True:
                output_png_file = "/tmp/bezel_game_adapted.png"
                create_new_bezel_file = True
            else:
                create_new_bezel_file = False
                output_png_file = "/tmp/" + os.path.splitext(
                    os.path.basename(overlay_png_file))[0] + "_adapted.png"
                if os.path.exists(output_png_file) is False:
                    create_new_bezel_file = True
                else:
                    if os.path.getmtime(output_png_file) < os.path.getmtime(
                            overlay_png_file):
                        create_new_bezel_file = True
            # fast way of checking the size of a png
            oldwidth, oldheight = bezelsUtil.fast_image_size(output_png_file)
            if (oldwidth != gameResolution["width"]
                    or oldheight != gameResolution["height"]):
                create_new_bezel_file = True

            xoffset = gameResolution["width"] - infos["width"]
            yoffset = gameResolution["height"] - infos["height"]
            retroarchConfig['custom_viewport_x'] = infos["left"] + xoffset / 2
            retroarchConfig['custom_viewport_y'] = infos["top"] + yoffset / 2
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
            retroarchConfig[
                'video_message_pos_x'] = infos["messagex"] + xoffset / 2
            retroarchConfig[
                'video_message_pos_y'] = infos["messagey"] + yoffset / 2

            if create_new_bezel_file is True:
                # Padding left and right borders for ultrawide screens (larger than 16:9 aspect ratio)
                # or up/down for 4K
                eslog.log("Generating a new adapted bezel file {}".format(
                    output_png_file))
                fillcolor = 'black'

                borderw = 0
                borderh = 0
                if wratio > 1:
                    borderw = xoffset / 2
                if hratio > 1:
                    borderh = yoffset / 2
                imgin = Image.open(overlay_png_file)
                if imgin.mode != "RGBA":
                    # TheBezelProject have Palette + alpha, not RGBA. PIL can't convert from P+A to RGBA.
                    # Even if it can load P+A, it can't save P+A as PNG. So we have to recreate a new image to adapt it.
                    if not 'transparency' in imgin.info:
                        return  # no transparent layer for the viewport, abort
                    alpha = imgin.split()[
                        -1]  # alpha from original palette + alpha
                    ix, iy = imgin.size
                    imgnew = Image.new("RGBA", (ix, iy), (0, 0, 0, 255))
                    imgnew.paste(alpha, (0, 0, ix, iy))
                    imgout = ImageOps.expand(imgnew,
                                             border=(borderw, borderh,
                                                     xoffset - borderw,
                                                     yoffset - borderh),
                                             fill=fillcolor)
                    imgout.save(output_png_file, mode="RGBA", format="PNG")
                else:
                    imgout = ImageOps.expand(imgin,
                                             border=(borderw, borderh,
                                                     xoffset - borderw,
                                                     yoffset - borderh),
                                             fill=fillcolor)
                    imgout.save(output_png_file, mode="RGBA", format="PNG")
            overlay_png_file = output_png_file  # replace by the new file (recreated or cached in /tmp)
    else:
        if viewPortUsed:
            retroarchConfig['custom_viewport_x'] = infos["left"]
            retroarchConfig['custom_viewport_y'] = infos["top"]
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
        retroarchConfig['video_message_pos_x'] = infos["messagex"]
        retroarchConfig['video_message_pos_y'] = infos["messagey"]

    eslog.log("Bezel file set to {}".format(overlay_png_file))
    writeBezelCfgConfig(overlay_cfg_file, overlay_png_file)
예제 #4
0
def writeBezelConfig(bezel, retroarchConfig, rom, gameResolution, system):
    # disable the overlay
    # if all steps are passed, enable them
    retroarchConfig['input_overlay_hide_in_menu'] = "false"
    overlay_cfg_file = batoceraFiles.overlayConfigFile

    # bezel are disabled
    # default values in case something wrong append
    retroarchConfig['input_overlay_enable'] = "false"
    retroarchConfig['video_message_pos_x'] = 0.05
    retroarchConfig['video_message_pos_y'] = 0.05

    if bezel is None:
        return

    bz_infos = bezelsUtil.getBezelInfos(rom, bezel, system.name)
    if bz_infos is None:
        return

    overlay_info_file = bz_infos["info"]
    overlay_png_file = bz_infos["png"]
    bezel_game = bz_infos["specific_to_game"]

    # only the png file is mandatory
    if os.path.exists(overlay_info_file):
        try:
            infos = json.load(open(overlay_info_file))
        except:
            infos = {}
    else:
        infos = {}

    # if image is not at the correct size, find the correct size
    bezelNeedAdaptation = False
    viewPortUsed = True
    if "width" not in infos or "height" not in infos or "top" not in infos or "left" not in infos or "bottom" not in infos or "right" not in infos:
        viewPortUsed = False

    gameRatio = float(gameResolution["width"]) / float(
        gameResolution["height"])

    if viewPortUsed:
        if gameResolution["width"] != infos["width"] or gameResolution[
                "height"] != infos["height"]:
            if gameRatio < 1.6:  # let's use bezels only for 16:10, 5:3, 16:9 and wider aspect ratios
                return
            else:
                bezelNeedAdaptation = True
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index(
                "custom"))  # overwritten from the beginning of this file
    else:
        # when there is no information about width and height in the .info, assume that the tv is HD 16/9 and infos are core provided
        if gameRatio < 1.6:  # let's use bezels only for 16:10, 5:3, 16:9 and wider aspect ratios
            return
        else:
            # No info on the bezel, let's get the bezel image width and height and apply the
            # ratios from usual 16:9 1920x1080 bezels (example: theBezelProject)
            try:
                infos["width"], infos["height"] = bezelsUtil.fast_image_size(
                    overlay_png_file)
                infos["top"] = int(infos["height"] * 2 / 1080)
                infos["left"] = int(
                    infos["width"] * 241 / 1920
                )  # 241 = (1920 - (1920 / (4:3))) / 2 + 1 pixel = where viewport start
                infos["bottom"] = int(infos["height"] * 2 / 1080)
                infos["right"] = int(infos["width"] * 241 / 1920)
                bezelNeedAdaptation = True
            except:
                pass  # outch, no ratio will be applied.
        if gameResolution["width"] == infos["width"] and gameResolution[
                "height"] == infos["height"]:
            bezelNeedAdaptation = False
        retroarchConfig['aspect_ratio_index'] = str(ratioIndexes.index("core"))

    retroarchConfig['input_overlay_enable'] = "true"
    retroarchConfig['input_overlay_scale'] = "1.0"
    retroarchConfig['input_overlay'] = overlay_cfg_file
    retroarchConfig['input_overlay_hide_in_menu'] = "true"

    if "opacity" not in infos:
        infos["opacity"] = 1.0
    if "messagex" not in infos:
        infos["messagex"] = 0.0
    if "messagey" not in infos:
        infos["messagey"] = 0.0

    retroarchConfig['input_overlay_opacity'] = infos["opacity"]

    # stretch option
    if system.isOptSet('bezel_stretch') and system.getOptBoolean(
            'bezel_stretch') == True:
        bezel_stretch = True
    else:
        bezel_stretch = False

    if bezelNeedAdaptation:
        wratio = gameResolution["width"] / float(infos["width"])
        hratio = gameResolution["height"] / float(infos["height"])

        # If width or height < original, can't add black borders, need to stretch
        if gameResolution["width"] < infos["width"] or gameResolution[
                "height"] < infos["height"]:
            bezel_stretch = True

        if bezel_stretch:
            retroarchConfig['custom_viewport_x'] = infos["left"] * wratio
            retroarchConfig['custom_viewport_y'] = infos["top"] * hratio
            retroarchConfig['custom_viewport_width'] = (
                infos["width"] - infos["left"] - infos["right"]) * wratio
            retroarchConfig['custom_viewport_height'] = (
                infos["height"] - infos["top"] - infos["bottom"]) * hratio
            retroarchConfig['video_message_pos_x'] = infos["messagex"] * wratio
            retroarchConfig['video_message_pos_y'] = infos["messagey"] * hratio
        else:
            if bezel_game is True:
                output_png_file = "/tmp/bezel_game_adapted.png"
                create_new_bezel_file = True
            else:
                create_new_bezel_file = False
                output_png_file = "/tmp/" + os.path.splitext(
                    os.path.basename(overlay_png_file))[0] + "_adapted.png"
                if os.path.exists(output_png_file) is False:
                    create_new_bezel_file = True
                else:
                    if os.path.getmtime(output_png_file) < os.path.getmtime(
                            overlay_png_file):
                        create_new_bezel_file = True
            # fast way of checking the size of a png
            oldwidth, oldheight = bezelsUtil.fast_image_size(output_png_file)
            if (oldwidth != gameResolution["width"]
                    or oldheight != gameResolution["height"]):
                create_new_bezel_file = True

            xoffset = gameResolution["width"] - infos["width"]
            yoffset = gameResolution["height"] - infos["height"]
            retroarchConfig['custom_viewport_x'] = infos["left"] + xoffset / 2
            retroarchConfig['custom_viewport_y'] = infos["top"] + yoffset / 2
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
            retroarchConfig[
                'video_message_pos_x'] = infos["messagex"] + xoffset / 2
            retroarchConfig[
                'video_message_pos_y'] = infos["messagey"] + yoffset / 2

            if create_new_bezel_file is True:
                # Padding left and right borders for ultrawide screens (larger than 16:9 aspect ratio)
                # or up/down for 4K
                eslog.debug("Generating a new adapted bezel file {}".format(
                    output_png_file))
                try:
                    bezelsUtil.padImage(overlay_png_file, output_png_file,
                                        gameResolution["width"],
                                        gameResolution["height"],
                                        infos["width"], infos["height"])
                except:
                    return
            overlay_png_file = output_png_file  # replace by the new file (recreated or cached in /tmp)
    else:
        if viewPortUsed:
            retroarchConfig['custom_viewport_x'] = infos["left"]
            retroarchConfig['custom_viewport_y'] = infos["top"]
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
        retroarchConfig['video_message_pos_x'] = infos["messagex"]
        retroarchConfig['video_message_pos_y'] = infos["messagey"]

    if system.isOptSet(
            'bezel.tattoo') and system.config['bezel.tattoo'] != "0":
        output_png = "/tmp/bezel_tattooed.png"
        bezelsUtil.tatooImage(overlay_png_file, output_png_file, system)
        overlay_png_file = output_png_file

    eslog.debug("Bezel file set to {}".format(overlay_png_file))
    writeBezelCfgConfig(overlay_cfg_file, overlay_png_file)
예제 #5
0
    def writeBezelConfig(bezelSet, system, rom, messSys):
        romBase = os.path.splitext(
            os.path.basename(rom))[0]  # filename without extension

        if messSys == "":
            tmpZipDir = "/var/run/mame_artwork/" + romBase  # ok, no need to zip, a folder is taken too
        else:
            tmpZipDir = "/var/run/mame_artwork/" + messSys  # ok, no need to zip, a folder is taken too
        # clean, in case no bezel is set, and in case we want to recreate it
        if os.path.exists(tmpZipDir):
            shutil.rmtree(tmpZipDir)

        if bezelSet is None:
            return

        # let's generate the zip file
        os.makedirs(tmpZipDir)

        # bezels infos
        bz_infos = bezelsUtil.getBezelInfos(rom, bezelSet, system.name)
        if bz_infos is None:
            return

        # copy the png inside
        if os.path.exists(bz_infos["mamezip"]):
            if messSys == "":
                artFile = "/var/run/mame_artwork/" + romBase + ".zip"
            else:
                artFile = "/var/run/mame_artwork/" + messSys + ".zip"
            if os.path.exists(artFile):
                if os.islink(artFile):
                    os.unlink(artFile)
                else:
                    os.remove(artFile)
            os.symlink(bz_infos["mamezip"], artFile)
            return
        elif os.path.exists(bz_infos["layout"]):
            os.symlink(bz_infos["layout"], tmpZipDir + "/default.lay")
            pngFile = os.path.split(bz_infos["png"])[1]
            os.symlink(bz_infos["png"], tmpZipDir + "/" + pngFile)
        else:
            pngFile = "default.png"
            os.symlink(bz_infos["png"], tmpZipDir + "/default.png")
            if os.path.exists(bz_infos["info"]):
                bzInfoFile = open(bz_infos["info"], "r")
                bzInfoText = bzInfoFile.readlines()
                bz_alpha = 1.0  # Just in case it's not set in the info file
                for infoLine in bzInfoText:
                    if len(infoLine) > 7:
                        infoLineClean = (infoLine.replace(
                            '"', '')).rstrip(",\n").lstrip()
                        infoLineData = infoLineClean.split(":")
                        if infoLineData[0].lower() == "width":
                            img_width = int(infoLineData[1])
                        elif infoLineData[0].lower() == "height":
                            img_height = int(infoLineData[1])
                        elif infoLineData[0].lower() == "top":
                            bz_y = int(infoLineData[1])
                        elif infoLineData[0].lower() == "left":
                            bz_x = int(infoLineData[1])
                        elif infoLineData[0].lower() == "bottom":
                            bz_bottom = int(infoLineData[1])
                        elif infoLineData[0].lower() == "right":
                            bz_right = int(infoLineData[1])
                        elif infoLineData[0].lower() == "opacity":
                            bz_alpha = float(infoLineData[1])
                bzInfoFile.close()
                bz_width = img_width - bz_x - bz_right
                bz_height = img_height - bz_y - bz_bottom
            else:
                img_width, img_height = bezelsUtil.fast_image_size(
                    bz_infos["png"])
                _, _, rotate = MameGenerator.getMameMachineSize(
                    romBase, tmpZipDir)

                # assumes that all bezels are setup for 4:3H or 3:4V aspects
                if rotate == 270 or rotate == 90:
                    bz_width = int(img_height * (3 / 4))
                else:
                    bz_width = int(img_height * (4 / 3))
                bz_height = img_height
                bz_x = int((img_width - bz_width) / 2)
                bz_y = 0
                bz_alpha = 1.0

            f = open(tmpZipDir + "/default.lay", 'w')
            f.write("<mamelayout version=\"2\">\n")
            f.write(
                "<element name=\"bezel\"><image file=\"default.png\" /></element>\n"
            )
            f.write("<view name=\"bezel\">\n")
            f.write("<screen index=\"0\"><bounds x=\"" + str(bz_x) +
                    "\" y=\"" + str(bz_y) + "\" width=\"" + str(bz_width) +
                    "\" height=\"" + str(bz_height) + "\" /></screen>\n")
            f.write("<element ref=\"bezel\"><bounds x=\"0\" y=\"0\" width=\"" +
                    str(img_width) + "\" height=\"" + str(img_height) +
                    "\" alpha=\"" + str(bz_alpha) + "\" /></element>\n")
            f.write("</view>\n")
            f.write("</mamelayout>\n")
            f.close()

        if system.isOptSet(
                'bezel.tattoo') and system.config['bezel.tattoo'] != "0":
            if system.config['bezel.tattoo'] == 'system':
                try:
                    tattoo_file = '/usr/share/batocera/controller-overlays/' + system.name + '.png'
                    if not os.path.exists(tattoo_file):
                        tattoo_file = '/usr/share/batocera/controller-overlays/generic.png'
                    tattoo = Image.open(tattoo_file)
                except Exception as e:
                    eslog.error("Error opening controller overlay: {}".format(
                        tattoo_file))
            elif system.config['bezel.tattoo'] == 'custom' and os.path.exists(
                    system.config['bezel.tattoo_file']):
                try:
                    tattoo_file = system.config['bezel.tattoo_file']
                    tattoo = Image.open(tattoo_file)
                except:
                    eslog.error(
                        "Error opening custom file: {}".format('tattoo_file'))
            else:
                try:
                    tattoo_file = '/usr/share/batocera/controller-overlays/generic.png'
                    tattoo = Image.open(tattoo_file)
                except:
                    eslog.error(
                        "Error opening custom file: {}".format('tattoo_file'))
            output_png_file = "/tmp/bezel_tattooed.png"
            back = Image.open(tmpZipDir + "/" + pngFile)
            tattoo = tattoo.convert("RGBA")
            back = back.convert("RGBA")
            tw, th = bezelsUtil.fast_image_size(tattoo_file)
            tatwidth = int(
                240 / 1920 * img_width
            )  # 240 = half of the difference between 4:3 and 16:9 on 1920px (0.5*1920/16*4)
            pcent = float(tatwidth / tw)
            tatheight = int(float(th) * pcent)
            tattoo = tattoo.resize((tatwidth, tatheight), Image.ANTIALIAS)
            alpha = back.split()[-1]
            alphatat = tattoo.split()[-1]
            if system.isOptSet('bezel.tattoo_corner'):
                corner = system.config['bezel.tattoo_corner']
            else:
                corner = 'NW'
            if (corner.upper() == 'NE'):
                back.paste(tattoo, (img_width - tatwidth, 20),
                           alphatat)  # 20 pixels vertical margins (on 1080p)
            elif (corner.upper() == 'SE'):
                back.paste(tattoo,
                           (img_width - tatwidth, img_height - tatheight - 20),
                           alphatat)
            elif (corner.upper() == 'SW'):
                back.paste(tattoo, (0, img_height - tatheight - 20), alphatat)
            else:  # default = NW
                back.paste(tattoo, (0, 20), alphatat)
            imgnew = Image.new("RGBA", (img_width, img_height), (0, 0, 0, 255))
            imgnew.paste(back, (0, 0, img_width, img_height))
            imgnew.save(output_png_file, mode="RGBA", format="PNG")

            try:
                os.remove(tmpZipDir + "/" + pngFile)
            except:
                pass
            os.symlink(output_png_file, tmpZipDir + "/" + pngFile)
예제 #6
0
    def writeBezelConfig(bezel, system, rom):
        romBase = os.path.splitext(os.path.basename(rom))[0] # filename without extension

        tmpZipDir = "/var/run/mame_artwork/" + romBase # ok, no need to zip, a folder is taken too
        # clean, in case no bezel is set, and in case we want to recreate it
        if os.path.exists(tmpZipDir):
            shutil.rmtree(tmpZipDir)

        if bezel is None:
            return

        # let's generate the zip file
        os.makedirs(tmpZipDir)

        # bezels infos
        bz_infos = bezelsUtil.getBezelInfos(rom, bezel, system.name)
        if bz_infos is None:
            return

        # copy the png inside
        os.symlink(bz_infos["png"], tmpZipDir + "/default.png")

        img_width, img_height = bezelsUtil.fast_image_size(bz_infos["png"])
        _, _, rotate = MameGenerator.getMameMachineSize(romBase, tmpZipDir)

        # assumes that all bezels are setup for 4:3H or 3:4V aspects
        if rotate == 270 or rotate == 90:
            bz_width = int(img_height * (3 / 4))
        else:
            bz_width = int(img_height * (4 / 3))
        bz_height = img_height
        bz_x = int((img_width - bz_width) / 2)
        bz_y = 0

        if system.isOptSet('bezel.tattoo') and system.config['bezel.tattoo'] != "0":
            if system.config['bezel.tattoo'] == 'system':
                try:
                    tattoo_file = '/usr/share/batocera/controller-overlays/'+system.name+'.png'
                    if not os.path.exists(tattoo_file):
                        tattoo_file = '/usr/share/batocera/controller-overlays/generic.png'
                    tattoo = Image.open(tattoo_file)
                except Exception as e:
                    eslog.error("Error opening controller overlay: {}".format(tattoo_file))
            elif system.config['bezel.tattoo'] == 'custom' and os.path.exists(system.config['bezel.tattoo_file']):
                try:
                    tattoo_file = system.config['bezel.tattoo_file']
                    tattoo = Image.open(tattoo_file)
                except:
                    eslog.error("Error opening custom file: {}".format('tattoo_file'))
            else:
                try:
                    tattoo_file = '/usr/share/batocera/controller-overlays/generic.png'
                    tattoo = Image.open(tattoo_file)
                except:
                    eslog.error("Error opening custom file: {}".format('tattoo_file'))
            output_png_file = "/tmp/bezel_tattooed.png"
            back = Image.open(tmpZipDir + "/default.png")
            tattoo = tattoo.convert("RGBA")
            back = back.convert("RGBA")
            tw,th = bezelsUtil.fast_image_size(tattoo_file)
            tatwidth = int(240/1920 * img_width) # 240 = half of the difference between 4:3 and 16:9 on 1920px (0.5*1920/16*4)
            pcent = float(tatwidth / tw)
            tatheight = int(float(th) * pcent)
            tattoo = tattoo.resize((tatwidth,tatheight), Image.ANTIALIAS)
            alpha = back.split()[-1]
            alphatat = tattoo.split()[-1]
            if system.isOptSet('bezel.tattoo_corner'):
                corner = system.config['bezel.tattoo_corner']
            else:
                corner = 'NW'
            if (corner.upper() == 'NE'):
                back.paste(tattoo, (img_width-tatwidth,20), alphatat) # 20 pixels vertical margins (on 1080p)
            elif (corner.upper() == 'SE'):
                back.paste(tattoo, (img_width-tatwidth,img_height-tatheight-20), alphatat)
            elif (corner.upper() == 'SW'):
                back.paste(tattoo, (0,img_height-tatheight-20), alphatat)
            else: # default = NW
                back.paste(tattoo, (0,20), alphatat)
            imgnew = Image.new("RGBA", (img_width,img_height), (0,0,0,255))
            imgnew.paste(back, (0,0,img_width,img_height))
            imgnew.save(output_png_file, mode="RGBA", format="PNG")

            try:
                os.remove(tmpZipDir + "/default.png")
            except:
                pass
            os.symlink(output_png_file, tmpZipDir + "/default.png")

        f = open(tmpZipDir + "/default.lay", 'w')
        f.write("<mamelayout version=\"2\">")
        f.write("<element name=\"bezel\"><image file=\"default.png\" /></element>")
        f.write("<view name=\"bezel\">")
        f.write("<screen index=\"0\"><bounds x=\"" + str(bz_x) + "\" y=\"" + str(bz_y) + "\" width=\"" + str(bz_width) + "\" height=\"" + str(bz_height) + "\" /></screen>")
        f.write("<bezel element=\"bezel\"><bounds x=\"0\" y=\"0\" width=\"" + str(img_width) + "\" height=\"" + str(img_height) + "\" /></bezel>")
        f.write("</view>")
        f.write("</mamelayout>")
        f.close()