Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struct heif_decoding_options: wrong total size #92

Open
hamzabidi opened this issue Aug 10, 2023 · 10 comments
Open

Struct heif_decoding_options: wrong total size #92

hamzabidi opened this issue Aug 10, 2023 · 10 comments

Comments

@hamzabidi
Copy link

hamzabidi commented Aug 10, 2023

In a fastapi project, i have this method:

   @staticmethod
    def ios_image_converter(file: UploadFile) -> Tuple[UploadFile, str]:
        # source
        source_extension = 'heic'
        source_content_type = 'image/heif'
       
       # target
        target_extension = 'jpg'
        target_format = 'JPEG'
        target_content_type = 'image/jpeg'

        # source type checking
        if file.content_type != source_content_type:
            raise Exception(f"expected file type 'image/heif', got {file.content_type}")

        # converting
        heif_file = pyheif.read(file.file.read())
        image = Image.frombytes(
            heif_file.mode,
            heif_file.size,
            heif_file.data,
            "raw",
            heif_file.mode,
            heif_file.stride
        )

        io = BytesIO()
        image.save(io, format=target_format)
        io.seek(0)

        # saving
        upload_file = UploadFile(io)
        upload_file.filename = file.filename.lower().replace(f'.{source_extension}', f'.{target_extension}')

        return upload_file, target_content_type

When I run it locally (ubuntu 22 LTS), I get no errors. But when I deploy it on a container based on the python:3.8-alpine image, I get this error:

File '/home/python/app/src/api/api_v1/endpoints/dossier.py', line 195, in dossier_piece_post file, content_type = FileService.ios_image_converter(file) File '/home/python/app/src/api/api_v1/services/FileService.py', line 57, in ios_image_converter heif_file = pyheif.read(file.file.read()) File '/usr/local/lib/python3.8/site-packages/pyheif/reader.py', line 103, in read return heif_file.load() File '/usr/local/lib/python3.8/site-packages/pyheif/reader.py', line 47, in load self.data, self.stride = _read_heif_image(self._heif_handle, self) File '/usr/local/lib/python3.8/site-packages/pyheif/reader.py', line 402, in _read_heif_image p_options.ignore_transformations = int(not heif_file.apply_transformations) ffi.error: struct heif_decoding_options: wrong total size (cdef says 48, but C compiler says 72). fix it or use '...;' as the last field in the cdef for struct heif_decoding_options to make it flexible

installed libs on my alpine pods:

libheif-1.16.2-r0
libheif-dev-1.16.2-r0

Any help please !

@Cyberfit
Copy link

I'm having the same issue running this on macOS py3.11.5

struct heif_decoding_options: wrong total size (cdef says 48, but C compiler says 72). fix it or use "...;" as the last field in the cdef for struct heif_decoding_options to make it flexible

@peterlauri
Copy link

I'm having same problem as CyberFit.

➜   brew info libffi
==> libffi: stable 3.4.4 (bottled), HEAD [keg-only]
Portable Foreign Function Interface library
https://sourceware.org/libffi/
/opt/homebrew/Cellar/libffi/3.4.4 (17 files, 724.8KB)
  Poured from bottle using the formulae.brew.sh API on 2023-08-15 at 08:48:22
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/lib/libffi.rb
License: MIT
==> Options
--HEAD
	Install HEAD version
==> Caveats
libffi is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"

For pkg-config to find libffi you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"
==> Analytics
install: 27,321 (30 days), 71,475 (90 days), 188,609 (365 days)
install-on-request: 6,790 (30 days), 17,520 (90 days), 43,862 (365 days)
build-error: 1 (30 days)
==> libheif: stable 1.16.2 (bottled)
ISO/IEC 23008-12:2017 HEIF file format decoder and encoder
https://www.libde265.org/
/opt/homebrew/Cellar/libheif/1.16.2 (27 files, 3.2MB) *
  Poured from bottle using the formulae.brew.sh API on 2023-08-15 at 08:48:29
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/lib/libheif.rb
License: LGPL-3.0-only
==> Dependencies
Build: cmake ✔, pkg-config ✔
Required: aom ✔, jpeg-turbo ✔, libde265 ✔, libpng ✔, shared-mime-info ✔, x265 ✔
==> Analytics
install: 26,975 (30 days), 75,270 (90 days), 252,115 (365 days)
install-on-request: 13,098 (30 days), 37,676 (90 days), 136,666 (365 days)
build-error: 0 (30 days)
➜   python --version
Python 3.11.5

@michaelrhanson
Copy link

michaelrhanson commented Oct 24, 2023

Same error on slightly older Python. The file in question is a recent HEIC from an iPhone running iOS 16.6.1.

ffi.error: struct heif_decoding_options: wrong total size (cdef says 48, but C compiler says 72). fix it or use "...;" as the last field in the cdef for struct heif_decoding_options to make it flexible
$ brew info libffi
==> libffi: stable 3.4.4 (bottled), HEAD [keg-only]
Portable Foreign Function Interface library
https://sourceware.org/libffi/
/opt/homebrew/Cellar/libffi/3.4.4 (17 files, 724.8KB)
  Poured from bottle using the formulae.brew.sh API on 2023-04-24 at 09:35:09
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/lib/libffi.rb
License: MIT
==> Options
--HEAD
	Install HEAD version
