3 #include "rescalers/simple.hpp"
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
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.
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
);
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
));