Opened 6 years ago

Closed 5 years ago

Last modified 9 months ago

#14909 closed enhancement (no change required)

Translator for HEIC - High Efficiency Image File Format

Reported by: vercu Owned by: nobody
Priority: low Milestone: Unscheduled
Component: Add-Ons/Translators Version: R1/Development
Keywords: heic heif Cc:
Blocked By: Blocking:
Platform: All

Description

The heic format is used on newer iPhones for storing pictures. Native support in Haiku would be nice to have.

Change History (5)

comment:1 by cb88, 6 years ago

https://github.com/strukturag/libheif

Note HEIC is a container format. When it contains HVEC encoded images it is patent encumbered and may require a license. HEIC can also contain other codecs like AV1 however.

comment:2 by vercu, 6 years ago

From the wiki page: In Apple's implementation, for single images they have chosen the latter .heic filename extension as the only one they will produce for photos, which indicates clearly that it went through HEVC encoding. heif is supported by Gimp, ImageMagick and Krita among others. It is not enabled in the Haiku Krita port. ImageMagick did not work here. But maybe I am doing something wrong.

comment:3 by cb88, 6 years ago

"which indicates clearly that it went through HEVC encoding."

Not sure why you think that... JPEG in a HEIC container is still called .heic In that respect it is similar for instance MKV which can contain a variety of codecs.

Surely it probably is HEVC on an iPhone, but that isn't a given.

comment:4 by pulkomandy, 5 years ago

Resolution: no change required
Status: newclosed

This can be implemented as a 3rd party translator if needed.

comment:5 by smallstepforman, 9 months ago

For an unrelated project, I have managed to get HEIC decoding using libheif which is included in Haiku. In essence, the code is as simple as this:

static BBitmap *LoadHeic(const char *path)
{
    //  Check MIME type
    FILE *f = fopen(path, "rb");
    if (!f)
    {
        printf("Error opening %s\n", path);
        return nullptr;
    }
    uint8_t buffer[12];
    fread(buffer, 12, 1, f);
    fclose(f);
    //printf("MIME = %s\n", heif_get_file_mime_type(buffer, 12));
    //  TODO validate against image/...

    //  Load file
    heif_context* ctx = heif_context_alloc();
    heif_context_read_from_file(ctx, path, nullptr);
    // get a handle to the primary image
    heif_image_handle* handle;
    heif_context_get_primary_image_handle(ctx, &handle);

    // decode the image and convert colorspace to RGB, saved as 24bit interleaved
    heif_image* img;
    heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, nullptr);

    int stride;
    const uint8_t* data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
    int width = heif_image_get_primary_width(img);
    int height = heif_image_get_primary_height(img);
    //printf("Size(%d x %d), stride=%d\n", width, height, stride);

    BBitmap *bitmap = new BBitmap(BRect(0, 0, width-1, height-1), B_RGBA32);
    bitmap->Lock();
    uint8 *dest = (uint8 *)bitmap->Bits();
    //  Convert BGRA to RGBA
    const uint8 *src = data;
#if 1
    for (int y=0; y < height; y++)
    {
        for (int x=0; x<width; x++)
        {
            uint8 r=*src++;
            uint8 g=*src++;
            uint8 b=*src++;
            uint8 a=*src++;
            *dest++ = b;
            *dest++ = g;
            *dest++ = r;
            *dest++ = a;
            dest += stride-(width*4);
        }
    }
#else
    memcpy(dest, src, stride*height);
#endif
    bitmap->Unlock();

    // clean up resources
    heif_image_release(img);
    heif_image_handle_release(handle);
    heif_context_free(ctx);

    return bitmap;
}

It shows how to sniff the MIME type, load the image, convert GBR<->RGB, and export a BBitmap. The conversions are a bit slow, but it works.

Version 0, edited 9 months ago by smallstepforman (next)
Note: See TracTickets for help on using tickets.