==> Caveats
libffi is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"

For pkg-config to find libffi you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"
$ brew info libheif
==> libheif: stable 1.16.2 (bottled)
ISO/IEC 23008-12:2017 HEIF file format decoder and encoder
https://www.libde265.org/
/opt/homebrew/Cellar/libheif/1.16.2 (27 files, 3.2MB) *
  Poured from bottle using the formulae.brew.sh API on 2023-10-10 at 08:04:32
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/lib/libheif.rb
License: LGPL-3.0-only
==> Dependencies
Build: cmake ✘, pkg-config ✔
Required: aom ✔, jpeg-turbo ✔, libde265 ✔, libpng ✔, shared-mime-info ✔, x265 ✔
$ python --version
Python 3.10.12

@michaelrhanson
Copy link

michaelrhanson commented Oct 24, 2023

This is probably a duplicate of #84 -- installing from master as directed in that issue resolves the problem.

@davidcz95
Copy link

This is probably a duplicate of #84 -- installing from master as directed in that issue resolves the problem.

when installing from master on M1 old error has returned fatal error: 'libheif/heif.h' file not foun i can install it through pip install pyheif but then Struct heif_decoding_options: wrong total size occurs

@derSoerrn95
Copy link

I have the same problem as @davidcz95

@malekinho8
Copy link

For anyone still on this thread, I found at least a temporary workaround using the pillow_heif module.

from pillow_heif import register_heif_opener
from PIL import Image

register_heif_opener()

def load_heic_image(heic_file_path):
    # obtain the image data
    image = Image.open(heic_file_path)
    return image
    
# Replace with your HEIC file path
heic_file_path = 'foo.heic'
image = load_heic_image(heic_file_path)

Hope this helps.

@lufte
Copy link

lufte commented Jan 18, 2024

Another workaround (installing from this repo didn't work for me because it would try to build against an incompatible version of libheif) is to downgrade to Python 3.11. I had upgraded to Python 3.12 but there is no pyheif wheel for it.

@AbidiHamza84
Copy link

AbidiHamza84 commented Mar 1, 2024

I finally found another way to do it !

`
from io import BytesIO
from typing import Final

from PIL import Image
from fastapi import UploadFile, File
from pillow_heif import register_heif_opener
from starlette.datastructures import Headers

from src.utils.mimes_type_enum import MimeTypeEnum

SOURCE_EXTENSION: Final[str] = 'heic'
SOURCE_CONTENT_TYPE: Final[MimeTypeEnum] = MimeTypeEnum.HEIC
TARGET_EXTENSION: Final[str] = 'png'
TARGET_FORMAT: Final[str] = 'PNG'
TARGET_CONTENT_TYPE: Final[MimeTypeEnum] = MimeTypeEnum.PNG

async def convert_to_png(file: UploadFile) -> UploadFile:
# source type checking
if file.content_type != SOURCE_CONTENT_TYPE.value:
raise Exception(f"expected file type {SOURCE_CONTENT_TYPE.value}, got {file.content_type}")

register_heif_opener()

with Image.open(file.file) as image:
    io = BytesIO()
    image.save(io, format=TARGET_FORMAT)
    io.seek(0)

# saving
upload_file = UploadFile(
    io,
    filename=file.filename.lower().replace(f'.{SOURCE_EXTENSION}', f'.{TARGET_EXTENSION}'),
    headers=Headers({'Content-Type': TARGET_CONTENT_TYPE.value})
)

return upload_file

`

I use the register_heif_opener() function to registers a Pillow plugin for HEIF format. To get it, you will need to install the pillow-heif lib pip install pillow-heif.

Thank you @malekinho8 for the idea ;)

@mzahidriaz
Copy link

I finally found another way to do it !

` from io import BytesIO from typing import Final

from PIL import Image from fastapi import UploadFile, File from pillow_heif import register_heif_opener from starlette.datastructures import Headers

from src.utils.mimes_type_enum import MimeTypeEnum

SOURCE_EXTENSION: Final[str] = 'heic' SOURCE_CONTENT_TYPE: Final[MimeTypeEnum] = MimeTypeEnum.HEIC TARGET_EXTENSION: Final[str] = 'png' TARGET_FORMAT: Final[str] = 'PNG' TARGET_CONTENT_TYPE: Final[MimeTypeEnum] = MimeTypeEnum.PNG

async def convert_to_png(file: UploadFile) -> UploadFile: # source type checking if file.content_type != SOURCE_CONTENT_TYPE.value: raise Exception(f"expected file type {SOURCE_CONTENT_TYPE.value}, got {file.content_type}")

register_heif_opener()

with Image.open(file.file) as image:
    io = BytesIO()
    image.save(io, format=TARGET_FORMAT)
    io.seek(0)

# saving
upload_file = UploadFile(
    io,
    filename=file.filename.lower().replace(f'.{SOURCE_EXTENSION}', f'.{TARGET_EXTENSION}'),
    headers=Headers({'Content-Type': TARGET_CONTENT_TYPE.value})
)

return upload_file

`

I use the register_heif_opener() function to registers a Pillow plugin for HEIF format. To get it, you will need to install the pillow-heif lib pip install pillow-heif.

Thank you @malekinho8 for the idea ;)

This worked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants