下面是实现代码(c++11),支持BPP为1,2,3,4字节的图像矩阵。
rotate.cpp
#include <type_traits>
#include <stdint.h>
#include <algorithm>
#include <cstring>
#include <vector>
// 成功返回标志
#define JIU_OK 0
// ERROR:空指针
#define JIU_NULL_PTR -1
// ERROR:无效参数
#define JIU_INVALID_ARG -2
// 适用于1,2,4字节像素图像的像素交换函数
template<typename T,size_t BPP = sizeof(T)>
inline typename std::enable_if<BPP == 1 || BPP == 2 || BPP == 4>::type _myswap(void*a, void* b) noexcept{
std::swap((T&)a, (T&)b);
}
// 适用于3字节(RGB/BGR)像素图像的像素交换函数
template<typename T, size_t BPP = sizeof(T)>
inline typename std::enable_if<BPP == 3>::type _myswap(void*a,void* b) noexcept {
for (int i = 0; i < BPP; ++i) {
std::swap(((uint8_t*)a)[i], ((uint8_t*)b)[i]);
}
}
/**
* 模板函数,将输入图像 顺时针原地旋转(In-place matrix transposition)90度<br>
* @param <BPP> 模板参数,每像素字节数(1,2,3,4)
* @param input 输入图像矩阵,size=width*height*bpp
* @param width 图像宽度
* @param height 图像宽度
*/
template<typename T, size_t BPP = sizeof(T)>
void rotate90(void*input,int width,int height) noexcept {
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
int I = height - 1 - j;
int J = i;
while ((i*height + j) >(I*width + J))
{
int p = I*width + J;
int tmp_i = p / height;
int tmp_j = p % height;
I = height - 1 - tmp_j;
J = tmp_i;
}
_myswap<T,BPP>((uint8_t*)input + (i*height + j)*BPP , (uint8_t*)input+(I*width + J)*BPP);
}
}
}
/**
* 将输入图像 顺时针原地旋转(In-place matrix transposition)90度<br>
* 图像必须是1字节对齐,多字节对齐的图像旋转可能会造成图像错位
* @param input 输入图像矩阵,size=width*height*bpp
* @param width 图像宽度
* @param height 图像宽度
* @param bpp 每像素字节数(1,2,3,4)
* @return 0-成功,-1 null pointer,-2 invalid argument
*/
int rotate90(void*input, int width, int height, int bpp) noexcept {
switch (bpp) {
case 1:
rotate90<uint8_t>(input, width, height);
return JIU_OK;
case 2:
rotate90<uint16_t>(input, width, height);
return JIU_OK;
case 3:
rotate90<uint8_t,3>(input, width, height);
return JIU_OK;
case 4:
rotate90<uint32_t>(input, width, height);
return JIU_OK;
default:
return JIU_INVALID_ARG;
}
}
//////////////////////////////////
/**
* 模板函数,将输入图像 顺时针原地旋转(In-place matrix transposition)270度<br>
* @param <BPP> 模板参数,每像素字节数(1,2,3,4)
* @param input 输入图像矩阵,size=width*height*bpp
* @param width 图像宽度
* @param height 图像宽度
*/
template<typename T, size_t BPP = sizeof(T)>
void rotate270(void*input, int width, int height) noexcept {
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
int I = j;
int J = width - 1 - i;
while ((i*height + j) >(I*width + J))
{
int p = I*width + J;
int tmp_i = p / height;
int tmp_j = p % height;
I = tmp_j;
J = width - 1 - tmp_i;
}
_myswap<T, BPP>((uint8_t*)input + (i*height + j)*BPP, (uint8_t*)input + (I*width + J)*BPP);
}
}
}
/**
* 将输入图像 顺时针原地旋转(In-place matrix transposition)270度<br>
* 图像必须是1字节对齐,多字节对齐的图像旋转可能会造成图像错位
* @param input 输入图像矩阵,size=width*height*bpp
* @param width 图像宽度
* @param height 图像宽度
* @param bpp 每像素字节数(1,2,3,4)
* @return 0-成功,-1 null pointer,-2 invalid argument
*/
int rotate270(void*input,int width,int height,int bpp) noexcept {
switch (bpp) {
case 1:
rotate270<uint8_t>(input, width, height);
return JIU_OK;
case 2:
rotate270<uint16_t>(input, width, height);
return JIU_OK;
case 3:
rotate270<uint8_t,3>(input, width, height);
return JIU_OK;
case 4:
rotate270<uint32_t>(input, width, height);
return JIU_OK;
default:
return JIU_INVALID_ARG;
}
}
完整代码参见gitee仓库:https://gitee.com/l0km/jimgutil/blob/master/native/src/rotate.cpp
在Win32(VS2015),Andriod(CLang),Linux(GCC)平台编译通过并通过测试
NOTE实测表明,这种原地旋转算法是非常慢的,为了节省内存而牺牲了时间,效率上得不偿失。