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