streamtools: refactor output/scaler drivers to their own directories
[jpcrr.git] / streamtools / resizer / hqx.cpp
blobe3074637ff9caacbca0acd496526dd1d66eba799
1 #ifdef WITH_HQX
2 #include "resize.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 inline uint32_t nnscale(uint32_t value, uint32_t trange, uint32_t srange)
27 //x / trange is as good approximation for value / srange as possible.
28 //=> x is as good approximation for value * trange / srange as possible.
29 return (uint32_t)(((uint64_t)value * trange + srange / 2) / srange);
32 void psize_dummy(uint32_t* src, uint32_t* dest, int width, int height)
34 memcpy(dest, src, 4 * width * height);
37 void psize_double(uint32_t* src, uint32_t* dest, int width, int height)
39 for(size_t y = 0; (int)y < height; y++)
40 for(size_t x = 0; (int)x < width; x++) {
41 size_t dbaseindex = 4 * y * width + 2 * x;
42 size_t sbaseindex = y * width + x;
43 dest[dbaseindex] = dest[dbaseindex + 1] = dest[dbaseindex + 2 * width] =
44 dest[dbaseindex + 2 * width + 1] = src[sbaseindex];
48 typedef void(*resize_t)(uint32_t*, uint32_t*, int, int);
49 int factors[] = {2, 3, 4, 4, 6, 8, 4, 6, 8};
50 int pfactors[] = {1, 1, 1, 2, 2, 2, 2, 2, 2};
51 resize_t hqxfun[] = {hq2x_32, hq3x_32, hq4x_32, hq2x_32, hq3x_32, hq4x_32,
52 hq2x_32, hq3x_32, hq4x_32};
53 resize_t psizefun[] = {psize_dummy, psize_dummy, psize_dummy, hq2x_32, hq2x_32,
54 hq2x_32, psize_double, psize_double, psize_double};
56 //Read the frame data in src (swidth x sheight) and resize it to dest (dwidth x dheight).
57 void resize_frame(unsigned char* dest, unsigned dwidth, unsigned dheight, const unsigned char* src,
58 unsigned swidth, unsigned sheight, int algo)
60 char magic[4] = {255, 255, 255, 0};
61 uint32_t* magic2 = (uint32_t*)magic;
62 uint32_t shiftscale = 0;
63 if(*magic2 > 0xFFFFFF)
64 shiftscale = 8; //Big-endian.
66 if(!initflag)
67 hqxInit();
68 initflag = true;
70 if(dwidth % factors[algo] || dheight % factors[algo])
71 throw std::runtime_error("hqx: Target image size must be multiple of scale factor");
73 uint32_t buffer1_width = dwidth / factors[algo];
74 uint32_t buffer2_width = dwidth / pfactors[algo];
75 uint32_t buffer3_width = dwidth;
76 uint32_t buffer1_height = dheight / factors[algo];
77 uint32_t buffer2_height = dheight / pfactors[algo];
78 uint32_t buffer3_height = dheight;
79 uint32_t* buffer1 = new uint32_t[buffer1_width * buffer1_height];
80 uint32_t* buffer2 = new uint32_t[buffer2_width * buffer2_height];
81 uint32_t* buffer3 = new uint32_t[buffer3_width * buffer3_height];
82 uint32_t* __restrict__ _src = (uint32_t*)src;
84 for(uint32_t y = 0; y < buffer1_height; y++)
85 for(uint32_t x = 0; x < buffer1_width; x++) {
86 uint32_t _x = nnscale(x, swidth, buffer1_width);
87 uint32_t _y = nnscale(y, sheight, buffer1_height);
88 buffer1[y * buffer1_width + x] = _src[_y * swidth + _x] >> shiftscale;
91 //Do the resize steps.
92 hqxfun[algo](buffer1, buffer2, buffer1_width, buffer1_height);
93 psizefun[algo](buffer2, buffer3, buffer2_width, buffer2_height);
95 //Final copy out of buffer3 to destination.
96 for(size_t i = 0; i < buffer3_width * buffer3_height; i++)
97 buffer3[i] <<= shiftscale;
98 memcpy(dest, buffer3, 4 * dwidth * dheight);
100 delete buffer1;
101 delete buffer2;
102 delete buffer3;
105 simple_resizer r_hqx2("hqx2", resize_frame, RMETHOD_HQX2);
106 simple_resizer r_hqx3("hqx3", resize_frame, RMETHOD_HQX3);
107 simple_resizer r_hqx4("hqx4", resize_frame, RMETHOD_HQX4);
108 simple_resizer r_hqx22("hqx22", resize_frame, RMETHOD_HQX22);
109 simple_resizer r_hqx32("hqx32", resize_frame, RMETHOD_HQX32);
110 simple_resizer r_hqx42("hqx42", resize_frame, RMETHOD_HQX42);
111 simple_resizer r_hqx2d("hqx2d", resize_frame, RMETHOD_HQX2d);
112 simple_resizer r_hqx3d("hqx3d", resize_frame, RMETHOD_HQX3d);
113 simple_resizer r_hqx4d("hqx4d", resize_frame, RMETHOD_HQX4d);
115 #endif