Files
kichikuou_xsystem35-sdl2/src/qnt.c
T
kichikuou 29a139c8a1 Use the standard integer types
This replaces BYTE, WORD and DWORD types with uint8_t, uint16_t and
uint32_t respectively.
2022-10-29 09:34:21 +09:00

252 lines
6.7 KiB
C

/*
* qnt.c extract QNT cg
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @version 1.0 01/07/30 initial version
* @version 1.1 01/08/10 fix alpha map extraction
* @version 1.2 01/11/26 zlibの展開バッファが画像サイズよりも大きなものを
* 要求するときの workaround
* @version 1.2 01/11/28 format version 1 に対応
* *(top + 4) is 0 -> version 0
* *(top + 4) is 1 -> version 1
* @version 1.3 03/02/22 縦横奇数サイズ時にpixel/alphaともおかしかったのをfix
* zlib展開バッファを縦横それぞれ1byteづつ多くとる
* ようにした
*/
/* $Id: qnt.c,v 1.4 2003/04/22 16:34:28 chikama Exp $ */
#include <stdlib.h>
#include <zlib.h>
#include "portab.h"
#include "LittleEndian.h"
#include "cg.h"
#include "qnt.h"
#include "system.h"
/*
zlib の展開バッファで、幅×高さ×3に、さらにどれくらい余裕をとるか
(リクルスで 1164バイトというのがあった)
*/
#define ZLIBBUF_MARGIN 5*1024
/*
Get information from header
b: raw data
qnt: acquired qnt information object
*/
static void extract_header(uint8_t *b, qnt_header *qnt) {
int rsv0 = LittleEndian_getDW(b, 4);
if (rsv0 == 0) {
qnt->hdr_size = 48;
qnt->x0 = LittleEndian_getDW(b, 8);
qnt->y0 = LittleEndian_getDW(b, 12);
qnt->width = LittleEndian_getDW(b, 16);
qnt->height = LittleEndian_getDW(b, 20);
qnt->bpp = LittleEndian_getDW(b, 24);
qnt->rsv = LittleEndian_getDW(b, 28);
qnt->pixel_size = LittleEndian_getDW(b, 32);
qnt->alpha_size = LittleEndian_getDW(b, 36);
} else {
qnt->hdr_size = LittleEndian_getDW(b, 8);
qnt->x0 = LittleEndian_getDW(b, 12);
qnt->y0 = LittleEndian_getDW(b, 16);
qnt->width = LittleEndian_getDW(b, 20);
qnt->height = LittleEndian_getDW(b, 24);
qnt->bpp = LittleEndian_getDW(b, 28);
qnt->rsv = LittleEndian_getDW(b, 32);
qnt->pixel_size = LittleEndian_getDW(b, 36);
qnt->alpha_size = LittleEndian_getDW(b, 40);
}
}
/*
Do extract qnt pixel image
qnt: qnt header information
pic: pixel to be stored
b : raw data (pointer to pixel)
*/
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);
if (Z_OK != uncompress(raw, &ucbuf, b, qnt->pixel_size)) {
WARNING("uncompress failed");
free(raw);
return;
}
w = qnt->width;
h = qnt->height;
j = 0;
for (i = 2; i >= 0; i--) {
for (y = 0; y < (h -1); y+=2) {
for (x = 0; x < (w -1); x+=2) {
pic[( y *w+x) *3 +i] = raw[j];
pic[((y+1)*w+x) *3 +i] = raw[j+1];
pic[( y *w+x+1)*3 +i] = raw[j+2];
pic[((y+1)*w+x+1)*3 +i] = raw[j+3];
j+=4;
}
if (x != w) {
pic[( y *w+x)*3 +i] = raw[j];
pic[((y+1)*w+x)*3 +i] = raw[j+1];
j+=4;
}
}
if (y != h) {
for (x = 0; x < (w -1); x+=2) {
pic[(y*w+x )*3+i] = raw[j];
pic[(y*w+x+1)*3+i] = raw[j+2];
j+=4;
}
if (x != w) {
pic[( y *w+x)*3 +i] = raw[j];
j+=4;
}
}
}
if (w > 1) {
for (x = 1; x < w; x++) {
pic[x*3 ] = pic[(x-1)*3 ] - pic[x*3 ];
pic[x*3+1] = pic[(x-1)*3+1] - pic[x*3+1];
pic[x*3+2] = pic[(x-1)*3+2] - pic[x*3+2];
}
}
if (h > 1) {
for (y = 1; y < h; y++) {
pic[(y*w)*3 ] = pic[((y-1)*w)*3 ] - pic[(y*w)*3 ];
pic[(y*w)*3+1] = pic[((y-1)*w)*3+1] - pic[(y*w)*3+1];
pic[(y*w)*3+2] = pic[((y-1)*w)*3+2] - pic[(y*w)*3+2];
for (x = 1; x < w; x++) {
int px, py;
py = pic[((y-1)*w+x )*3];
px = pic[( y *w+x-1)*3];
pic[(y*w+x)*3] = ((py+px)>>1) - pic[(y*w+x)*3];
py = pic[((y-1)*w+x )*3+1];
px = pic[( y *w+x-1)*3+1];
pic[(y*w+x)*3+1] = ((py+px)>>1) - pic[(y*w+x)*3+1];
py = pic[((y-1)*w+x )*3+2];
px = pic[( y *w+x-1)*3+2];
pic[(y*w+x)*3+2] = ((py+px)>>1) - pic[(y*w+x)*3+2];
}
}
}
free(raw);
}
/*
Do extract qnt alpha image
qnt: qnt header information
pic: pixel to be stored
b : raw data (pointer to alpha pixel)
*/
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);
if (Z_OK != uncompress(raw, &ucbuf, b, qnt->alpha_size)) {
WARNING("uncompress failed");
free(raw);
return;
}
w = qnt->width;
h = qnt->height;
i = 1;
if (w > 1) {
pic[0] = raw[0];
for (x = 1; x < w; x++) {
pic[x] = pic[x-1] - raw[i];
i++;
}
if (w%2) i++;
}
if (h > 1) {
for (y = 1; y < h; y++) {
pic[y*w] = pic[(y-1) *w] - raw[i]; i++;
for (x = 1; x < w; x++) {
int pax, pay;
pax = pic[ y * w + x -1];
pay = pic[(y-1)* w + x ];
pic[y*w+x] = ((pax+pay) >> 1) - raw[i];
i++;
}
if (w%2) i++;
}
}
free(raw);
}
/*
Check data is qnt format cg or not
data: raw data (pointer to data top)
return: TRUE if data is qnt
*/
boolean qnt_checkfmt(uint8_t *data) {
if (data[0] != 'Q' || data[1] != 'N' || data[2] != 'T') return FALSE;
return TRUE;
}
/*
Extract qnt header and pixel
data: raw data (pointer to data top)
return: extracted image data and information
*/
cgdata *qnt_extract(uint8_t *data) {
cgdata *cg = calloc(1, sizeof(cgdata));
qnt_header qnt;
extract_header(data, &qnt);
cg->pic = malloc(sizeof(uint8_t) * ((qnt.width+10) * (qnt.height+10) * 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)));
extract_alpha(&qnt, (uint8_t *)cg->alpha, data + qnt.hdr_size + qnt.pixel_size);
}
cg->type = ALCG_QNT;
cg->x = qnt.x0;
cg->y = qnt.y0;
cg->width = qnt.width;
cg->height = qnt.height;
cg->depth = 24;
cg->pal = NULL;
return cg;
}