mrhan1993 / Fooocus-API

FastAPI powered API for Fooocus
GNU General Public License v3.0
562 stars 149 forks source link

Base64 padding/invalid string error #390

Open kizzhang opened 1 month ago

kizzhang commented 1 month ago

I encounter this issue with the current version when i tried to decode the output base64 image. This issue does not happen for a previous version (v0.3.30) that I have.

To produce the ERROR:

inpaint_params = {
    "prompt": "(realistic skin:2),dark skin, (skin texture:1.8), (muscular: 1.9)",
    "negative_prompt": "",#"cloth",
    "style_selections": [
        "Fooocus V2",
        "Fooocus Enhance",
        "Fooocus Sharp"
    ],
    "performance_selection": "Quality", # "Speed", "Quality",
    "aspect_ratios_selection": "1152*896",
    "image_number": 1,
    "image_seed": -1,
    "sharpness": 5,
    "guidance_scale": 4,
    "base_model_name": "juggernautXL_v9Rundiffusionphoto2.safetensors",
    "loras": [{"enabled": True,"model_name": "Darker_skin_SDXL.safetensors", "weight": 0.6}],

    "advanced_params": {
        "inpaint_strength": 0.5,  # NOTE
        "inpaint_respective_field": 0,  # NOTE
        "inpaint_erode_or_dilate": 0,
        "inpaint_engine": 'None'
    },
    "require_base64": True,  # NOTE
    "async_process": False,
    "input_image": "",
    "input_mask": "",
    "inpaint_additional_prompt": " ",
}

def inpaint(input_image: str, input_mask: str, preset_params: dict) -> dict:
    preset_params["input_image"] = input_image
    preset_params["input_mask"] = input_mask
    preset_params["require_base64"] = True
    preset_params["async_process"]= False
    data = json.dumps(preset_params)
    response = requests.post(url=f"{cfg.fooocus_host}{cfg.inpaint_outpaint}",
                             data=data,
                             headers=headers,
                             timeout=300)

    return response.json()

img = Image.open('path/to/image')
img = ImageOps.exif_transpose(img).convert("RGB")

def encode_image_to_base64(image: Image.Image) -> str:
    image_data = io.BytesIO()
    image.save(image_data, format='JPEG')
    image_data_bytes = image_data.getvalue()
    encoded_image = base64.b64encode(image_data_bytes).decode('utf-8')
    return encoded_image

def decode_base64_to_image(base64_image: str) -> Image.Image:
    pil_image = Image.open(io.BytesIO(base64.b64decode(base64_image))).convert("RGB")
    return pil_image

img_64bytes, mask_64bytes = encode_image_to_base64(image = img), encode_image_to_base64(image = res_mask)

inpaint_output = inpaint(input_image = img_64bytes,input_mask=mask_64bytes,preset_params=inpaint_params)

##### ERROR OCCURS HERE #####
inpainted_image = decode_base64_to_image(inpaint_output[0]['base64'])

As i mentioned, the last line does not incur any error but return correct image in the previous version.

mrhan1993 commented 1 month ago

I will deal with this problem in my spare time, sorry about this 😞

mrhan1993 commented 3 weeks ago

This issue caused by https://github.com/mrhan1993/Fooocus-API/commit/948f342bc62ba5ba2737acaf8e54f0bc82c91dff

The return is correct, but you have to remove str like 'data:image/{ext};base64,' , that is used for browser

change this :

def decode_base64_to_image(base64_image: str) -> Image.Image:
    pil_image = Image.open(io.BytesIO(base64.b64decode(base64_image))).convert("RGB")
    return pil_image

to

def decode_base64_to_image(base64_image: str) -> Image.Image:
    base64_image = base64_image.split(',', maxsplit=1)[1]
    pil_image = Image.open(io.BytesIO(base64.b64decode(base64_image))).convert("RGB")
    return pil_image