Skip to content

Skip failing records when rendering WMF images - #8506

Merged
hugovk merged 6 commits into
python-pillow:mainfrom
radarhere:emf_records
Mar 29, 2025
Merged

hugovk merged 6 commits into
python-pillow:mainfrom
radarhere:emf_records

Conversation

@radarhere

Copy link
Copy Markdown
Member

Resolves #6980

The issue would like Pillow to be more lenient when rendering invalid EMF files. The API that raises the error is relatively simple

Pillow/src/display.c

Lines 799 to 800 in 81a3bf5

if (!PlayEnhMetaFile(dc, meta, &rect)) {
PyErr_SetString(PyExc_OSError, "cannot render metafile");

so I asked about it at https://learn.microsoft.com/en-us/answers/questions/2100252/playenhmetafile-fails-without-any-getlasterror-res, and the answer showed that PlayEnhMetaFileRecord can be used to render the image gradually, skipping failing records.

@petsuter

Copy link
Copy Markdown

Great! As mentioned in the ticket, the C# .NET implementation also uses such record-by-record API's internally and allows the files to be handled, so I wouldn't hesitate to do the same. Also programs like Windows Paint and IrfanView allow the files to be opened without error.👍

@radarhere
radarhere force-pushed the emf_records branch 2 times, most recently from ee84978 to e4087f9 Compare October 26, 2024 11:33
@radarhere

Copy link
Copy Markdown
Member Author

It turns out my initial commit didn't work on 32-bit Windows - https://ci.appveyor.com/project/Python-pillow/pillow/builds/50869937/job/3jd42o23cjses7ms#L3048

src/display.c(807): error C2440: 'function': cannot convert from 'BOOL (__cdecl *)(HDC,HANDLETABLE *,const ENHMETARECORD *,int,LPARAM)' to 'ENHMFENUMPROC'

I've pushed a commit to only use the new behaviour on 64-bit. @petsuter is that sufficient to resolve your issue? Or would you like to see this work on 32-bit as well?

@radarhere radarhere changed the title Skip failing records when rendering WMF images Skip failing records when rendering WMF images on 64-bit Oct 26, 2024
@petsuter

Copy link
Copy Markdown

I don't know of any 32-bit Python usage anymore, thanks.

(Could it be the return value should be int not BOOL? https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nc-wingdi-enhmfenumproc)

@radarhere

Copy link
Copy Markdown
Member Author

Thanks.

No, changing it to int still gives https://ci.appveyor.com/project/radarhere/pillow/builds/50870384/job/ji4kbtk94gl000q3#L3047

src/display.c(807): error C2440: 'function': cannot convert from 'int (__cdecl *)(HDC,HANDLETABLE *,const ENHMETARECORD *,int,LPARAM)' to 'ENHMFENUMPROC'

Comment thread src/display.c Outdated

BOOL
enhMetaFileProc(
HDC hdc, HANDLETABLE FAR *lpht, const ENHMETARECORD *lpmr, int nHandles, LPARAM data

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why a FAR pointer?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/display.c Outdated
@radarhere radarhere changed the title Skip failing records when rendering WMF images on 64-bit Skip failing records when rendering WMF images Dec 27, 2024
Skip failing WMF records on 32-bit Windows
@hugovk
hugovk merged commit 2579973 into python-pillow:main Mar 29, 2025
@radarhere
radarhere deleted the emf_records branch March 29, 2025 20:18
@aclark4life aclark4life added the WMF Windows Metafile / Enhanced Metafile (WMF/EMF) label Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Windows WMF Windows Metafile / Enhanced Metafile (WMF/EMF)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EMF files: OSError: cannot render metafile

6 participants