Blue Brain BioExplorer
ImageUtils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2024, EPFL/Blue Brain Project
3  * All rights reserved. Do not distribute without permission.
4  *
5  * This file is part of Blue Brain BioExplorer <https://github.com/BlueBrain/BioExplorer>
6  *
7  * This library is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Lesser General Public License version 3.0 as published
9  * by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "ImageUtils.h"
22 
23 #include "base64/base64.h"
24 
25 namespace
26 {
27 template <class T>
28 inline void INPLACESWAP(T& a, T& b)
29 {
30  a ^= b;
31  b ^= a;
32  a ^= b;
33 }
34 } // namespace
35 namespace core
36 {
37 namespace freeimage
38 {
39 // https://github.com/imazen/freeimage/blob/master/Source/FreeImage/Conversion.cpp#L56
40 bool SwapRedBlue32(FIBITMAP* freeImage)
41 {
42  if (FreeImage_GetImageType(freeImage) != FIT_BITMAP)
43  return false;
44 
45  const unsigned bytesperpixel = FreeImage_GetBPP(freeImage) / 8;
46  if (bytesperpixel > 4 || bytesperpixel < 3)
47  return false;
48 
49  const unsigned height = FreeImage_GetHeight(freeImage);
50  const unsigned pitch = FreeImage_GetPitch(freeImage);
51  const unsigned lineSize = FreeImage_GetLine(freeImage);
52 
53  BYTE* line = FreeImage_GetBits(freeImage);
54  for (unsigned y = 0; y < height; ++y, line += pitch)
55  for (BYTE* pixel = line; pixel < line + lineSize; pixel += bytesperpixel)
56  {
57  INPLACESWAP(pixel[0], pixel[2]);
58  }
59  return true;
60 }
61 
62 std::string getBase64Image(ImagePtr image, const std::string& format, const int quality)
63 {
64  FreeImage_SetOutputMessage([](FREE_IMAGE_FORMAT, const char* message) { throw std::runtime_error(message); });
65 
66  auto fif = format == "jpg" ? FIF_JPEG : FreeImage_GetFIFFromFormat(format.c_str());
67  if (fif == FIF_JPEG)
68  image.reset(FreeImage_ConvertTo24Bits(image.get()));
69  else if (fif == FIF_UNKNOWN)
70  throw std::runtime_error("Unknown format: " + format);
71 
72  int flags = quality;
73  if (fif == FIF_TIFF)
74  flags = TIFF_NONE;
75 
76  freeimage::MemoryPtr memory(FreeImage_OpenMemory());
77 
78  FreeImage_SaveToMemory(fif, image.get(), memory.get(), flags);
79 
80  BYTE* pixels = NULL;
81  DWORD numPixels = 0;
82  FreeImage_AcquireMemory(memory.get(), &pixels, &numPixels);
83  return {base64_encode(pixels, numPixels)};
84 }
85 
86 ImagePtr mergeImages(const std::vector<ImagePtr>& images)
87 {
88  int width, height, bbp;
89  width = height = bbp = 0;
90  for (const auto& image : images)
91  {
92  width += FreeImage_GetWidth(image.get());
93  height = FreeImage_GetHeight(image.get());
94  bbp = FreeImage_GetBPP(image.get());
95  }
96 
97  FreeImage_SetOutputMessage([](FREE_IMAGE_FORMAT, const char* message) { throw std::runtime_error(message); });
98 
99  ImagePtr mergedImage{FreeImage_Allocate(width, height, bbp)};
100  int offset = 0;
101  for (const auto& image : images)
102  {
103  const auto imageWidth = FreeImage_GetWidth(image.get());
104  FreeImage_Paste(mergedImage.get(), image.get(), offset, 0, 255);
105  offset += imageWidth;
106  }
107  return mergedImage;
108 }
109 } // namespace freeimage
110 } // namespace core
std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
Definition: base64.cpp:41
std::unique_ptr< FIBITMAP, ImageDeleter > ImagePtr
Definition: ImageUtils.h:49
bool SwapRedBlue32(FIBITMAP *freeImage)
Definition: ImageUtils.cpp:40
std::string getBase64Image(ImagePtr image, const std::string &format, const int quality)
Definition: ImageUtils.cpp:62
std::unique_ptr< FIMEMORY, MemoryDeleter > MemoryPtr
Definition: ImageUtils.h:50
ImagePtr mergeImages(const std::vector< ImagePtr > &images)
Definition: ImageUtils.cpp:86