Skip to content

Commit c076e74

Browse files
committed
thanm: implement sprite merging for jpeg images during extraction
Needed for th20 endings Requires libjpeg > 8.0. I'm bad with cmake, so I just assume the library is already installed system-wide.
1 parent 057519f commit c076e74

4 files changed

Lines changed: 78 additions & 10 deletions

File tree

thanm/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ add_executable(thanm
99
thanm.h image.h anmmap.h reg.h expr.h
1010
)
1111
target_include_directories(thanm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
12-
target_link_libraries(thanm PRIVATE util $<$<BOOL:${PNG_FOUND}>:PNG::PNG> math setargv thtk_warning)
12+
target_link_libraries(thanm PRIVATE util $<$<BOOL:${PNG_FOUND}>:PNG::PNG> math setargv thtk_warning jpeg)
1313
install(TARGETS thanm)
1414
install(FILES thanm.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)

thanm/image.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,16 @@
2626
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2727
* DAMAGE.
2828
*/
29+
#define HAVE_LIBJPEG
2930
#include <config.h>
3031
#include <string.h>
3132
#include <inttypes.h>
3233
#ifdef HAVE_LIBPNG
3334
#include <png.h>
3435
#endif
36+
#ifdef HAVE_LIBJPEG
37+
#include <jpeglib.h>
38+
#endif
3539
#include <stdlib.h>
3640
#include <errno.h>
3741
#include "image.h"
@@ -337,3 +341,46 @@ png_write(
337341
fclose(stream);
338342
}
339343
#endif
344+
345+
#ifdef HAVE_LIBJPEG
346+
void
347+
jpeg_read_mem(
348+
image_t *image,
349+
void *data,
350+
size_t len)
351+
{
352+
struct jpeg_decompress_struct cinfo;
353+
struct jpeg_error_mgr jerr;
354+
355+
JSAMPROW row_pointer[1];
356+
357+
cinfo.err = jpeg_std_error(&jerr);
358+
jpeg_create_decompress(&cinfo);
359+
jpeg_mem_src(&cinfo, data, len);
360+
jpeg_read_header(&cinfo, TRUE);
361+
jpeg_start_decompress(&cinfo);
362+
363+
image->width = cinfo.image_width;
364+
image->height = cinfo.image_height;
365+
image->format = FORMAT_RGBA8888;
366+
image->data = malloc(image->width * image->height * 4);
367+
368+
uint8_t *pos = image->data;
369+
uint8_t *line = malloc(image->width * 4);
370+
while (cinfo.output_scanline < cinfo.image_height) {
371+
row_pointer[0] = line;
372+
jpeg_read_scanlines(&cinfo, row_pointer, 1);
373+
for (size_t i = 0; i < cinfo.image_width; i++) {
374+
pos[i * 4 + 0] = line[i * 3 + 0];
375+
pos[i * 4 + 1] = line[i * 3 + 1];
376+
pos[i * 4 + 2] = line[i * 3 + 2];
377+
pos[i * 4 + 3] = 0xFF;
378+
}
379+
pos += cinfo.image_width * 4;
380+
}
381+
free(line);
382+
383+
jpeg_finish_decompress(&cinfo);
384+
jpeg_destroy_decompress(&cinfo);
385+
}
386+
#endif

thanm/image.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,10 @@ png_write(
7979
const char* filename,
8080
image_t* image);
8181

82+
void
83+
jpeg_read_mem(
84+
image_t *image,
85+
void *data,
86+
size_t len);
87+
8288
#endif

thanm/thanm.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,12 @@ static const id_format_pair_t th18_patch[] = {
563563
{ 0, NULL }
564564
};
565565

566+
enum FileType {
567+
FILETYPE_BITMAP,
568+
FILETYPE_PNG,
569+
FILETYPE_JPEG,
570+
};
571+
566572
static inline int
567573
jfif_identify(uint8_t* jfif, uint32_t size) {
568574
return size >= 11 &&
@@ -1532,7 +1538,7 @@ anm_replace(
15321538
return;
15331539
}
15341540

1535-
int is_png = 0;
1541+
int entry_filetype = FILETYPE_BITMAP;
15361542
if (TH19_OR_NEWER(version)) {
15371543
anm_entry_t *entry = entry_first;
15381544
const uint32_t ox = option_dont_add_offset_border ? 0 : entry->header->x;
@@ -1553,7 +1559,7 @@ anm_replace(
15531559
fprintf(stderr, "%s: composing %s\n", argv0, filename);
15541560
image = malloc(sizeof(image_t));
15551561
png_read_mem(image, entry->data, entry->thtx->size);
1556-
is_png = 1;
1562+
entry_filetype = FILETYPE_PNG;
15571563
} else {
15581564
image = png_read(filename);
15591565
}
@@ -1576,7 +1582,7 @@ anm_replace(
15761582
unsigned int y;
15771583
format_t fmt = formats[f];
15781584

1579-
if (is_png) {
1585+
if (entry_filetype == FILETYPE_PNG) {
15801586
if (fmt != FORMAT_BGRA8888) {
15811587
fprintf(stderr, "%s: %s is not FORMAT_BGRA8888\n", argv0, entry->name);
15821588
exit(1);
@@ -1609,7 +1615,7 @@ anm_replace(
16091615

16101616
free(converted_data);
16111617

1612-
if (is_png) {
1618+
if (entry_filetype == FILETYPE_PNG) {
16131619
image_t image2 = {
16141620
.data = entry->data,
16151621
.width = entry->thtx->w,
@@ -1638,12 +1644,16 @@ anm_replace(
16381644
static unsigned char *
16391645
entry_to_rgba(
16401646
anm_entry_t *entry,
1641-
int is_png)
1647+
int filetype)
16421648
{
1643-
if (is_png) {
1649+
if (filetype == FILETYPE_PNG) {
16441650
image_t image;
16451651
png_read_mem(&image, entry->data, entry->thtx->size);
16461652
return image.data;
1653+
} else if (filetype == FILETYPE_JPEG) {
1654+
image_t image;
1655+
jpeg_read_mem(&image, entry->data, entry->thtx->size);
1656+
return image.data;
16471657
} else {
16481658
return format_to_rgba(entry->data, entry->thtx->w * entry->thtx->h, entry->thtx->format);
16491659
}
@@ -1681,14 +1691,19 @@ anm_extract(
16811691

16821692
uint32_t ox = option_dont_add_offset_border ? 0 : entry->header->x;
16831693
uint32_t oy = option_dont_add_offset_border ? 0 : entry->header->y;
1684-
int is_png = 0;
1694+
int filetype = FILETYPE_BITMAP;
16851695

16861696
if (TH19_OR_NEWER(version)) {
16871697
if (png_identify(entry->thtx->data, entry->thtx->size) &&
16881698
(ox || oy || entry->next_by_name)) {
16891699
if (option_verbose >= 2)
16901700
fprintf(stderr, "%s: composing %s\n", argv0, filename);
1691-
is_png = 1;
1701+
filetype = FILETYPE_PNG;
1702+
} else if (jfif_identify(entry->thtx->data, entry->thtx->size) &&
1703+
(ox || oy || entry->next_by_name)) {
1704+
if (option_verbose >= 2)
1705+
fprintf(stderr, "%s: composing %s\n", argv0, filename);
1706+
filetype = FILETYPE_JPEG;
16921707
} else {
16931708
if (option_verbose >= 2)
16941709
fprintf(stderr, "%s: not composing %s\n", argv0, filename);
@@ -1716,7 +1731,7 @@ anm_extract(
17161731
if (formats[f] == entryp->thtx->format) {
17171732
ox = option_dont_add_offset_border ? 0 : entryp->header->x;
17181733
oy = option_dont_add_offset_border ? 0 : entryp->header->y;
1719-
unsigned char* temp_data = entry_to_rgba(entryp, is_png);
1734+
unsigned char* temp_data = entry_to_rgba(entryp, filetype);
17201735
for (y = oy; y < oy + entryp->thtx->h; ++y) {
17211736
memcpy(image.data + y * image.width * 4 + ox * 4,
17221737
temp_data + (y - oy) * entryp->thtx->w * 4,

0 commit comments

Comments
 (0)