mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-28 09:48:05 +03:00
This replaces BYTE, WORD and DWORD types with uint8_t, uint16_t and uint32_t respectively.
252 lines
6.7 KiB
C
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;
|
|
}
|