mirror of
https://bitbucket.org/King_DuckZ/jumping-in-d.git
synced 2024-10-30 02:49:01 +00:00
110 lines
4 KiB
D
110 lines
4 KiB
D
/* Copyright 2015, Michele Santullo
|
|
* This file is part of "Jumping in D".
|
|
*
|
|
* "Jumping in D" is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* "Jumping in D" is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with "Jumping in D". If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
module bpg;
|
|
import std.stdint;
|
|
import std.array;
|
|
|
|
//Define structs as in the c header file (libbpg.h)
|
|
struct BPGDecoderContext;
|
|
|
|
struct BPGExtensionData {
|
|
BPGExtensionTagEnum tag;
|
|
uint32_t buf_len;
|
|
uint8_t *buf;
|
|
BPGExtensionData* next;
|
|
}
|
|
|
|
struct BPGImageInfo {
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint8_t format; /* see BPGImageFormatEnum */
|
|
uint8_t has_alpha; /* TRUE if an alpha plane is present */
|
|
uint8_t color_space; /* see BPGColorSpaceEnum */
|
|
uint8_t bit_depth;
|
|
uint8_t premultiplied_alpha; /* TRUE if the color is alpha premultiplied */
|
|
uint8_t has_w_plane; /* TRUE if a W plane is present (for CMYK encoding) */
|
|
uint8_t limited_range; /* TRUE if limited range for the color */
|
|
uint8_t has_animation; /* TRUE if the image contains animations */
|
|
uint16_t loop_count; /* animations: number of loop, 0 = infinity */
|
|
}
|
|
|
|
//Just a convenience struct to return the uncompressed image and its size
|
|
struct DecodedBPGImage {
|
|
ubyte[] data;
|
|
int width;
|
|
int height;
|
|
}
|
|
|
|
//Enums, as defined in the c header (libbpg.h)
|
|
enum BPGDecoderOutputFormat : int {
|
|
BPG_OUTPUT_FORMAT_RGB24,
|
|
BPG_OUTPUT_FORMAT_RGBA32, /* not premultiplied alpha */
|
|
BPG_OUTPUT_FORMAT_RGB48,
|
|
BPG_OUTPUT_FORMAT_RGBA64, /* not premultiplied alpha */
|
|
BPG_OUTPUT_FORMAT_CMYK32,
|
|
BPG_OUTPUT_FORMAT_CMYK64,
|
|
};
|
|
|
|
enum BPGExtensionTagEnum : int {
|
|
BPG_EXTENSION_TAG_EXIF = 1,
|
|
BPG_EXTENSION_TAG_ICCP = 2,
|
|
BPG_EXTENSION_TAG_XMP = 3,
|
|
BPG_EXTENSION_TAG_THUMBNAIL = 4,
|
|
BPG_EXTENSION_TAG_ANIM_CONTROL = 5,
|
|
};
|
|
|
|
//Declaration of the c functions
|
|
private extern (C) BPGDecoderContext* bpg_decoder_open();
|
|
private extern (C) int bpg_decoder_keep_extension_data (BPGDecoderContext* s, int enable);
|
|
private extern (C) int bpg_decoder_decode (BPGDecoderContext* s, const uint8_t* buf, int buf_len);
|
|
private extern (C) BPGExtensionData bpg_decoder_get_extension_data (BPGDecoderContext* s);
|
|
private extern (C) int bpg_decoder_get_info (BPGDecoderContext* s, BPGImageInfo* p);
|
|
private extern (C) void bpg_decoder_close (BPGDecoderContext* s);
|
|
private extern (C) void bpg_decoder_free_extension_data (BPGExtensionData* first_md);
|
|
private extern (C) int bpg_decoder_start (BPGDecoderContext* s, BPGDecoderOutputFormat out_fmt);
|
|
private extern (C) int bpg_decoder_get_line (BPGDecoderContext* s, void* buf);
|
|
|
|
//Use the c functions to decode the compressed data in parData.
|
|
//This function does just that, and only returns 24 bit images.
|
|
public DecodedBPGImage decode_bpg_image (const(char)[] parData) {
|
|
auto context = bpg_decoder_open();
|
|
scope(exit) bpg_decoder_close(context);
|
|
|
|
if (bpg_decoder_decode(context, cast(ubyte*)parData.ptr, cast(int)parData.length) < 0) {
|
|
throw new Exception("Could not decode image");
|
|
}
|
|
|
|
BPGImageInfo img_info;
|
|
bpg_decoder_get_info(context, &img_info);
|
|
ubyte[] rgbline = new ubyte[img_info.width * 3];
|
|
ubyte[] retdata;
|
|
retdata.reserve(img_info.width * 3 * img_info.height);
|
|
|
|
bpg_decoder_start(context, BPGDecoderOutputFormat.BPG_OUTPUT_FORMAT_RGB24);
|
|
for (auto z = 0; z < img_info.height; ++z) {
|
|
bpg_decoder_get_line(context, rgbline.ptr);
|
|
retdata ~= rgbline;
|
|
}
|
|
assert(img_info.width * 3 * img_info.height == retdata.length);
|
|
|
|
DecodedBPGImage retval;
|
|
retval.width = img_info.width;
|
|
retval.height = img_info.height;
|
|
retval.data = retdata;
|
|
return retval;
|
|
}
|