Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Commit 40dd4ef

Browse files
committed
misc: quantize png images to reduce filesize
1 parent 526fe9b commit 40dd4ef

File tree

6 files changed

+9170
-10
lines changed

6 files changed

+9170
-10
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
steps:
1717
- run: |
1818
sudo apt-get update
19-
sudo apt-get install libsdl2-dev libsdl2-image-dev
19+
sudo apt-get install libsdl2-dev libsdl2-image-dev libimagequant-dev
2020
- uses: actions/checkout@v3
2121
- name: Build
2222
run: |

CMakeLists.txt

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,44 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
88

99
find_package(PkgConfig REQUIRED)
1010
find_package(X11 REQUIRED)
11+
find_package(OpenMP REQUIRED)
1112

1213
pkg_check_modules(SDL2 REQUIRED sdl2)
1314
pkg_check_modules(SDL2_IMAGE REQUIRED SDL2_image)
15+
pkg_check_modules(IMAGEQUANT REQUIRED imagequant)
16+
17+
include_directories(
18+
${CMAKE_SOURCE_DIR}
19+
${X11_INCLUDE_DIR}
20+
${SDL2_INCLUDE_DIRS}
21+
${SDL2_IMAGE_INCLUDE_DIRS}
22+
${IMAGEQUANT_INCLUDE_DIRS}
23+
)
1424

15-
include_directories(${CMAKE_SOURCE_DIR} ${X11_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS})
16-
17-
link_directories(${SDL2_LIBRARY_DIRS} ${SDL2_IMAGE_LIBRARY_DIRS})
25+
link_directories(
26+
${SDL2_LIBRARY_DIRS}
27+
${SDL2_IMAGE_LIBRARY_DIRS}
28+
${IMAGEQUANT_LIBRARY_DIRS}
29+
)
1830

1931
add_executable(vpxds
2032
main.cpp
2133
VPXDisplayServer.h
2234
VPXDisplayServer.cpp
2335
inc/mongoose/mongoose.c
2436
inc/mongoose/mongoose.h
37+
inc/lodepng/lodepng.cpp
38+
inc/lodepng/lodepng.h
2539
)
2640

27-
target_link_libraries(vpxds ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} ${X11_LIBRARIES})
28-
41+
target_link_libraries(vpxds
42+
${SDL2_LIBRARIES}
43+
${SDL2_IMAGE_LIBRARIES}
44+
${X11_LIBRARIES}
45+
libimagequant.a
46+
OpenMP::OpenMP_CXX
47+
)
2948

3049
add_custom_command(TARGET vpxds POST_BUILD
3150
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/assets" "$<TARGET_FILE_DIR:vpxds>/assets"
32-
)
51+
)

VPXDisplayServer.cpp

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
#include "inc/mongoose/mongoose.h"
66
#include "inc/mINI/ini.h"
77
#include "inc/subprocess/subprocess.h"
8+
#include "inc/lodepng/lodepng.h"
89

910
#include <iostream>
1011
#include <filesystem>
1112
#include <algorithm>
1213
#include <X11/Xlib.h>
1314

15+
#include <libimagequant.h>
16+
1417
static VPXDisplayServer* g_pServer = NULL;
1518

1619
void VPXDisplayServer::Forward(struct mg_http_message *hm, struct mg_connection *c)
@@ -234,7 +237,7 @@ void VPXDisplayServer::Capture(struct mg_connection *c, void *ev_data)
234237
int process_return;
235238
if (!subprocess_join(&subprocess, &process_return)) {
236239
PLOGI.printf("process return: %d", process_return);
237-
if (!process_return) {
240+
if (!process_return && ProcessPNG(szCapture)) {
238241
mg_http_reply(c, 200, "", "");
239242
return;
240243
}
@@ -281,9 +284,9 @@ void VPXDisplayServer::CaptureES(struct mg_connection *c, void *ev_data)
281284
int process_return;
282285
if (!subprocess_join(&subprocess, &process_return)) {
283286
PLOGI.printf("process returned: %d", process_return);
284-
if (!process_return) {
287+
if (!process_return && ProcessPNG(szPath)) {
285288
struct mg_http_serve_opts opts = {};
286-
mg_http_serve_file(c, hm, szPath.c_str(), &opts);
289+
mg_http_serve_file(c, hm, szPath.c_str(), &opts);
287290
return;
288291
}
289292
}
@@ -454,6 +457,63 @@ void VPXDisplayServer::LoadINI()
454457
}
455458
}
456459

460+
bool VPXDisplayServer::ProcessPNG(const std::string& filename)
461+
{
462+
unsigned int width;
463+
unsigned int height;
464+
unsigned char* pPixels;
465+
466+
if (lodepng_decode32_file(&pPixels, &width, &height, filename.c_str()))
467+
return false;
468+
469+
liq_attr* pHandle = liq_attr_create();
470+
liq_image* pImage = liq_image_create_rgba(pHandle, pPixels, width, height, 0);
471+
472+
liq_result* pQuantizationResult;
473+
if (liq_image_quantize(pImage, pHandle, &pQuantizationResult) != LIQ_OK)
474+
return false;
475+
476+
size_t pixelsSize = width * height;
477+
unsigned char* pPixels8 = (unsigned char *)malloc(pixelsSize);
478+
liq_set_dithering_level(pQuantizationResult, 1.0);
479+
480+
liq_write_remapped_image(pQuantizationResult, pImage, pPixels8, pixelsSize);
481+
const liq_palette* pPalette = liq_get_palette(pQuantizationResult);
482+
483+
LodePNGState state;
484+
lodepng_state_init(&state);
485+
state.info_raw.colortype = LCT_PALETTE;
486+
state.info_raw.bitdepth = 8;
487+
state.info_png.color.colortype = LCT_PALETTE;
488+
state.info_png.color.bitdepth = 8;
489+
490+
for (int i = 0; i < pPalette->count; i++) {
491+
lodepng_palette_add(&state.info_png.color, pPalette->entries[i].r, pPalette->entries[i].g, pPalette->entries[i].b, pPalette->entries[i].a);
492+
lodepng_palette_add(&state.info_raw, pPalette->entries[i].r, pPalette->entries[i].g, pPalette->entries[i].b, pPalette->entries[i].a);
493+
}
494+
495+
unsigned char* pOutput;
496+
size_t outputSize;
497+
if (lodepng_encode(&pOutput, &outputSize, pPixels8, width, height, &state))
498+
return false;
499+
500+
FILE *fp = fopen(filename.c_str(), "wb");
501+
if (!fp)
502+
return false;
503+
504+
fwrite(pOutput, 1, outputSize, fp);
505+
fclose(fp);
506+
507+
liq_result_destroy(pQuantizationResult);
508+
liq_image_destroy(pImage);
509+
liq_attr_destroy(pHandle);
510+
511+
free(pPixels8);
512+
lodepng_state_cleanup(&state);
513+
514+
return true;
515+
}
516+
457517
int VPXDisplayServer::Start()
458518
{
459519
PLOGI << "Starting VPXDS...";

VPXDisplayServer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class VPXDisplayServer
3939
void Reset(struct mg_connection *c, void *ev_data);
4040
void Capture(struct mg_connection *c, void *ev_data);
4141
void CaptureES(struct mg_connection *c, void *ev_data);
42+
bool ProcessPNG(const std::string& filename);
4243

4344
VPXDisplay* m_pBackglassDisplay;
4445
VPXDisplay* m_pDMDDisplay;

0 commit comments

Comments
 (0)