现在博客上面看到的都是opencv的,opencv还要安装它的组件库太麻烦,linux环境还好,如果上镜像环境,安装是个大麻烦。所以改造成去掉opencv的。 全景图切成六个面
private BufferedImage sideCubeMapImage(int width,int height,int type, int sideId, int sideWidth, int sideHeight,String saveUrl, int[] rgbArray) {
log.error("==========handle " + sideId + " start ===========");
double[][] imageTransform =
{
{0, 0},
{Math.PI / 2, 0},
{Math.PI, 0},
{-Math.PI / 2, 0},
{0, -Math.PI / 2},
{0, Math.PI / 2}
};
// 新的图片坐标点与原始图片坐标的映射关系
double[][] mapx = new double[sideHeight][sideWidth];
double[][] mapy = new double[sideHeight][sideWidth];
//计算相邻ak和相反an的三角形张成球体中心
final double an = Math.sin(Math.PI / 4);
final double ak = Math.cos(Math.PI / 4);
double ftu = imageTransform[sideId][0];
double ftv = imageTransform[sideId][1];
//对于每个像素点计算相应的源坐标,具体计算公式参考球面转立方体映射
for (int y = 0; y < sideHeight; y++) {
for (int x = 0; x < sideWidth; x++) {
//将坐标映射在平面上
float nx = (float) y / (float) sideHeight - 0.5f;
float ny = (float) x / (float) sideWidth - 0.5f;
nx *= 2;
ny *= 2;
nx *= an;
ny *= an;
double u, v;
if (Double.compare(ftv,0) == 0) {
u = Math.atan2(nx, ak);
v = Math.atan2(ny * Math.cos(u), ak);
u += ftu;
} else if (ftv > 0) {
// Bottom face 低面
double d = Math.sqrt(nx * nx + ny * ny);
v = Math.PI / 2 - Math.atan2(d, ak);
u = Math.atan2(ny, nx);
} else {
// Top face 顶面
double d = Math.sqrt(nx * nx + ny * ny);
v = -Math.PI / 2 + Math.atan2(d, ak);
u = Math.atan2(-ny, nx);
}
// Map from angular coordinates to [-1, 1], respectively.
u = u / (Math.PI);
v = v / (Math.PI / 2);
// Warp around, if our coordinates are out of bounds.
while (v < -1) {
v += 2;
u += 1;
}
while (v > 1) {
v -= 2;
u += 1;
}
while (u < -1) {
u += 2;
}
while (u > 1) {
u -= 2;
}
// Map from [-1, 1] to in texture space
u = u / 2.0f + 0.5f;
v = v / 2.0f + 0.5f;
u = u * (width - 1);
v = v * (height - 1);
mapx[y][x]=u;
mapy[y][x]=v;
}
}
int[] newRgbArray = new int[sideWidth * sideHeight];
for(int y = 0; y < sideHeight; y++ ) {
for(int x = 0; x < sideWidth; x++) {
int newx = (int)Math.round(mapx[y][x]);
int newy = (int)Math.round(mapy[y][x]);
// 这里似乎要旋转,暂不清楚为什么
newRgbArray[x * sideHeight + y] = rgbArray[newy * width + newx];
}
}
BufferedImage result = new BufferedImage(sideWidth,sideHeight,type);
result.setRGB(0,0,sideWidth, sideHeight,newRgbArray, 0 ,sideWidth);
// 没有其它格式的前景图,先写死jpg格式
if (sideId == 0) {
bufferSave(saveUrl+File.separator+"f.jpg", result);
} else if (sideId == 1) {
bufferSave(saveUrl+File.separator+"r.jpg", result);
} else if (sideId == 2) {
bufferSave(saveUrl+File.separator+"b.jpg", result);
} else if (sideId == 3) {
bufferSave(saveUrl+File.separator+"l.jpg", result);
} else if (sideId == 4) {
//旋转角度
BufferedImage bufferedImage = new BufferedImage(result.getWidth(), result.getHeight(), result.getType());
Graphics2D graphics = bufferedImage.createGraphics();
graphics.translate(0,0);
graphics.rotate(Math.PI / 2, result.getWidth() / 2.0, result.getHeight() /2.0);
graphics.drawImage(result, null,null);
bufferSave(saveUrl+File.separator+"u.jpg", bufferedImage);
return bufferedImage;
} else {
//旋转角度
BufferedImage bufferedImage = new BufferedImage(result.getWidth(), result.getHeight(), result.getType());
Graphics2D graphics = bufferedImage.createGraphics();
graphics.translate(0,0);
graphics.rotate((-1) * Math.PI / 2, result.getWidth() / 2.0, result.getHeight() /2.0);
graphics.drawImage(result, null,null);
bufferSave(saveUrl+File.separator+"d.jpg", bufferedImage);
return bufferedImage;
}
log.error("==========handle " + sideId + " over ===========");
return result;
}
获取像素点上的三色数组
int[] rgbArray = source.getRGB(0, 0, source.getWidth(), source.getHeight(), null, 0, source.getWidth());
每个面再进行切割成不同层级和像素
private void spiltMatrix(List<BufferedImage> mats,int size,String level,String savePathLocal,int tilesize) throws IOException {
List<String> dirPrefixName= Arrays.asList("l", "f", "r", "b", "u", "d");
// 取余数(获取最后一列的宽高)
int remainder=size % tilesize;
int num=(size-remainder)/tilesize;
// 遍历每个子矩阵
for(int k = 0; k < mats.size(); k++){
BufferedImage mat=mats.get(k);
String dir=dirPrefixName.get(k);
BufferedImage sliceImage;
for (int i = 0; i < num+1; i++) {
for (int j = 0; j < num+1; j++) {
int remI=size-i*tilesize;
int remJ=size-j*tilesize;
sliceImage=mat.getSubimage(j * tilesize, i * tilesize, Math.min(remJ, tilesize), Math.min(remI, tilesize));
BufferedImage outputImage = new BufferedImage(Math.min(remJ, tilesize), Math.min(remI, tilesize), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = outputImage.createGraphics();
// 设置绘图质量
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// 绘制并调整图片大小
g2d.drawImage(sliceImage, 0, 0, Math.min(remJ, tilesize), Math.min(remI, tilesize), null);
g2d.dispose();
// 保存切分后的图片
int numx=i+1;
int numy=j+1;
String jpgName=level+"_"+dir+"_"+numx+"_"+numy;
String finalNme=savePathLocal+File.separator+dir+File.separator+level+File.separator+numx;
//不存在则创建
File packFile = new File(finalNme);
if (!packFile.exists()) {
boolean mkdirs = packFile.mkdirs();
}
ImageIO.write(outputImage,"jpg",new File(finalNme+File.separator+jpgName+".jpg"));
outputImage.flush();
}
}
}
}
已上生产环境,不懂的可以私信我,看完好用记得点赞收藏