SDL_Main isn't needed on sane platforms anyway. Remove it
[jpcrr.git] / streamtools / resizer-hqx.cpp
blob51704b045082880f3d65fc87bb0a016c87b09252
1 #include "resize.hpp"
2 #include <stdint.h>
3 extern "C" {
4 #include <hqx.h>
6 #include <cstring>
7 #include <stdexcept>
10 #define RMETHOD_HQX2 0
11 #define RMETHOD_HQX3 1
12 #define RMETHOD_HQX4 2
13 #define RMETHOD_HQX22 3
14 #define RMETHOD_HQX32 4
15 #define RMETHOD_HQX42 5
16 #define RMETHOD_HQX2d 6
17 #define RMETHOD_HQX3d 7
18 #define RMETHOD_HQX4d 8
20 namespace
22 bool initflag = false;
24 inline uint32_t nnscale(uint32_t value, uint32_t trange, uint32_t srange)
26 //x / trange is as good approximation for value / srange as possible.
27 //=> x is as good approximation for value * trange / srange as possible.
28 return (uint32_t)(((uint64_t)value * trange + srange / 2) / srange);
31 void psize_dummy(uint32_t* src, uint32_t* dest, int width, int height)
33 memcpy(dest, src, 4 * width * height);
36 void psize_double(uint32_t* src, uint32_t* dest, int width, int height)
38 for(size_t y = 0; (int)y < height; y++)
39 for(size_t x = 0; (int)x < width; x++) {
40 size_t dbaseindex = 4 * y * width + 2 * x;
41 size_t sbaseindex = y * width + x;
42 dest[dbaseindex] = dest[dbaseindex + 1] = dest[dbaseindex + 2 * width] =
43 dest[dbaseindex + 2 * width + 1] = src[sbaseindex];
47 typedef void(*resize_t)(uint32_t*, uint32_t*, int, int);
48 int factors[] = {2, 3, 4, 4, 6, 8, 4, 6, 8};
49 int pfactors[] = {1, 1, 1, 2, 2, 2, 2, 2, 2};
50 resize_t hqxfun[] = {hq2x_32, hq3x_32, hq4x_32, hq2x_32, hq3x_32, hq4x_32,
51 hq2x_32, hq3x_32, hq4x_32};
52 resize_t psizefun[] = {psize_dummy, psize_dummy, psize_dummy, hq2x_32, hq2x_32,
53 hq2x_32, psize_double, psize_double, psize_double};
55 //Read the frame data in src (swidth x sheight) and resize it to dest (dwidth x dheight).
56 void resize_frame(unsigned char* dest, unsigned dwidth, unsigned dheight, const unsigned char* src,
57 unsigned swidth, unsigned sheight, int algo)
59 char magic[4] = {255, 255, 255, 0};
60 uint32_t* magic2 = (uint32_t*)magic;
61 uint32_t shiftscale = 0;
62 if(*magic2 > 0xFFFFFF)
63 shiftscale = 8; //Big-endian.
65 if(!initflag)
66 hqxInit();
67 initflag = true;
69 if(dwidth % factors[algo] || dheight % factors[algo])
70 throw std::runtime_error("hqx: Target image size must be multiple of scale factor");
72 uint32_t buffer1_width = dwidth / factors[algo];
73 uint32_t buffer2_width = dwidth / pfactors[algo];
74 uint32_t buffer3_width = dwidth;
75 uint32_t buffer1_height = dheight / factors[algo];
76 uint32_t buffer2_height = dheight / pfactors[algo];
77 uint32_t buffer3_height = dheight;
78 uint32_t* buffer1 = new uint32_t[buffer1_width * buffer1_height];
79 uint32_t* buffer2 = new uint32_t[buffer2_width * buffer2_height];
80 uint32_t* buffer3 = new uint32_t[buffer3_width * buffer3_height];
81 uint32_t* __restrict__ _src = (uint32_t*)src;
83 for(uint32_t y = 0; y < buffer1_height; y++)
84 for(uint32_t x = 0; x < buffer1_width; x++) {
85 uint32_t _x = nnscale(x, swidth, buffer1_width);
86 uint32_t _y = nnscale(y, sheight, buffer1_height);
87 buffer1[y * buffer1_width + x] = _src[_y * swidth + _x] >> shiftscale;
90 //Do the resize 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] <<= shiftscale;
97 memcpy(dest, buffer3, 4 * dwidth * dheight);
99 delete buffer1;
100 delete buffer2;
101 delete buffer3;
104 simple_resizer r_hqx2("hqx2", resize_frame, RMETHOD_HQX2);
105 simple_resizer r_hqx3("hqx3", resize_frame, RMETHOD_HQX3);
106 simple_resizer r_hqx4("hqx4", resize_frame, RMETHOD_HQX4);
107 simple_resizer r_hqx22("hqx22", resize_frame, RMETHOD_HQX22);
108 simple_resizer r_hqx32("hqx32", resize_frame, RMETHOD_HQX32);
109 simple_resizer r_hqx42("hqx42", resize_frame, RMETHOD_HQX42);
110 simple_resizer r_hqx2d("hqx2d", resize_frame, RMETHOD_HQX2d);
111 simple_resizer r_hqx3d("hqx3d", resize_frame, RMETHOD_HQX3d);
112 simple_resizer r_hqx4d("hqx4d", resize_frame, RMETHOD_HQX4d);