Add ability to edit game name from UI
[jpcrr.git] / streamtools / rescalers / hqx.cpp
blob7571c8fe401bda2f5f72fdee3dffbd33d91eb3d8
1 #ifdef WITH_HQX
2 #include <sstream>
3 #include "rescalers/simple.hpp"
4 #include <stdint.h>
5 extern "C" {
6 #include <hqx.h>
8 #include <cstring>
9 #include <stdexcept>
12 #define RMETHOD_HQX2 0
13 #define RMETHOD_HQX3 1
14 #define RMETHOD_HQX4 2
15 #define RMETHOD_HQX22 3
16 #define RMETHOD_HQX32 4
17 #define RMETHOD_HQX42 5
18 #define RMETHOD_HQX2d 6
19 #define RMETHOD_HQX3d 7
20 #define RMETHOD_HQX4d 8
22 namespace
24 bool initflag = false;
26 void psize_dummy(uint32_t* src, uint32_t* dest, int width, int height)
28 memcpy(dest, src, 4 * width * height);
31 void psize_double(uint32_t* src, uint32_t* dest, int width, int height)
33 for(size_t y = 0; (int)y < height; y++)
34 for(size_t x = 0; (int)x < width; x++) {
35 size_t dbaseindex = 4 * y * width + 2 * x;
36 size_t sbaseindex = y * width + x;
37 dest[dbaseindex] = dest[dbaseindex + 1] = dest[dbaseindex + 2 * width] =
38 dest[dbaseindex + 2 * width + 1] = src[sbaseindex];
42 typedef void(*rescale_t)(uint32_t*, uint32_t*, int, int);
43 int factors[] = {2, 3, 4, 4, 6, 8, 4, 6, 8};
44 int pfactors[] = {1, 1, 1, 2, 2, 2, 2, 2, 2};
45 rescale_t hqxfun[] = {hq2x_32, hq3x_32, hq4x_32, hq2x_32, hq3x_32, hq4x_32,
46 hq2x_32, hq3x_32, hq4x_32};
47 rescale_t psizefun[] = {psize_dummy, psize_dummy, psize_dummy, hq2x_32, hq2x_32,
48 hq2x_32, psize_double, psize_double, psize_double};
50 //Read the frame data in src (swidth x sheight) and rescale it to dest (dwidth x dheight).
51 void rescale_frame(unsigned char* dest, unsigned dwidth, unsigned dheight, const unsigned char* src,
52 unsigned swidth, unsigned sheight, int algo)
54 unsigned char magic[4] = {255, 255, 255, 0};
55 uint32_t* magic2 = (uint32_t*)magic;
56 uint32_t magic3 = ~*magic2;
57 uint32_t shiftscale = 0;
58 if(*magic2 > 0xFFFFFF)
59 shiftscale = 8; //Big-endian.
61 if(!initflag)
62 hqxInit();
63 initflag = true;
65 if(dwidth % factors[algo] || dheight % factors[algo])
66 throw std::runtime_error("hqx: Target image size must be multiple of scale factor");
67 if(dwidth / factors[algo] != swidth || dheight / factors[algo] != sheight) {
68 std::ostringstream str;
69 str << "hqx: Expected source to have resolution of " << dwidth / factors[algo] << "x"
70 << dheight / factors[algo] << ", got " << swidth << "x" << sheight << ".";
71 throw std::runtime_error(str.str());
74 uint32_t buffer1_width = dwidth / factors[algo];
75 uint32_t buffer2_width = dwidth / pfactors[algo];
76 uint32_t buffer3_width = dwidth;
77 uint32_t buffer1_height = dheight / factors[algo];
78 uint32_t buffer2_height = dheight / pfactors[algo];
79 uint32_t buffer3_height = dheight;
80 uint32_t* buffer1 = new uint32_t[buffer1_width * buffer1_height];
81 uint32_t* buffer2 = new uint32_t[buffer2_width * buffer2_height];
82 uint32_t* buffer3 = new uint32_t[buffer3_width * buffer3_height];
83 uint32_t* __restrict__ _src = (uint32_t*)src;
85 for(uint32_t y = 0; y < buffer1_height; y++)
86 for(uint32_t x = 0; x < buffer1_width; x++)
87 //Mask off high bits because HQX will crash otherwise.
88 buffer1[y * buffer1_width + x] = (_src[y * swidth + x] >> shiftscale) & 0xFFFFFF;
90 //Do the rescale steps.
91 hqxfun[algo](buffer1, buffer2, buffer1_width, buffer1_height);
92 psizefun[algo](buffer2, buffer3, buffer2_width, buffer2_height);
94 //Final copy out of buffer3 to destination.
95 for(size_t i = 0; i < buffer3_width * buffer3_height; i++)
96 buffer3[i] = (buffer3[i] << shiftscale) | magic3;
97 memcpy(dest, buffer3, 4 * dwidth * dheight);
99 delete buffer1;
100 delete buffer2;
101 delete buffer3;
104 simple_rescaler r_hqx2("hqx2", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
105 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX2));
106 simple_rescaler r_hqx3("hqx3", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
107 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX3));
108 simple_rescaler r_hqx4("hqx4", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
109 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX4));
110 simple_rescaler r_hqx22("hqx22", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
111 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX22));
112 simple_rescaler r_hqx32("hqx32", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
113 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX32));
114 simple_rescaler r_hqx42("hqx42", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
115 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX42));
116 simple_rescaler r_hqx2d("hqx2d", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
117 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX2d));
118 simple_rescaler r_hqx3d("hqx3d", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
119 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX3d));
120 simple_rescaler r_hqx4d("hqx4d", bind_last<void, int, uint8_t*, uint32_t, uint32_t, const uint8_t*,
121 uint32_t, uint32_t>(make_bound_method(rescale_frame), RMETHOD_HQX4d));
123 #endif