modelscope / modelscope/ms-swift

`decode_base64_to_image_file` fails on CMYK images — silently drops an entire dataset (e.g. SEEDBench_IMG_KO)

Open Beginner friendly
#10,095 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
15.7k
Forks
1.7k
Avg merge
1d 16h
Merged PRs (30d)
136

Description

Checklist / 检查清单
  • I have searched existing issues, and this is a new bug report. / 我已经搜索过现有的 issues,确认这是一个新的 bug report。
Bug Description / Bug 描述
Summary

decode_base64_to_image() normalizes only three image modes before the caller writes the file as PNG, so any dataset containing a CMYK image raises OSError: cannot write mode CMYK as PNG. Because run.py catches per-dataset exceptions and still exits 0, the affected dataset produces no prediction file, no score, and no non-zero exit code — it simply disappears from the results.

Reproduced on main @ d21c5e9, Pillow 12.3.0.

Location

vlmeval/smp/vlm.py:156-171

def decode_base64_to_image(base64_string, target_size=-1):
    image_data = base64.b64decode(base64_string)
    image = Image.open(io.BytesIO(image_data))
    if image.mode in ('RGBA', 'P', 'LA'):      # <-- incomplete
        image = image.convert('RGB')
    ...

def decode_base64_to_image_file(base64_string, image_path, target_size=-1):
    image = decode_base64_to_image(base64_string, target_size=target_size)
    ...
    image.save(image_path)                     # format inferred from .png suffix

The conversion list enumerates three modes, but the set PNG cannot encode is larger. Verified with Pillow 12.3.0:

PNG accepts PNG rejects (OSError: cannot write mode X as PNG)
1 L LA I I;16 P RGB RGBA PA CMYK YCbCr LAB HSV F

CMYK and YCbCr are both native JPEG modes, so either can appear in any base64-encoded dataset. PA is also rejected despite resembling a palette mode.

Reproduction
from PIL import Image
import base64, io
from vlmeval.smp.vlm import decode_base64_to_image_file

buf = io.BytesIO()
Image.new('CMYK', (32, 32)).save(buf, format='JPEG')   # valid CMYK JPEG
b64 = base64.b64encode(buf.getvalue()).decode()

decode_base64_to_image_file(b64, '/tmp/x.png')
# OSError: cannot write mode CMYK as PNG

Real-world trigger: SEEDBench_IMG_KO (NCSOFT/K-SEED) contains CMYK images. Evaluating it produces:

[dataset] SEEDBench_IMG_KO ... cannot write mode CMYK as PNG

and then the run continues to completion with exit code 0, leaving that benchmark absent from the report. The failure mode is easy to miss: status.json records an error_message, but nothing else signals that a 14k-sample benchmark was dropped.

Suggested fix

Convert whenever the mode is not PNG-encodable, rather than listing three cases:

 def decode_base64_to_image(base64_string, target_size=-1):
     image_data = base64.b64decode(base64_string)
     image = Image.open(io.BytesIO(image_data))
-    if image.mode in ('RGBA', 'P', 'LA'):
+    # PNG cannot encode PA/CMYK/YCbCr/LAB/HSV/F; CMYK and YCbCr are native
+    # JPEG modes and do occur in released datasets.
+    if image.mode not in ('1', 'L', 'LA', 'I', 'I;16', 'P', 'RGB', 'RGBA'):
         image = image.convert('RGB')
     if target_size > 0:
         image.thumbnail((target_size, target_size))
     return image

Keeping P/LA unconverted preserves current behaviour for the modes PNG supports; only the genuinely unsupported ones are coerced.

Two adjacent points, if useful:

  • encode_image_to_base64(..., fmt='JPEG') has the mirror problem: JPEG cannot encode RGBA/LA/P alpha modes.
  • Independently of this bug, a dataset that raises during inference currently yields a clean exit. Surfacing a non-zero exit, or a summary line naming datasets that produced no prediction, would make failures like this visible at the point they happen rather than when someone notices a gap in the results table.
Environment
  • VLMEvalKit main @ d21c5e9
  • Pillow 12.3.0
  • Observed while evaluating a local model over SEEDBench_IMG_KO via --mode infer
How to Reproduce / 如何复现

from vlmeval.api import LMDeployAPI # run.py:653 (get_api_model_class default)
from vlmeval.dataset import build_dataset # dataset/init.py:402
from vlmeval.inference import infer_data_job # inference.py:210
from vlmeval.smp import get_pred_file_path # smp/file.py:208

WORK, MODEL, DS = 'outputs/manual/9b/T-manual', '9b', 'SEEDBench_IMG_KO'

dataset = build_dataset(DS) # resolves name -> class
model = LMDeployAPI(model=MODEL, # run.py:281-284
api_base='http://127.0.0.1:8000/v1/chat/completions',
key='sk-admin', max_tokens=2048, temperature=0.0)

result_file = get_pred_file_path(WORK, MODEL, DS) # /9b_.xlsx
infer_data_job(model, work_dir=WORK, model_name=MODEL, # writes result_file
dataset=dataset, verbose=True, api_nproc=64)

print(dataset.evaluate(result_file, model='exact_matching', # returns the metrics
nproc=4, verbose=True))

Additional Information / 补充信息

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in vlmeval/smp/vlm.py:156-171, then run the CMYK reproduction through decode_base64_to_image_file. Update the mode handling so unsupported PNG modes are converted while existing PNG-compatible modes retain their behavior. Done means CMYK and other listed unsupported modes can be written as PNG without OSError, while the provided reproduction succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-vision
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.