Add webp CG support

Used in the MangaGamer version of Rance 5D.

The logic for the OVER chunk was taken from libsys4.
This commit is contained in:
kichikuou
2021-11-03 21:09:02 +09:00
parent 162bf8dc25
commit 0ecc4edb43
12 changed files with 200 additions and 19 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
- name: Install Deps
run: |
sudo apt update
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libportmidi-dev libcjson-dev
sudo apt install libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libportmidi-dev libcjson-dev
- name: Build
run: |
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
echo PATH: $PATH
- name: Install Deps
run: pacman -S --noconfirm ${{ matrix.package }}-SDL2 ${{ matrix.package }}-SDL2_ttf ${{ matrix.package }}-SDL2_mixer ${{ matrix.package }}-libjpeg-turbo ${{ matrix.package }}-cjson ${{ matrix.package }}-nsis ${{ matrix.package }}-ntldd-git
run: pacman -S --noconfirm ${{ matrix.package }}-SDL2 ${{ matrix.package }}-SDL2_ttf ${{ matrix.package }}-SDL2_mixer ${{ matrix.package }}-libjpeg-turbo ${{ matrix.package }}-libwebp ${{ matrix.package }}-cjson ${{ matrix.package }}-nsis ${{ matrix.package }}-ntldd-git
- name: Checkout
uses: actions/checkout@v2
+5
View File
@@ -65,6 +65,11 @@ else()
set(HAVE_JPEG 1)
endif()
optional_pkg_check_modules(WEBP IMPORTED_TARGET libwebp)
if (WEBP_FOUND)
set(HAVE_WEBP 1)
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
if (CMAKE_USE_PTHREADS_INIT)
+3 -3
View File
@@ -8,7 +8,7 @@ Prebuilt binaries for Windows and Android can be downloaded from the [Releases](
## Build
### Linux (Debian / Ubuntu)
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libcjson-dev
$ sudo apt install build-essential cmake libgtk-3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libcjson-dev
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
@@ -18,7 +18,7 @@ Prebuilt binaries for Windows and Android can be downloaded from the [Releases](
[Homebrew](https://brew.sh/index_ja) is needed.
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf libjpeg cjson
$ brew install cmake pkg-config sdl2 sdl2_mixer sdl2_ttf libjpeg webp cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ../../
@@ -28,7 +28,7 @@ Prebuilt binaries for Windows and Android can be downloaded from the [Releases](
[MSYS2](https://www.msys2.org) is needed.
$ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-cjson
$ pacman -S cmake mingw-w64-x86_64-cmake mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libwebp mingw-w64-x86_64-cjson
$ mkdir -p out/debug
$ cd out/debug
$ cmake -G"MSYS Makefiles" -DCMAKE_BUILD_TYPE=Debug ../../
+1
View File
@@ -32,6 +32,7 @@
#cmakedefine HAVE_SDLJOY @HAVE_SDLJOY@
#cmakedefine HAVE_SIGACTION @HAVE_SIGACTION@
#cmakedefine HAVE_UNAME @HAVE_UNAME@
#cmakedefine HAVE_WEBP @HAVE_WEBP@
#define DEFAULT_GOTHIC_TTF "@DEFAULT_FONT_PATH@MTLc3m.ttf"
#define DEFAULT_MINCHO_TTF "@DEFAULT_FONT_PATH@mincho.otf"
+1 -1
View File
@@ -86,7 +86,7 @@ static surface_t *smask_get(int no) {
if (i == am->datanum) return NULL;
return sf_getcg(am->mmap->addr + am->offset[i]);
return sf_getcg(am->mmap->addr + am->offset[i], 0 /*FIXME*/);
}
// ベースになるマスクの alpha 値を拡大して取り出す
+18 -5
View File
@@ -33,6 +33,9 @@
#include "ags.h"
#include "pms.h"
#include "qnt.h"
#ifdef HAVE_WEBP
#include "webp.h"
#endif
#include "ngraph.h"
#include "dri.h"
#include "ald_manager.h"
@@ -50,6 +53,10 @@ static CG_TYPE check_cgformat(BYTE *data) {
return ALCG_PMS8;
} else if (pms64k_checkfmt(data)) {
return ALCG_PMS16;
#ifdef HAVE_WEBP
} else if (webp_checkfmt(data)) {
return ALCG_WEBP;
#endif
}
return ALCG_UNKNOWN;
}
@@ -61,7 +68,7 @@ static CG_TYPE check_cgformat(BYTE *data) {
* @return CG が展開された surface
* 未知の形式のときは NULL が返る
*/
surface_t *sf_getcg(void *b) {
surface_t *sf_getcg(void *b, size_t size) {
surface_t *sf = NULL;
int type;
cgdata *cg = NULL;
@@ -77,6 +84,11 @@ surface_t *sf_getcg(void *b) {
case ALCG_QNT:
cg = qnt_extract(b);
break;
#ifdef HAVE_WEBP
case ALCG_WEBP:
cg = webp_extract(b, size);
break;
#endif
default:
break;
}
@@ -93,7 +105,7 @@ surface_t *sf_getcg(void *b) {
break;
case ALCG_PMS16:
if (cg->alpha) {
if (cg->alpha) {
sf = sf_create_surface(cg->width, cg->height, sf0->depth);
gr_drawimage16(sf, cg, cg->x, cg->y);
gr_draw_amap(sf, cg->x, cg->y, cg->alpha, cg->width, cg->height, cg->width);
@@ -103,7 +115,8 @@ surface_t *sf_getcg(void *b) {
}
break;
case ALCG_QNT:
case ALCG_QNT:
case ALCG_WEBP:
if (cg->alpha) {
sf = sf_create_surface(cg->width, cg->height, sf0->depth);
gr_drawimage24(sf, cg, cg->x, cg->y);
@@ -112,7 +125,7 @@ surface_t *sf_getcg(void *b) {
sf = sf_create_pixel(cg->width, cg->height, sf0->depth);
gr_drawimage24(sf, cg, cg->x, cg->y);
}
break;
break;
}
if (cg->pic) free(cg->pic);
@@ -137,7 +150,7 @@ surface_t *sf_loadcg_no(int no) {
return NULL;
}
sf = sf_getcg(dfile->data);
sf = sf_getcg(dfile->data, dfile->size);
ald_freedata(dfile);
+1 -1
View File
@@ -83,7 +83,7 @@ extern void gr_drawimage16(surface_t *ds, cgdata *cg, int x, int y);
/* defined in cg.c */
extern surface_t *sf_getcg(void *buf);
extern surface_t *sf_getcg(void *buf, size_t size);
extern surface_t *sf_loadcg_no(int no);
+4
View File
@@ -46,6 +46,10 @@ if (HAVE_JPEG)
target_link_libraries(xsystem35 PRIVATE JPEG::JPEG)
endif()
endif()
if (HAVE_WEBP)
target_sources(xsystem35 PRIVATE webp.c)
target_link_libraries(xsystem35 PRIVATE PkgConfig::WEBP)
endif()
# Music
target_sources(xsystem35 PRIVATE
+8 -7
View File
@@ -32,13 +32,14 @@
*/
typedef enum {
ALCG_UNKNOWN = 1,
ALCG_VSP = 2,
ALCG_PMS8 = 3,
ALCG_PMS16 = 4,
ALCG_BMP8 = 5,
ALCG_BMP24 = 6,
ALCG_QNT = 7,
ALCG_JPEG = 8,
ALCG_VSP,
ALCG_PMS8,
ALCG_PMS16,
ALCG_BMP8,
ALCG_BMP24,
ALCG_QNT,
ALCG_JPEG,
ALCG_WEBP,
} CG_TYPE;
/*
+129
View File
@@ -0,0 +1,129 @@
/*
* Copyright (C) 2021 kichikuou <KichikuouChrome@gmail.com>
*
* 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
*
*/
#include <webp/decode.h>
#include "system.h"
#include "webp.h"
#include "dri.h"
#include "ald_manager.h"
#include "LittleEndian.h"
boolean webp_checkfmt(BYTE *data) {
if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F')
return FALSE;
if (data[8] != 'W' || data[9] != 'E' || data[10] != 'B' || data[11] != 'P')
return FALSE;
return TRUE;
}
static int get_base_cg(uint8_t *data, size_t size) {
if (size < 12)
return 0;
if (data[size-12] != 'O' || data[size-11] != 'V' || data[size-10] != 'E' || data[size-9] != 'R')
return 0;
int uk = LittleEndian_getDW(data, size-8); // size?
if (uk != 4)
WARNING("WEBP: expected 0x4 preceding base CG number, got %d\n", uk);
return LittleEndian_getDW(data, size-4);
}
static uint8_t *webp_load(uint8_t *data, size_t size, int *width, int *height, int *has_alpha) {
uint8_t *pixels = WebPDecodeRGBA(data, size, width, height);
if (!pixels) {
return NULL;
}
WebPBitstreamFeatures features;
WebPGetFeatures(data, size, &features);
*has_alpha = features.has_alpha;
int base = get_base_cg(data, size);
if (!base)
return pixels;
dridata *dfile = ald_getdata(DRIFILE_CG, base - 1);
if (!dfile) {
WARNING("Cannot load base CG %d\n", base - 1);
return pixels;
}
int base_width, base_height, base_has_alpha;
uint8_t *base_pixels = webp_load(dfile->data, dfile->size, &base_width, &base_height, &base_has_alpha);
ald_freedata(dfile);
if (!base_pixels) {
WARNING("Cannot decode base CG %d\n", base - 1);
return pixels;
}
if (*width != base_width || *height != base_height) {
WARNING("webp base CG dimensions don't match: (%d,%d) / (%d,%d)\n",
base_width, base_height, *width, *height);
WebPFree(base_pixels);
return pixels;
}
*has_alpha |= base_has_alpha;
uint8_t *p = pixels;
uint8_t *bp = base_pixels;
for (int n = base_width * base_height; n > 0; n--) {
if (p[0] == 255 && p[1] == 0 && p[2] == 255) {
p[0] = bp[0];
p[1] = bp[1];
p[2] = bp[2];
p[3] = bp[3];
}
p += 4;
bp += 4;
}
WebPFree(base_pixels);
return pixels;
}
static void rgba_to_rgb_and_alpha(uint8_t *rgba, uint8_t *rgb, uint8_t *alpha, int nr_pixels) {
for (int i = 0; i < nr_pixels; i++) {
*rgb++ = *rgba++;
*rgb++ = *rgba++;
*rgb++ = *rgba++;
*alpha++ = *rgba++;
}
}
cgdata *webp_extract(BYTE *data, size_t size) {
int width, height, has_alpha;
uint8_t *rgba = webp_load(data, size, &width, &height, &has_alpha);
if (!rgba) {
WARNING("webp image decode failed");
return NULL;
}
cgdata *cg = calloc(1, sizeof(cgdata));
cg->type = ALCG_WEBP;
cg->width = width;
cg->height = height;
cg->pic = malloc(cg->width * cg->height * 3);
cg->alpha = malloc(cg->width * cg->height);
rgba_to_rgb_and_alpha(rgba, cg->pic, cg->alpha, cg->width * cg->height);
if (!has_alpha) {
free(cg->alpha);
cg->alpha = NULL;
}
WebPFree(rgba);
return cg;
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2021 kichikuou <KichikuouChrome@gmail.com>
*
* 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
*
*/
#ifndef __WEBP_H__
#define __WEBP_H__
#include "cg.h"
boolean webp_checkfmt(BYTE *data);
cgdata *webp_extract(BYTE *data, size_t size);
#endif // __WEBP_H__