mirror of
https://github.com/Nyx0uf/qlImageSize.git
synced 2026-02-26 18:24:15 +01:00
136 lines
3.4 KiB
Objective-C
136 lines
3.4 KiB
Objective-C
//
|
|
// bpg_decode.m
|
|
// qlImageSize
|
|
//
|
|
// Created by @Nyx0uf on 30/12/14.
|
|
// Copyright (c) 2014 Nyx0uf. All rights reserved.
|
|
//
|
|
|
|
|
|
#import "bpg_decode.h"
|
|
#import "libbpg.h"
|
|
|
|
|
|
#ifdef NYX_QL_SUPPORT_BPG_DECODE
|
|
CF_RETURNS_RETAINED CGImageRef decode_bpg_at_path(CFStringRef filepath, image_infos* infos)
|
|
{
|
|
// Read file
|
|
uint8_t* buffer = NULL;
|
|
const size_t file_size = read_file(filepath, &buffer);
|
|
if (0 == file_size)
|
|
{
|
|
free(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
// Decode image
|
|
BPGDecoderContext* bpg_ctx = bpg_decoder_open();
|
|
int ret = bpg_decoder_decode(bpg_ctx, buffer, (int)file_size);
|
|
free(buffer);
|
|
if (ret < 0)
|
|
{
|
|
bpg_decoder_close(bpg_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
// Get image infos
|
|
BPGImageInfo img_info_s, *img_info = &img_info_s;
|
|
bpg_decoder_get_info(bpg_ctx, img_info);
|
|
const size_t w = (size_t)img_info->width;
|
|
const size_t h = (size_t)img_info->height;
|
|
|
|
// Choose output colorspace (RGB / RGBA)
|
|
const size_t num_c = img_info->has_alpha ? 4 : 3;
|
|
const size_t stride = num_c * w;
|
|
const size_t img_size = stride * h;
|
|
uint8_t* rgb_buffer = (uint8_t*)malloc(img_size);
|
|
size_t idx = 0;
|
|
bpg_decoder_start(bpg_ctx, img_info->has_alpha ? BPG_OUTPUT_FORMAT_RGBA32 : BPG_OUTPUT_FORMAT_RGB24);
|
|
for (size_t y = 0; y < h; y++)
|
|
{
|
|
bpg_decoder_get_line(bpg_ctx, rgb_buffer + idx);
|
|
idx += stride;
|
|
}
|
|
bpg_decoder_close(bpg_ctx);
|
|
|
|
if (infos != NULL)
|
|
{
|
|
infos->width = w;
|
|
infos->height = h;
|
|
infos->filesize = file_size;
|
|
}
|
|
|
|
// Create CGImage
|
|
CGDataProviderRef data_provider = CGDataProviderCreateWithData(NULL, rgb_buffer, img_size, NULL);
|
|
if (data_provider == NULL)
|
|
{
|
|
free(rgb_buffer);
|
|
return NULL;
|
|
}
|
|
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
|
|
CGImageRef img_ref = CGImageCreate(w, h, 8, 8 * num_c, stride, color_space, kCGBitmapByteOrderDefault | ((img_info->has_alpha) ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNone), data_provider, NULL, true, kCGRenderingIntentDefault);
|
|
CGColorSpaceRelease(color_space);
|
|
CGDataProviderRelease(data_provider);
|
|
free(rgb_buffer);
|
|
return img_ref;
|
|
}
|
|
#endif /* NYX_QL_SUPPORT_BPG_DECODE */
|
|
|
|
#ifdef NYX_MD_SUPPORT_BPG_DECODE
|
|
bool get_bpg_informations_for_filepath(CFStringRef filepath, image_infos* infos)
|
|
{
|
|
// Read file
|
|
uint8_t* buffer = NULL;
|
|
const size_t size = read_file(filepath, &buffer);
|
|
if (0 == size)
|
|
{
|
|
free(buffer);
|
|
return false;
|
|
}
|
|
|
|
// Decode image
|
|
BPGDecoderContext* bpg_ctx = bpg_decoder_open();
|
|
int ret = bpg_decoder_decode(bpg_ctx, buffer, (int)size);
|
|
free(buffer);
|
|
if (ret < 0)
|
|
{
|
|
bpg_decoder_close(bpg_ctx);
|
|
return false;
|
|
}
|
|
|
|
// Get image infos
|
|
BPGImageInfo img_info_s, *img_info = &img_info_s;
|
|
bpg_decoder_get_info(bpg_ctx, img_info);
|
|
infos->width = (size_t)img_info->width;
|
|
infos->height = (size_t)img_info->height;
|
|
infos->has_alpha = (uint8_t)img_info->has_alpha;
|
|
infos->bit_depth = (uint8_t)img_info->bit_depth;
|
|
colorspace_t cs = colorspace_unknown;
|
|
const BPGColorSpaceEnum color_space = (BPGColorSpaceEnum)img_info->color_space;
|
|
switch (color_space)
|
|
{
|
|
case BPG_CS_RGB:
|
|
cs = colorspace_rgb;
|
|
break;
|
|
case BPG_CS_YCbCr:
|
|
cs = colorspace_ycbcr;
|
|
break;
|
|
case BPG_CS_YCgCo:
|
|
cs = colorspace_ycgco;
|
|
break;
|
|
case BPG_CS_YCbCr_BT709:
|
|
cs = colorspace_bt709;
|
|
break;
|
|
case BPG_CS_YCbCr_BT2020:
|
|
cs = colorspace_bt2020;
|
|
break;
|
|
default:
|
|
cs = colorspace_unknown;
|
|
}
|
|
infos->colorspace = cs;
|
|
bpg_decoder_close(bpg_ctx);
|
|
|
|
return true;
|
|
}
|
|
#endif /* NYX_MD_SUPPORT_BPG_DECODE */
|