qoi_pipe decoding support
This commit is contained in:
parent
87de9b6df3
commit
12893ac743
2
external/solanaceae_tox
vendored
2
external/solanaceae_tox
vendored
@ -1 +1 @@
|
||||
Subproject commit ec926dcb95be38e22a4b2ddc0c5cd5d14eb3a6b7
|
||||
Subproject commit 178f08ee9617bd89e12bb16163a56ec4cafcf012
|
@ -1,10 +1,72 @@
|
||||
#include "./image_loader_qoi.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <qoi/qoi.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define QOI_HEADER_SIZE 14
|
||||
|
||||
// true if data looks like qoi
|
||||
static bool probe_qoi(const uint8_t* data, int64_t data_size) {
|
||||
// smallest possible qoi
|
||||
// magic
|
||||
// dims (w h)
|
||||
// chan
|
||||
// col
|
||||
if (data_size < QOI_HEADER_SIZE+8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
data[0] != 'q' ||
|
||||
data[1] != 'o' ||
|
||||
data[2] != 'i' ||
|
||||
data[3] != 'f'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// every qoi ends with 0,0,0,0,0,0,0,1
|
||||
// returns the index for the first byte after padding (aka the size of the qoi)
|
||||
static int64_t probe_qoi_padding(const uint8_t* data, int64_t data_size) {
|
||||
assert(data);
|
||||
assert(data_size >= 8);
|
||||
|
||||
// loop checks if 0x00 or 0x01, otherwise skips 2
|
||||
// we start at the last possible first position
|
||||
for (int64_t pos = 7; pos < data_size;) {
|
||||
if (data[pos] == 0x00) {
|
||||
pos += 1; // not last char in padding, but we might be in the padding
|
||||
} else if (data[pos] == 0x01) {
|
||||
// last char from padding
|
||||
if (
|
||||
data[pos-7] == 0x00 &&
|
||||
data[pos-6] == 0x00 &&
|
||||
data[pos-5] == 0x00 &&
|
||||
data[pos-4] == 0x00 &&
|
||||
data[pos-3] == 0x00 &&
|
||||
data[pos-2] == 0x00 &&
|
||||
data[pos-1] == 0x00
|
||||
) {
|
||||
//return pos - 7; // first byte of padding
|
||||
return pos+1;
|
||||
} else {
|
||||
pos += 8; // cant be last byte for another 7
|
||||
}
|
||||
} else {
|
||||
pos += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
ImageLoaderQOI::ImageInfo ImageLoaderQOI::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) {
|
||||
ImageInfo res;
|
||||
|
||||
@ -26,24 +88,46 @@ ImageLoaderQOI::ImageInfo ImageLoaderQOI::loadInfoFromMemory(const uint8_t* data
|
||||
ImageLoaderQOI::ImageResult ImageLoaderQOI::loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) {
|
||||
ImageResult res;
|
||||
|
||||
qoi_desc desc;
|
||||
|
||||
uint8_t* img_data = static_cast<uint8_t*>(
|
||||
qoi_decode(data, data_size, &desc, 4)
|
||||
);
|
||||
if (img_data == nullptr) {
|
||||
// not readable
|
||||
if (!probe_qoi(data, data_size)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res.width = desc.width;
|
||||
res.height = desc.height;
|
||||
for (size_t data_pos = 0; data_pos < data_size;) {
|
||||
const auto qoi_size = probe_qoi_padding(data+data_pos, data_size-data_pos);
|
||||
if (qoi_size < QOI_HEADER_SIZE+8) {
|
||||
// too small
|
||||
break;
|
||||
}
|
||||
|
||||
auto& new_frame = res.frames.emplace_back();
|
||||
new_frame.ms = 0;
|
||||
new_frame.data = {img_data, img_data+(desc.width*desc.height*4)};
|
||||
qoi_desc desc;
|
||||
|
||||
uint8_t* img_data = static_cast<uint8_t*>(
|
||||
qoi_decode(data + data_pos, qoi_size, &desc, 4)
|
||||
);
|
||||
if (img_data == nullptr) {
|
||||
// not readable
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res.width == 0 || res.height == 0) {
|
||||
res.width = desc.width;
|
||||
res.height = desc.height;
|
||||
}
|
||||
|
||||
if (res.width == desc.width && res.height == desc.height) {
|
||||
auto& new_frame = res.frames.emplace_back();
|
||||
new_frame.ms = 25; // ffmpeg default
|
||||
new_frame.data = {img_data, img_data+(desc.width*desc.height*4)};
|
||||
} else {
|
||||
// dim mismatch, what do we do? abort, continue?
|
||||
data_pos = data_size; // force exit loop
|
||||
}
|
||||
|
||||
free(img_data);
|
||||
|
||||
data_pos += qoi_size;
|
||||
}
|
||||
|
||||
free(img_data);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user