QNT: Calculate decompression buffers exactly

Round image dimensions up to even values for QNT's 2x2 pixel blocks, and
use the resulting exact size for pixel and alpha decompression.

Verification against Only You Re Cross's QNT files confirmed that the
former 1164-byte discrepancy is odd-height padding, not extra zlib
output. Remove the obsolete fixed margin.
This commit is contained in:
kichikuou
2026-07-10 08:54:19 +09:00
parent bc37ba6256
commit 5c827225ab
+13 -11
View File
@@ -40,11 +40,13 @@
#include "qnt.h"
#include "system.h"
/*
zlib の展開バッファで、幅×高さ×3に、さらにどれくらい余裕をとるか
(リクルスで 1164バイトというのがあった)
*/
#define ZLIBBUF_MARGIN 5*1024
// QNT compressed data is arranged in 2x2 pixel blocks, so odd dimensions
// are decompressed through the next even width or height.
static long zlibbuf_size(qnt_header *qnt, int bytes_per_pixel) {
long width = (qnt->width + 1) & ~1;
long height = (qnt->height + 1) & ~1;
return width * height * bytes_per_pixel;
}
/*
Get information from header
@@ -86,8 +88,8 @@ static void extract_header(uint8_t *b, qnt_header *qnt) {
*/
static void extract_pixel(qnt_header *qnt, uint8_t *pic, uint8_t *b) {
int i, j, x, y, w, h;
long ucbuf = (qnt->width+1) * (qnt->height+1) * 3 + ZLIBBUF_MARGIN;
uint8_t *raw = malloc(sizeof(uint8_t) * ucbuf);
long ucbuf = zlibbuf_size(qnt, 3);
uint8_t *raw = malloc(ucbuf);
if (Z_OK != uncompress(raw, &ucbuf, b, qnt->pixel_size)) {
WARNING("uncompress failed");
@@ -168,8 +170,8 @@ static void extract_pixel(qnt_header *qnt, uint8_t *pic, uint8_t *b) {
*/
static void extract_alpha(qnt_header *qnt, uint8_t *pic, uint8_t *b) {
int i, x, y, w, h;
long ucbuf = (qnt->width+1) * (qnt->height+1) + ZLIBBUF_MARGIN;
uint8_t *raw = malloc(sizeof(uint8_t) * ucbuf);
long ucbuf = zlibbuf_size(qnt, 1);
uint8_t *raw = malloc(ucbuf);
if (Z_OK != uncompress(raw, &ucbuf, b, qnt->alpha_size)) {
WARNING("uncompress failed");
@@ -231,11 +233,11 @@ cgdata *qnt_extract(uint8_t *data) {
qnt_header qnt;
extract_header(data, &qnt);
cg->pic = malloc(sizeof(uint8_t) * ((qnt.width+10) * (qnt.height+10) * 3));
cg->pic = malloc(qnt.width * qnt.height * 3);
extract_pixel(&qnt, cg->pic, data + qnt.hdr_size);
if (qnt.alpha_size != 0) {
cg->alpha = malloc(sizeof(uint8_t) * ((qnt.width+10) * (qnt.height+10)));
cg->alpha = malloc(qnt.width * qnt.height);
extract_alpha(&qnt, (uint8_t *)cg->alpha, data + qnt.hdr_size + qnt.pixel_size);
}