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
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.
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
);
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
);