SO3Engine
SO3ConversionTools.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#include <boost/thread/thread.hpp>
27
28#include <iostream>
29#include <iomanip>
30
31namespace SO3
32{
33
34 std::string ConversionTools::GetValidImageExtension(std::string ext)
35 {
36 if ((ext == "png") || (ext == "bmp") || (ext == "tga") || (ext == "jpg") || (ext == "hdr"))
37 return ext;
38 else
39 return std::string("png");
40 }
41
42 bool ConversionTools::SaveOgreImage(Ogre::Image &image, boost::filesystem::path &path)
43 {
44 std::string ext = boost::filesystem::extension(path).substr(1);
45
46 int channels = (int)Ogre::PixelUtil::getComponentCount(image.getFormat());
47 int stride = image.getWidth() * (int)Ogre::PixelUtil::getNumElemBytes(image.getFormat());
48
49 if (ext == "png")
50 {
51 image.save(path.generic_string());
52 return true;
53 //return (bool)stbi_write_png(path.generic_string().c_str(), image.getWidth(), image.getHeight(), channels, image.getData(), stride);
54 }
55 else if (ext == "bmp")
56 {
57 return (bool)stbi_write_bmp(path.generic_string().c_str(), image.getWidth(), image.getHeight(), channels, image.getData());
58 }
59 else if (ext == "tga")
60 {
61 return (bool)stbi_write_tga(path.generic_string().c_str(), image.getWidth(), image.getHeight(), channels, image.getData());
62 }
63 else if (ext == "jpg")
64 {
65 return (bool)stbi_write_jpg(path.generic_string().c_str(), image.getWidth(), image.getHeight(), channels, image.getData(), 90);
66 }
67 else if (ext == "hdr")
68 {
69 return (bool)stbi_write_hdr(path.generic_string().c_str(), image.getWidth(), image.getHeight(), channels, (const float*)image.getData());
70 }
71
72 return false;
73 }
74
75 bool ConversionTools::SaveImage(const std::string &filename, int w, int h, int channels, const void *data, int quality)
76 {
77 std::string::size_type index_of_extension = filename.find_last_of('.');
78 std::string ext = filename.substr(index_of_extension + 1);
79
80 if (ext == "png")
81 {
82 return (bool)stbi_write_png(filename.c_str(), w, h, channels, data, w * channels);
83 }
84 else if (ext == "bmp")
85 {
86 return (bool)stbi_write_bmp(filename.c_str(), w, h, channels, data);
87 }
88 else if (ext == "tga")
89 {
90 return (bool)stbi_write_tga(filename.c_str(), w, h, channels, data);
91 }
92 else if (ext == "jpg")
93 {
94 return (bool)stbi_write_jpg(filename.c_str(), w, h, channels, data, quality);
95 }
96 else if (ext == "hdr")
97 {
98 return (bool)stbi_write_hdr(filename.c_str(), w, h, channels, (const float*)data);
99 }
100
101 return false;
102 }
103
104#define FLOATEPSILON std::numeric_limits<double>::epsilon()
105
110 ConversionTools::ConversionTools()
111 {
112 // Forbiden (private). Use static functions instead.
113 }
114
115 int ConversionTools::OgreToScolColorRGBA(const Ogre::ColourValue& ogreColor)
116 {
117 // ATTENTION! RGB and RGBA values are encoded in a different way!
118 // RGBA colour are encoded by scol as "RR GG BB 0A << 1" in memory ("see SCOLParticle.cpp" of the ZooEngine (!)).
119 int a = static_cast<int>(ogreColor.a * CONST_COLOR_ALPHA);
120 int b = static_cast<int>(ogreColor.b * CONST_COLOR);
121 int g = static_cast<int>(ogreColor.g * CONST_COLOR);
122 int r = static_cast<int>(ogreColor.r * CONST_COLOR);
123 return 0x0 + ((a & 0x0000007E) + ((b & 0x000000ff) << 7) + ((g & 0x000000ff) << 15) + ((r & 0x000000ff) << 23));
124 }
125
126 Ogre::ColourValue ConversionTools::ScolToOgreColorRGBA(const int& scolColor)
127 {
128 // ATTENTION! RGB and RGBA values are encoded in a different way!
129 // RGBA colour are encoded by scol as "RR GG BB 0A << 1" in memory ("see SCOLParticle.cpp" of the ZooEngine (!)).
130 float r = ((scolColor >> 23) & 0x000000ff) / CONST_COLOR;
131 float g = ((scolColor >> 15) & 0x000000ff) / CONST_COLOR;
132 float b = ((scolColor >> 7) & 0x000000ff) / CONST_COLOR;
133 float a = ((scolColor) & 0x0000007E) / CONST_COLOR_ALPHA;
134 return Ogre::ColourValue(r, g, b, a);
135 }
136
137 int ConversionTools::OgreToScolColorRGB(const Ogre::ColourValue& ogreColor)
138 {
139 // ATTENTION! RGB and RGBA values are encoded in a different way!
140 // RGB colour are encoded by scol as "00 BB GG RR" in memory (see make_rgb bind, "CSTmakeRGB" in "utils.c" of the scol VM).
141 int b = static_cast<int>(ogreColor.b * CONST_COLOR);
142 int g = static_cast<int>(ogreColor.g * CONST_COLOR);
143 int r = static_cast<int>(ogreColor.r * CONST_COLOR);
144 return 0x0 + (r & 0x000000ff) + ((g & 0x000000ff) << 8) + ((b & 0x000000ff) << 16);
145 }
146
147 Ogre::ColourValue ConversionTools::ScolToOgreColorRGB(const int& scolColor)
148 {
149 // ATTENTION! RGB and RGBA values are encoded in a different way!
150 // RGB colour are encoded by scol as "00 BB GG RR" in memory (see make_rgb bind, "CSTmakeRGB" in "utils.c" of the scol VM).
151 float b = ((scolColor >> 16) & 0x000000ff) / CONST_COLOR;
152 float g = ((scolColor >> 8) & 0x000000ff) / CONST_COLOR;
153 float r = ((scolColor) & 0x000000ff) / CONST_COLOR;
154 return Ogre::ColourValue(r, g, b, 1.0f);
155 }
156
157 void ConversionTools::bitmapToBuff(const int start, const int end, const SConvertBuffer &conv)
158 {
159 size_t srcByte;
160 size_t destByte;
161 int x, y;
162
163 for (y = start; y < end; y++)
164 {
165 for (x = 0; x < conv.width; x++)
166 {
167 srcByte = (x * conv.bpp) + (conv.sbpl * y);
168 destByte = (x * conv.bpp) + (conv.dbpl * y);
169
170 ((Ogre::uint8*)conv.dstBuff)[destByte] = conv.srcBuff[srcByte];
171 ((Ogre::uint8*)conv.dstBuff)[destByte + 1] = conv.srcBuff[srcByte + 1];
172 ((Ogre::uint8*)conv.dstBuff)[destByte + 2] = conv.srcBuff[srcByte + 2];
173 }
174 }
175 }
176
177 void ConversionTools::bitmapsToBuffPf(const int start, const int end, const SConvertBuffer &conv, Ogre::PixelFormat format)
178 {
179 size_t srcByte;
180 size_t destByte;
181 int x, y;
182 Ogre::uint8 r, g, b, a;
183
184 size_t pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
185 for (y = start; y < end; y++)
186 {
187 for (x = 0; x < conv.width; x++)
188 {
189 srcByte = (x * conv.bpp) + (conv.sbpl * y);
190 destByte = (x * pixelSize) + (conv.dbpl * y);
191 r = conv.srcBuff[srcByte];
192 g = conv.srcBuff[srcByte + 1];
193 b = conv.srcBuff[srcByte + 2];
194 a = (conv.srcBuffa != 0) ? conv.srcBuffa[(x + (conv.abpl * y))] : 255;
195
196 Ogre::PixelUtil::packColour(b, g, r, a, format, &((Ogre::uint8*)conv.dstBuff)[destByte]);
197 }
198 }
199 }
200
201 void ConversionTools::bitmapsToScaleBuffNearest(const int start, const int end, const SConvertBuffer &conv, Ogre::PixelFormat format, const int x_ratio, const int y_ratio)
202 {
203 int x, y, i, j;
204 Ogre::uint8 r, g, b, a;
205 size_t destByte;
206
207 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
208 for (i = start; i < end; i++)
209 {
210 for (j = 0; j < conv.width; j++)
211 {
212 destByte = pixelSize * ((i * conv.width) + j);
213 y = (i * y_ratio) >> 16;
214 x = (j * x_ratio) >> 16;
215 r = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp)];
216 g = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 1];
217 b = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 2];
218 if (conv.bpp == 4)
219 a = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 3];
220 else
221 a = (conv.srcBuffa != 0) ? conv.srcBuffa[(conv.abpl * y) + x] : 255;
222
223 Ogre::PixelUtil::packColour(b, g, r, a, format, &((Ogre::uint8*)conv.dstBuff)[destByte]);
224 }
225 }
226 }
227
228 void ConversionTools::bitmapsToScaleBuffBilinear(const int start, const int end, const SConvertBuffer &conv, Ogre::PixelFormat format, const float x_ratio, const float y_ratio)
229 {
230 int x, y, i, j;
231 float w, h;
232 Ogre::uint8 r, g, b, a;
233 Ogre::uint A[4];
234 Ogre::uint B[4];
235 Ogre::uint C[4];
236 Ogre::uint D[4];
237
238 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
239 for (i = start; i < end; i++)
240 {
241 for (j = 0; j < conv.width; j++)
242 {
243 y = (int)(y_ratio * i);
244 x = (int)(x_ratio * j);
245 w = (x_ratio * j) - x;
246 h = (y_ratio * i) - y;
247
248 A[0] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp)];
249 B[0] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + conv.bpp];
250 C[0] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp)];
251 D[0] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + conv.bpp];
252
253 A[1] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 1];
254 B[1] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + conv.bpp + 1];
255 C[1] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + 1];
256 D[1] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + conv.bpp + 1];
257
258 A[2] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 2];
259 B[2] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + conv.bpp + 2];
260 C[2] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + 2];
261 D[2] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + conv.bpp + 2];
262
263 if (conv.bpp == 4)
264 {
265 A[3] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + 3];
266 B[3] = conv.srcBuff[(y * conv.sbpl) + (x * conv.bpp) + conv.bpp + 3];
267 C[3] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + 3];
268 D[3] = conv.srcBuff[((y + 1) * conv.sbpl) + (x * conv.bpp) + conv.bpp + 3];
269 }
270 else
271 {
272 A[3] = (conv.srcBuffa != 0) ? conv.srcBuffa[(y * conv.abpl) + x] : 255;
273 B[3] = (conv.srcBuffa != 0) ? conv.srcBuffa[(y * conv.abpl) + x + 1] : 255;
274 C[3] = (conv.srcBuffa != 0) ? conv.srcBuffa[((y + 1) * conv.abpl) + x] : 255;
275 D[3] = (conv.srcBuffa != 0) ? conv.srcBuffa[((y + 1) * conv.abpl) + x + 1] : 255;
276 }
277
278 r = (Ogre::uint8)(A[0] * (1 - w) * (1 - h) + B[0] * (w)* (1 - h) + C[0] * (h)* (1 - w) + D[0] * (w * h));
279 g = (Ogre::uint8)(A[1] * (1 - w) * (1 - h) + B[1] * (w)* (1 - h) + C[1] * (h)* (1 - w) + D[1] * (w * h));
280 b = (Ogre::uint8)(A[2] * (1 - w) * (1 - h) + B[2] * (w)* (1 - h) + C[2] * (h)* (1 - w) + D[2] * (w * h));
281 a = (Ogre::uint8)(A[3] * (1 - w) * (1 - h) + B[3] * (w)* (1 - h) + C[3] * (h)* (1 - w) + D[3] * (w * h));
282
283 Ogre::PixelUtil::packColour(b, g, r, a, format, &((Ogre::uint8*)conv.dstBuff)[pixelSize * ((i * conv.width) + j)]);
284 }
285 }
286 }
287
288 void ConversionTools::ScolBitmapGetRGB(PtrObjBitmap scolBitmap, unsigned char* buff)
289 {
290 if ((scolBitmap == 0) || (buff == 0))
291 return;
292
293 //Scol bitmap are 32bits aligned
294 int sbpl = scolBitmap->BPL;
295 int dbpl = scolBitmap->TailleW * 3;
296
297 if (sbpl == dbpl)
298 memcpy(buff, scolBitmap->bits, scolBitmap->TailleW * scolBitmap->TailleH * scolBitmap->BytesPP);
299 else
300 {
301 int numthreads = (scolBitmap->TailleH <= 8) ? 1 : std::thread::hardware_concurrency();
302 int rows = scolBitmap->TailleH / numthreads;
303 int extra = scolBitmap->TailleH % numthreads;
304 int start = 0;
305 int end = rows;
306
307 ConversionTools::SConvertBuffer conv(scolBitmap->bits, 0, buff, scolBitmap->TailleW, scolBitmap->TailleH, sbpl, 1, dbpl, scolBitmap->BytesPP);
308
309 std::vector<std::thread> thgroup;
310 for (int t = 1; t <= numthreads; t++)
311 {
312 if (t == numthreads) // last thread does extra rows:
313 end += extra;
314
315 thgroup.emplace_back(std::bind(ConversionTools::bitmapToBuff, start, end, conv));
316
317 start = end;
318 end = start + rows;
319 }
320
321 for (auto& thread : thgroup)
322 thread.join();
323 }
324 }
325
326 void ConversionTools::ScolBitmapGetRGBA(PtrObjBitmap scolBitmap, PtrObjBitmap alphaBitmap, const Ogre::PixelBox& pixelbox)
327 {
328 if ((scolBitmap == 0) || (pixelbox.data == 0))
329 return;
330
331 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(pixelbox.format);
332
333 //Scol bitmap are 32bits aligned
334 int sbpl = scolBitmap->BPL;
335 int abpl = (alphaBitmap != 0) ? alphaBitmap->BPL : 0;
336 int dbpl = pixelSize * pixelbox.rowPitch;
337 uchar* alphaBuff = (alphaBitmap != 0) ? alphaBitmap->bits : 0;
338
339 //no scale needed
340 if ((scolBitmap->TailleW == pixelbox.getWidth()) && ((scolBitmap->TailleH == pixelbox.getHeight())))
341 {
342 if (!alphaBitmap && (sbpl == dbpl) && (pixelbox.format == Ogre::PF_BYTE_BGR))
343 {
344 memcpy(pixelbox.data, scolBitmap->bits, scolBitmap->TailleW * scolBitmap->TailleH * scolBitmap->BytesPP);
345 }
346 else
347 {
348 int numthreads = (scolBitmap->TailleH <= 8) ? 1 : std::thread::hardware_concurrency();
349 int rows = scolBitmap->TailleH / numthreads;
350 int extra = scolBitmap->TailleH % numthreads;
351 int start = 0;
352 int end = rows;
353
354 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, pixelbox.data, scolBitmap->TailleW, scolBitmap->TailleH, sbpl, abpl, dbpl, scolBitmap->BytesPP);
355
356 std::vector<std::thread> thgroup;
357 for (int t = 1; t <= numthreads; t++)
358 {
359 if (t == numthreads) // last thread does extra rows:
360 end += extra;
361
362 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToBuffPf, start, end, conv, pixelbox.format));
363
364 start = end;
365 end = start + rows;
366 }
367
368 for (auto& thread : thgroup)
369 thread.join();
370 }
371 }
372 else
373 {
374#if defined(ANDROID)// || defined(APPLE_IOS)
375 //nearest pixel fast but crappy
376 int x_ratio = (int)(((scolBitmap->TailleW - 1) << 16) / pixelbox.getWidth());
377 int y_ratio = (int)(((scolBitmap->TailleH - 1) << 16) / pixelbox.getHeight());
378
379 int numthreads = (pixelbox.getHeight() <= 8) ? 1 : std::thread::hardware_concurrency();
380 int rows = pixelbox.getHeight() / numthreads;
381 int extra = pixelbox.getHeight() % numthreads;
382 int start = 0;
383 int end = rows;
384
385 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, pixelbox.data, pixelbox.getWidth(), pixelbox.getHeight(), sbpl, abpl, dbpl, scolBitmap->BytesPP);
386
387 std::vector<std::thread> thgroup;
388 for (int t = 1; t <= numthreads; t++)
389 {
390 if (t == numthreads) // last thread does extra rows:
391 end += extra;
392
393 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffNearest, start, end, conv, pixelbox.format, x_ratio, y_ratio));
394
395 start = end;
396 end = start + rows;
397 }
398
399 for (auto& thread : thgroup)
400 thread.join();
401#else
402 //bilinear pixel
403 float x_ratio = (float)(scolBitmap->TailleW - 1) / (float)pixelbox.getWidth();
404 float y_ratio = (float)(scolBitmap->TailleH - 1) / (float)pixelbox.getHeight();
405
406 int numthreads = (pixelbox.getHeight() <= 8) ? 1 : std::thread::hardware_concurrency();
407 int rows = pixelbox.getHeight() / numthreads;
408 int extra = pixelbox.getHeight() % numthreads;
409 int start = 0;
410 int end = rows;
411
412 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, pixelbox.data, pixelbox.getWidth(), pixelbox.getHeight(), sbpl, abpl, dbpl, scolBitmap->BytesPP);
413
414 std::vector<std::thread> thgroup;
415 for (int t = 1; t <= numthreads; t++)
416 {
417 if (t == numthreads) // last thread does extra rows:
418 end += extra;
419
420 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffBilinear, start, end, conv, pixelbox.format, x_ratio, y_ratio));
421
422 start = end;
423 end = start + rows;
424 }
425
426 for (auto& thread : thgroup)
427 thread.join();
428#endif
429 }
430 }
431
432 void ConversionTools::ScolBitmapGetRGBA(PtrObjBitmap scolBitmap, PtrObjBitmap alphaBitmap, void* buff)
433 {
434 if ((scolBitmap == 0) || (buff == 0))
435 return;
436
437 //Scol bitmap are 32bits aligned
438 int sbpl = scolBitmap->BPL;
439 int abpl = (alphaBitmap != 0) ? alphaBitmap->BPL : 0;
440 int dbpl = scolBitmap->TailleW;
441 uchar* alphaBuff = (alphaBitmap != 0) ? alphaBitmap->bits : 0;
442
443 int numthreads = (scolBitmap->TailleH <= 8) ? 1 : std::thread::hardware_concurrency();
444 int rows = scolBitmap->TailleH / numthreads;
445 int extra = scolBitmap->TailleH % numthreads;
446 int start = 0;
447 int end = rows;
448
449 Ogre::PixelFormat format = Ogre::PF_BYTE_BGRA;
450 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, buff, scolBitmap->TailleW, scolBitmap->TailleH, sbpl, abpl, dbpl, scolBitmap->BytesPP);
451
452 std::vector<std::thread> thgroup;
453 for (int t = 1; t <= numthreads; t++)
454 {
455 if (t == numthreads) // last thread does extra rows:
456 end += extra;
457
458 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToBuffPf, start, end, conv, format));
459
460 start = end;
461 end = start + rows;
462 }
463
464 for (auto& thread : thgroup)
465 thread.join();
466 }
467
468 void ConversionTools::ScolBitmapGetRGBA(PtrObjBitmap scolBitmap, PtrObjBitmap alphaBitmap, Ogre::PixelFormat format, void* buff)
469 {
470 if ((scolBitmap == 0) || (buff == 0))
471 return;
472
473 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
474
475 //Scol bitmap are 32bits aligned
476 int sbpl = scolBitmap->BPL;
477 int abpl = (alphaBitmap != 0) ? alphaBitmap->BPL : 0;
478 int dbpl = pixelSize * scolBitmap->TailleW;
479 uchar* alphaBuff = (alphaBitmap != 0) ? alphaBitmap->bits : 0;
480
481 if (!alphaBitmap && (sbpl == dbpl) && (format == Ogre::PF_BYTE_BGR))
482 {
483 memcpy(buff, scolBitmap->bits, scolBitmap->TailleW * scolBitmap->TailleH * scolBitmap->BytesPP);
484 }
485 else
486 {
487 int numthreads = (scolBitmap->TailleH <= 8) ? 1 : std::thread::hardware_concurrency();
488 int rows = scolBitmap->TailleH / numthreads;
489 int extra = scolBitmap->TailleH % numthreads;
490 int start = 0;
491 int end = rows;
492
493 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, buff, scolBitmap->TailleW, scolBitmap->TailleH, sbpl, abpl, dbpl, scolBitmap->BytesPP);
494
495 std::vector<std::thread> thgroup;
496 for (int t = 1; t <= numthreads; t++)
497 {
498 if (t == numthreads) // last thread does extra rows:
499 end += extra;
500
501 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToBuffPf, start, end, conv, format));
502
503 start = end;
504 end = start + rows;
505 }
506
507 for (auto& thread : thgroup)
508 thread.join();
509 }
510 }
511
512 void ConversionTools::ScolBitmapGetRGBA(PtrObjBitmap scolBitmap, PtrObjBitmap alphaBitmap, unsigned int nwidth, unsigned int nheight, Ogre::PixelFormat format, void* buff)
513 {
514 if ((scolBitmap == 0) || (buff == 0))
515 return;
516
517 //no scale needed
518 if ((scolBitmap->TailleW == nwidth) && ((scolBitmap->TailleH == nheight)))
519 return ScolBitmapGetRGBA(scolBitmap, alphaBitmap, format, buff);
520
521 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
522
523 //Scol bitmap are 32bits aligned
524 int sbpl = scolBitmap->BPL;
525 int abpl = (alphaBitmap != 0) ? alphaBitmap->BPL : 0;
526 int dbpl = nwidth * pixelSize;
527 uchar* alphaBuff = (alphaBitmap != 0) ? alphaBitmap->bits : 0;
528
529#if defined(ANDROID)// || defined(APPLE_IOS)
530 //nearest pixel fast but crappy
531 int x_ratio = (int)(((scolBitmap->TailleW - 1) << 16) / nwidth);
532 int y_ratio = (int)(((scolBitmap->TailleH - 1) << 16) / nheight);
533
534 int numthreads = (nheight <= 8) ? 1 : std::thread::hardware_concurrency();
535 int rows = nheight / numthreads;
536 int extra = nheight % numthreads;
537 int start = 0;
538 int end = rows;
539
540 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, buff, nwidth, nheight, sbpl, abpl, dbpl, scolBitmap->BytesPP);
541
542 std::vector<std::thread> thgroup;
543 for (int t = 1; t <= numthreads; t++)
544 {
545 if (t == numthreads) // last thread does extra rows:
546 end += extra;
547
548 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffNearest, start, end, conv, format, x_ratio, y_ratio));
549
550 start = end;
551 end = start + rows;
552 }
553
554 for (auto& thread : thgroup)
555 thread.join();
556#else
557 //bilinear pixel
558 float x_ratio = (float)(scolBitmap->TailleW - 1) / (float)nwidth;
559 float y_ratio = (float)(scolBitmap->TailleH - 1) / (float)nheight;
560
561 int numthreads = (nheight <= 8) ? 1 : std::thread::hardware_concurrency();
562 int rows = nheight / numthreads;
563 int extra = nheight % numthreads;
564 int start = 0;
565 int end = rows;
566
567 ConversionTools::SConvertBuffer conv(scolBitmap->bits, alphaBuff, buff, nwidth, nheight, sbpl, abpl, dbpl, scolBitmap->BytesPP);
568
569 std::vector<std::thread> thgroup;
570 for (int t = 1; t <= numthreads; t++)
571 {
572 if (t == numthreads) // last thread does extra rows:
573 end += extra;
574
575 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffBilinear, start, end, conv, format, x_ratio, y_ratio));
576
577 start = end;
578 end = start + rows;
579 }
580
581 for (auto& thread : thgroup)
582 thread.join();
583#endif
584}
585
586
587 void ConversionTools::ScolBitmapGetRGBA(const uchar* sbuff, const int swidth, const int sheight, const int sbpp, const int sbpl, unsigned int nwidth, unsigned int nheight, Ogre::PixelFormat format, void* buff)
588 {
589 if ((sbuff == 0) || (buff == 0))
590 return;
591
592 unsigned char pixelSize = Ogre::PixelUtil::getNumElemBytes(format);
593 int dbpl = nwidth * pixelSize;
594
595#if defined(ANDROID)// || defined(APPLE_IOS)
596 //nearest pixel fast but crappy
597 int x_ratio = (int)(((swidth - 1) << 16) / nwidth);
598 int y_ratio = (int)(((sheight - 1) << 16) / nheight);
599
600 int numthreads = (nheight <= 8) ? 1 : std::thread::hardware_concurrency();
601 int rows = nheight / numthreads;
602 int extra = nheight % numthreads;
603 int start = 0;
604 int end = rows;
605
606 ConversionTools::SConvertBuffer conv(sbuff, 0, buff, nwidth, nheight, sbpl, 0, dbpl, sbpp);
607
608 std::vector<std::thread> thgroup;
609 for (int t = 1; t <= numthreads; t++)
610 {
611 if (t == numthreads) // last thread does extra rows:
612 end += extra;
613
614 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffNearest, start, end, conv, format, x_ratio, y_ratio));
615
616 start = end;
617 end = start + rows;
618 }
619
620 for (auto& thread : thgroup)
621 thread.join();
622#else
623 //bilinear pixel
624 float x_ratio = (float)(swidth - 1) / (float)nwidth;
625 float y_ratio = (float)(sheight - 1) / (float)nheight;
626
627 int numthreads = (nheight <= 8) ? 1 : std::thread::hardware_concurrency();
628 int rows = nheight / numthreads;
629 int extra = nheight % numthreads;
630 int start = 0;
631 int end = rows;
632
633 ConversionTools::SConvertBuffer conv(sbuff, 0, buff, nwidth, nheight, sbpl, 0, dbpl, sbpp);
634
635 std::vector<std::thread> thgroup;
636 for (int t = 1; t <= numthreads; t++)
637 {
638 if (t == numthreads) // last thread does extra rows:
639 end += extra;
640
641 thgroup.emplace_back(std::bind(ConversionTools::bitmapsToScaleBuffBilinear, start, end, conv, format, x_ratio, y_ratio));
642
643 start = end;
644 end = start + rows;
645 }
646
647 for (auto& thread : thgroup)
648 thread.join();
649#endif
650 }
651
652 bool ConversionTools::fequal(float a, float b)
653 {
654 return (fabs(a - b) < FLOATEPSILON);
655 }
656
657 double ConversionTools::GetDecExp(int nDec)
658 {
659 double dRet;
660 double ad[6] = { 1.,10.,100.,1000.,10000.,100000. };
661
662 if (nDec >= 0 && nDec <= 5) return(ad[nDec]);
663 dRet = ad[5];
664 for (int i = 1; i < nDec - 4; i++) dRet *= 10.;
665 return floor(dRet);
666 }
667
668 double ConversionTools::Roundn(double dValue, int nDecimales)
669 {
670 if (nDecimales < 0 || dValue == 0.) return(dValue);
671
672 double dSeuil = (dValue < 0. ? -.5 : .5);
673 double dExp = GetDecExp(nDecimales);
674 double dCalc = (((dValue*dExp) + dSeuil));
675
676 if (dValue < 0.)
677 return(ceil(dCalc) / dExp);
678 else
679 return(floor(dCalc) / dExp);
680 }
681
683 {
684 return static_cast<float>(Roundn((double)val, 6));
685 }
686
688 {
689 return Roundn(val, 6);
690 }
691
693 {
694 float ret = static_cast<float>(Roundn((double)val, 6));
695 std::stringstream stream;
696 stream << std::fixed << std::setprecision(6) << ret;
697 return stream.str();
698 }
699
701 {
702 double ret = Roundn(val, 6);
703 std::stringstream stream;
704 stream << std::fixed << std::setprecision(6) << ret;
705 return stream.str();
706 }
707}
int nheight
Definition SO3SCOL.cpp:5095
SCOL_EXPORT int cbmachine w
Definition SO3SCOL.cpp:5150
int nwidth
Definition SO3SCOL.cpp:5094
static bool SaveImage(const std::string &filename, int w, int h, int comp, const void *data, int quality=90)
static void bitmapsToScaleBuffNearest(const int start, const int end, const SConvertBuffer &conv, const Ogre::PixelFormat format, const int x_ratio, const int y_ratio)
static std::string GetValidImageExtension(std::string ext)
static Ogre::ColourValue ScolToOgreColorRGB(const int &scolColor)
static Ogre::ColourValue ScolToOgreColorRGBA(const int &scolColor)
static float formatFloat(float val)
static bool SaveOgreImage(Ogre::Image &image, boost::filesystem::path &path)
static std::string formatFloatToString(double val)
static void bitmapsToScaleBuffBilinear(const int start, const int end, const SConvertBuffer &conv, const Ogre::PixelFormat format, const float x_ratio, const float y_ratio)
static int OgreToScolColorRGBA(const Ogre::ColourValue &ogreColor)
static void bitmapsToBuffPf(const int start, const int end, const SConvertBuffer &conv, const Ogre::PixelFormat format)
static bool fequal(float a, float b)
static void ScolBitmapGetRGB(PtrObjBitmap scolBitmap, unsigned char *buff)
static void bitmapToBuff(const int start, const int end, const SConvertBuffer &conv)
static void ScolBitmapGetRGBA(PtrObjBitmap scolBitmap, PtrObjBitmap alphaBitmap, const Ogre::PixelBox &pixelbox)
static int OgreToScolColorRGB(const Ogre::ColourValue &ogreColor)
static double Roundn(double dValue, int nDecimales)
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data)
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)