25 #include "ImageDistribution.hh"
35 vector<Image<unsigned char>*> inputPtrs;
37 for(
unsigned int i=0; i<inputImages.size(); i++){
38 inputPtrs.push_back(&inputImages[i]);
41 MapImagesToFixedSize(inputPtrs,
51 cout <<
"mapping to fixed size..." << endl;
55 imagePositionsPixel.clear();
58 if (inputImages.size() == 0)
return;
60 BIASASSERT(inputImages[0]->GetWidth() > 0)
61 BIASASSERT(inputImages[0]->GetHeight() > 0)
62 BIASASSERT(outputImage.
GetWidth() > 0)
66 const unsigned int &numImages = inputImages.size();
67 const unsigned int &widthIn = inputImages[0]->GetWidth();
68 const unsigned int &heightIn = inputImages[0]->GetHeight();
70 const unsigned int &widthOut = outputImage.
GetWidth();
71 const unsigned int &heightOut = outputImage.
GetHeight();
78 ComputeGridAndScale(numImages, widthIn, heightIn, widthOut, heightOut,
79 numCols, numRows, scale);
82 vector<Vector2<unsigned int> > imPosGrid;
83 vector<vector<int> > imageIndices;
85 ComputeImagePositions(numImages, widthIn, heightIn, numRows, numCols, scale,
86 imPosGrid, imagePositionsPixel, imageIndices);
89 unsigned char* outputImData = outputImage.
GetImageData();
91 float widthInScaled = float(widthIn) * scale;
92 float heightInScaled = float(heightIn) * scale;
94 for (
unsigned int y = 0; y < heightOut; ++y) {
96 if (y >= (numRows * heightInScaled)) {
break; }
99 const unsigned int row = (unsigned)floor(
float(y) / heightInScaled);
101 for (
unsigned int x = 0; x < widthOut; ++x) {
103 if (x >= (numCols * widthInScaled)) {
break; }
106 const unsigned int col = (unsigned)floor(
float(x) / widthInScaled);
109 const int curImageIndex = imageIndices[col][row];
111 if (curImageIndex == -1) {
116 const unsigned int xImage = (unsigned)rint((x - col * widthInScaled) / scale);
117 const unsigned int yImage = (unsigned)rint((y - row * heightInScaled) / scale);
119 const unsigned int inputOffset
121 * inputImages[curImageIndex]->GetWidth()
122 * inputImages[curImageIndex]->GetChannelCount())
124 * inputImages[curImageIndex]->GetChannelCount());
126 const unsigned int outputOffset
134 const unsigned char* inputImData
135 = inputImages[curImageIndex]->GetImageData();
138 outputImData[outputOffset + c] = inputImData[inputOffset + c];
150 vector<Image<unsigned char>*> inputPtrs;
152 for(
unsigned int i=0; i<inputImages.size(); i++){
153 inputPtrs.push_back(&inputImages[i]);
156 MapImagesToSquare(inputPtrs,
158 imagePositionsPixel);
165 cout <<
"mapping to square (scale is ignored)..." << endl;
169 const unsigned int numImages = inputImages.size();
170 const unsigned int widthIn = inputImages[0]->GetWidth();
171 const unsigned int heightIn = inputImages[0]->GetHeight();
174 const unsigned int widthOut = 1;
175 const unsigned int heightOut = 1;
178 unsigned int numCols;
179 unsigned int numRows;
182 ComputeGridAndScale(numImages, widthIn, heightIn, widthOut, heightOut,
183 numCols, numRows, scale);
186 vector<Vector2<unsigned int> > imPosGrid;
187 vector<Vector2<unsigned int> > imPosPixel;
188 vector<vector<int> > imageIndices;
190 ComputeImagePositions(numImages, widthIn, heightIn, numRows, numCols, scale,
191 imPosGrid, imPosPixel, imageIndices);
194 const unsigned int edgeLength = max(numCols * widthIn, numRows * heightIn);
196 outputImage.
Init(edgeLength, edgeLength, inputImages[0]->GetChannelCount());
199 unsigned char* outputImData = outputImage.
GetImageData();
201 for (
size_t imageCount = 0; imageCount < numImages; ++imageCount) {
202 const unsigned char* inputImData = inputImages[imageCount]->GetImageData();
204 const unsigned int xOffset = imPosGrid[imageCount][0] * widthIn;
205 const unsigned int yOffset = imPosGrid[imageCount][1] * heightIn;
207 for (
unsigned int y = 0; y < inputImages[imageCount]->GetHeight(); ++y) {
208 for (
unsigned int x = 0; x < inputImages[imageCount]->GetWidth(); ++x) {
209 const unsigned int inputOffset
211 * inputImages[imageCount]->GetWidth()
212 * inputImages[imageCount]->GetChannelCount())
214 * inputImages[imageCount]->GetChannelCount());
216 const unsigned int outputOffset
223 for (
unsigned int c = 0; c < inputImages[imageCount]->GetChannelCount(); ++c) {
224 outputImData[outputOffset + c] = inputImData[inputOffset + c];
231 ComputeImagePositions(numImages, widthIn, heightIn, numRows, numCols, 1.0,
232 imPosGrid, imagePositionsPixel, imageIndices);
236 void ImageDistribution::ComputeGridAndScale(
unsigned int numImages,
237 unsigned int widthIn,
238 unsigned int heightIn,
239 unsigned int widthOut,
240 unsigned int heightOut,
241 unsigned int &numCols,
242 unsigned int &numRows,
250 const float numImagesF = (float)numImages;
251 const float widthInF = (float)widthIn;
252 const float heightInF = (float)heightIn;
254 const float widthOutF = (float)widthOut;
255 const float heightOutF = (float)heightOut;
258 for (
float tmpNumCols = numImagesF; tmpNumCols >= 1.0; --tmpNumCols) {
259 const float tmpNumRows = ceil(numImagesF / tmpNumCols);
262 const float tmpScale = min(widthOutF / (tmpNumCols * widthInF),
263 heightOutF / (tmpNumRows * heightInF));
265 if (tmpScale > scale) {
266 numCols = (
unsigned int)tmpNumCols;
267 numRows = (
unsigned int)tmpNumRows;
272 cout <<
"taking " << numCols <<
"x" << numRows <<
" @ "
273 << (scale * 100.0) <<
"%" << endl;
276 void ImageDistribution::ComputeImagePositions(
unsigned int numImages,
277 unsigned int widthIn,
278 unsigned int heightIn,
279 unsigned int numRows,
280 unsigned int numCols,
284 vector<vector<int> > &imageIndices)
287 const float numImagesF = (float)numImages;
288 const float widthInF = (float)widthIn;
289 const float heightInF = (float)heightIn;
291 const float numColsF = (float)numCols;
294 imageIndices.clear();
296 imageIndices.resize(numCols);
297 for (
unsigned int colCount = 0; colCount < numCols; ++colCount) {
298 imageIndices[colCount].resize(numRows, -1);
302 imagePositionsGrid.clear();
303 imagePositionsGrid.reserve(
size_t(numImagesF));
304 imagePositionsPixel.clear();
305 imagePositionsPixel.reserve(
size_t(numImagesF));
307 for (
size_t imageCount = 0; imageCount < size_t(numImagesF); ++imageCount) {
309 const unsigned int row = (
unsigned int)floor(
float(imageCount) / numColsF);
310 const unsigned int col = (
unsigned int)(imageCount - (row * numColsF));
315 (
unsigned)rint(row * heightInF * scale)));
316 imageIndices[col][row] = imageCount;
318 cout <<
"image " << imageCount <<
" is at "
319 << imagePositionsGrid[imageCount][0] <<
"x" << imagePositionsGrid[imageCount][1]
321 << imagePositionsPixel[imageCount][0] <<
"," << imagePositionsPixel[imageCount][1]
unsigned int GetWidth() const
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
void SetZero()
zeroes the image