mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #881 from Atlante45/png_import_cleanup
Png import cleanup
This commit is contained in:
commit
56f6b12fcd
3 changed files with 51 additions and 301 deletions
|
@ -1,242 +0,0 @@
|
|||
//
|
||||
// SquarePixelMap.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Tomáš Horáček on 6/25/13.
|
||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SquarePixelMap.h"
|
||||
|
||||
#define CHILD_COORD_X_IS_1 0x1
|
||||
#define CHILD_COORD_Y_IS_1 0x2
|
||||
#define ALPHA_CHANNEL_RANGE_FLOAT 256.f
|
||||
#define ALPHA_CHANNEL_BIT_OFFSET 24
|
||||
#define RED_CHANNEL_BIT_OFFSET 16
|
||||
#define GREEN_CHANNEL_BIT_OFFSET 8
|
||||
|
||||
unsigned int numberOfBitsForSize(unsigned int size) {
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size--;
|
||||
|
||||
unsigned int ans = 1;
|
||||
while (size >>= 1) {
|
||||
ans++;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
struct PixelQuadTreeCoordinates {
|
||||
unsigned int x;
|
||||
unsigned int y;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
class PixelQuadTreeNode {
|
||||
public:
|
||||
PixelQuadTreeCoordinates _coord;
|
||||
uint32_t _color; // undefined value for _allChildrenHasSameColor = false
|
||||
bool _allChildrenHasSameColor;
|
||||
uint8_t _minimumNeighbourhoodAplha;
|
||||
|
||||
// 0 x -> 1
|
||||
// +---+---+
|
||||
// y | 0 | 1 | <- child index
|
||||
// | +---+---+
|
||||
// v | 2 | 3 |
|
||||
// +---+---+
|
||||
// 1
|
||||
PixelQuadTreeNode* _children[4];
|
||||
|
||||
PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap);
|
||||
~PixelQuadTreeNode() {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
delete _children[i];
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void updateChildCoordinates(int i, PixelQuadTreeCoordinates& childCoord) {
|
||||
childCoord.x = _coord.x;
|
||||
childCoord.y = _coord.y;
|
||||
|
||||
if (i & CHILD_COORD_X_IS_1) {
|
||||
childCoord.x += childCoord.size;
|
||||
}
|
||||
if (i & CHILD_COORD_Y_IS_1) {
|
||||
childCoord.y += childCoord.size;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasAllChildrenSameColor() {
|
||||
return false; //turn off import voxel grouping
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (!_children[i]->_allChildrenHasSameColor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t firstColor = _children[0]->_color;
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (firstColor != _children[i]->_color) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
PixelQuadTreeNode::PixelQuadTreeNode(PixelQuadTreeCoordinates coord, SquarePixelMap* pixelMap) : _coord(coord), _minimumNeighbourhoodAplha(-1) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_children[i] = NULL;
|
||||
}
|
||||
|
||||
if (_coord.size == 1) {
|
||||
_color = pixelMap->getPixelAt(_coord.x, _coord.y);
|
||||
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x + 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x - 1, _coord.y), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y + 1), _minimumNeighbourhoodAplha);
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(pixelMap->getAlphaAt(_coord.x, _coord.y - 1), _minimumNeighbourhoodAplha);
|
||||
|
||||
_allChildrenHasSameColor = true;
|
||||
} else {
|
||||
PixelQuadTreeCoordinates childCoord = PixelQuadTreeCoordinates();
|
||||
childCoord.size = _coord.size / 2;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
this->updateChildCoordinates(i, childCoord);
|
||||
|
||||
|
||||
if (childCoord.x < pixelMap->dimension() &&
|
||||
childCoord.y < pixelMap->dimension()) {
|
||||
|
||||
_children[i] = new PixelQuadTreeNode(childCoord, pixelMap);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hasAllChildrenSameColor()) {
|
||||
_allChildrenHasSameColor = true;
|
||||
_color = _children[0]->_color;
|
||||
|
||||
_minimumNeighbourhoodAplha = _children[0]->_minimumNeighbourhoodAplha;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_minimumNeighbourhoodAplha = std::min<uint8_t>(_children[i]->_minimumNeighbourhoodAplha, _minimumNeighbourhoodAplha);
|
||||
delete _children[i];
|
||||
_children[i] = NULL;
|
||||
}
|
||||
} else {
|
||||
_allChildrenHasSameColor = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SquarePixelMap::SquarePixelMap(const uint32_t* pixels, int dimension) : _rootPixelQuadTreeNode(NULL) {
|
||||
_data = new SquarePixelMapData();
|
||||
_data->dimension = dimension;
|
||||
_data->reference_counter = 1;
|
||||
|
||||
size_t pixels_size = dimension * dimension;
|
||||
_data->pixels = new uint32_t[pixels_size];
|
||||
memcpy((void*)_data->pixels, (void*)pixels, sizeof(uint32_t) * pixels_size);
|
||||
}
|
||||
|
||||
SquarePixelMap::SquarePixelMap(const SquarePixelMap& other) {
|
||||
this->_data = other._data;
|
||||
this->_data->reference_counter++;
|
||||
}
|
||||
|
||||
SquarePixelMap::~SquarePixelMap() {
|
||||
delete _rootPixelQuadTreeNode;
|
||||
|
||||
if (--_data->reference_counter == 0) {
|
||||
delete _data->pixels;
|
||||
delete _data;
|
||||
}
|
||||
}
|
||||
|
||||
void SquarePixelMap::addVoxelsToVoxelTree(VoxelTree* voxelTree) {
|
||||
this->generateRootPixelQuadTreeNode();
|
||||
this->createVoxelsFromPixelQuadTreeToVoxelTree(_rootPixelQuadTreeNode, voxelTree);
|
||||
}
|
||||
|
||||
int SquarePixelMap::dimension() {
|
||||
return _data->dimension;
|
||||
}
|
||||
|
||||
uint32_t SquarePixelMap::getPixelAt(unsigned int x, unsigned int y) {
|
||||
return _data->pixels[x + y * _data->dimension];
|
||||
}
|
||||
|
||||
uint8_t SquarePixelMap::getAlphaAt(int x, int y) {
|
||||
int max_coord = this->dimension() - 1;
|
||||
|
||||
if (x < 0 || y < 0 || x > max_coord || y > max_coord) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this->getPixelAt(x, y) >> ALPHA_CHANNEL_BIT_OFFSET;
|
||||
}
|
||||
|
||||
void SquarePixelMap::generateRootPixelQuadTreeNode() {
|
||||
delete _rootPixelQuadTreeNode;
|
||||
|
||||
PixelQuadTreeCoordinates rootNodeCoord = PixelQuadTreeCoordinates();
|
||||
rootNodeCoord.size = 1 << numberOfBitsForSize(_data->dimension);
|
||||
rootNodeCoord.x = rootNodeCoord.y = 0;
|
||||
|
||||
_rootPixelQuadTreeNode = new PixelQuadTreeNode(rootNodeCoord, this);
|
||||
}
|
||||
|
||||
void SquarePixelMap::createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree) {
|
||||
if (pixelQuadTreeNode->_allChildrenHasSameColor) {
|
||||
VoxelDetail voxel = this->getVoxelDetail(pixelQuadTreeNode);
|
||||
|
||||
unsigned char minimumNeighbourhoodAplha = std::max<int>(0, pixelQuadTreeNode->_minimumNeighbourhoodAplha - 1);
|
||||
|
||||
float minimumNeighbourhoodY = voxel.s * (floor(minimumNeighbourhoodAplha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||
|
||||
do {
|
||||
voxelTree->createVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.red, voxel.green, voxel.blue, true);
|
||||
} while ((voxel.y -= voxel.s) > minimumNeighbourhoodY);
|
||||
} else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
PixelQuadTreeNode* child = pixelQuadTreeNode->_children[i];
|
||||
if (child) {
|
||||
this->createVoxelsFromPixelQuadTreeToVoxelTree(child, voxelTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoxelDetail SquarePixelMap::getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode) {
|
||||
VoxelDetail voxel = VoxelDetail();
|
||||
|
||||
uint32_t color = pixelQuadTreeNode->_color;
|
||||
unsigned char alpha = std::max<int>(0, (color >> ALPHA_CHANNEL_BIT_OFFSET) - 1);
|
||||
|
||||
voxel.red = color >> RED_CHANNEL_BIT_OFFSET;
|
||||
voxel.green = color >> GREEN_CHANNEL_BIT_OFFSET;
|
||||
voxel.blue = color;
|
||||
|
||||
|
||||
float rootSize = _rootPixelQuadTreeNode->_coord.size;
|
||||
|
||||
voxel.s = pixelQuadTreeNode->_coord.size / rootSize;
|
||||
voxel.y = voxel.s * (floor(alpha / (ALPHA_CHANNEL_RANGE_FLOAT * voxel.s)) + 0.5);
|
||||
voxel.x = pixelQuadTreeNode->_coord.x / rootSize + voxel.s / 2;
|
||||
voxel.z = pixelQuadTreeNode->_coord.y / rootSize + voxel.s / 2;
|
||||
|
||||
return voxel;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// SquarePixelMap.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Tomáš Horáček on 6/25/13.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__SquarePixelMap__
|
||||
#define __hifi__SquarePixelMap__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "VoxelTree.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
class PixelQuadTreeNode;
|
||||
|
||||
struct SquarePixelMapData {
|
||||
const uint32_t* pixels;
|
||||
int dimension;
|
||||
int reference_counter;
|
||||
};
|
||||
|
||||
class SquarePixelMap {
|
||||
public:
|
||||
SquarePixelMap(const uint32_t* pixels, int dimension);
|
||||
SquarePixelMap(const SquarePixelMap& other);
|
||||
~SquarePixelMap();
|
||||
|
||||
void addVoxelsToVoxelTree(VoxelTree* voxelTree);
|
||||
|
||||
int dimension();
|
||||
uint32_t getPixelAt(unsigned int x, unsigned int y);
|
||||
uint8_t getAlphaAt(int x, int y);
|
||||
private:
|
||||
SquarePixelMapData* _data;
|
||||
PixelQuadTreeNode* _rootPixelQuadTreeNode;
|
||||
|
||||
void generateRootPixelQuadTreeNode();
|
||||
void createVoxelsFromPixelQuadTreeToVoxelTree(PixelQuadTreeNode* pixelQuadTreeNode, VoxelTree* voxelTree);
|
||||
VoxelDetail getVoxelDetail(PixelQuadTreeNode* pixelQuadTreeNode);
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__SquarePixelMap__) */
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QImage>
|
||||
#include <QRgb>
|
||||
|
||||
#include "CoverageMap.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "OctalCode.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "SharedUtil.h"
|
||||
#include "SquarePixelMap.h"
|
||||
#include "Tags.h"
|
||||
#include "ViewFrustum.h"
|
||||
#include "VoxelConstants.h"
|
||||
|
@ -1587,25 +1587,61 @@ bool VoxelTree::readFromSVOFile(const char* fileName) {
|
|||
}
|
||||
|
||||
bool VoxelTree::readFromSquareARGB32Pixels(const char* filename) {
|
||||
QImage pngImage = QImage(filename);
|
||||
if (pngImage.height() != pngImage.width()) {
|
||||
qDebug("ERROR: Bad PNG size: height != width.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
emit importSize(1.0f, 1.0f, 1.0f);
|
||||
emit importProgress(0);
|
||||
|
||||
const uint32_t* pixels;
|
||||
if (pngImage.format() == QImage::Format_ARGB32) {
|
||||
pixels = reinterpret_cast<const uint32_t*>(pngImage.constBits());
|
||||
} else {
|
||||
QImage tmp = pngImage.convertToFormat(QImage::Format_ARGB32);
|
||||
pixels = reinterpret_cast<const uint32_t*>(tmp.constBits());
|
||||
int minAlpha = INT_MAX;
|
||||
|
||||
QImage pngImage = QImage(filename);
|
||||
|
||||
for (int x = 0; x < pngImage.width() * pngImage.height(); ++x) {
|
||||
minAlpha = std::min(qAlpha(pngImage.color(x)) , minAlpha);
|
||||
}
|
||||
|
||||
SquarePixelMap pixelMap = SquarePixelMap(pixels, pngImage.height());
|
||||
pixelMap.addVoxelsToVoxelTree(this);
|
||||
int maxSize = std::max(pngImage.width(), pngImage.height());
|
||||
|
||||
int scale = 1;
|
||||
while (maxSize > scale) {scale *= 2;}
|
||||
float size = 1.0f / scale;
|
||||
|
||||
QRgb pixel;
|
||||
int minNeighborhoodAlpha;
|
||||
|
||||
for (int i = 0; i < pngImage.width(); ++i) {
|
||||
for (int j = 0; j < pngImage.height(); ++j) {
|
||||
emit importProgress((100 * (i * pngImage.height() + j)) /
|
||||
(pngImage.width() * pngImage.height()));
|
||||
|
||||
pixel = pngImage.pixel(i, j);
|
||||
minNeighborhoodAlpha = qAlpha(pixel) - 1;
|
||||
|
||||
if (i != 0) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i - 1, j)));
|
||||
}
|
||||
if (j != 0) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j - 1)));
|
||||
}
|
||||
if (i < pngImage.width() - 1) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i + 1, j)));
|
||||
}
|
||||
if (j < pngImage.height() - 1) {
|
||||
minNeighborhoodAlpha = std::min(minNeighborhoodAlpha, qAlpha(pngImage.pixel(i, j + 1)));
|
||||
}
|
||||
|
||||
while (qAlpha(pixel) > minNeighborhoodAlpha) {
|
||||
++minNeighborhoodAlpha;
|
||||
createVoxel(i * size,
|
||||
(minNeighborhoodAlpha - minAlpha) * size,
|
||||
j * size,
|
||||
size,
|
||||
qRed(pixel),
|
||||
qGreen(pixel),
|
||||
qBlue(pixel),
|
||||
true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
emit importProgress(100);
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue