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