LCOV - code coverage report
Current view: top level - ezlibs - ezBmp.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 74.8 % 111 83
Test Date: 2025-09-16 22:55:37 Functions: 66.7 % 9 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 61.1 % 18 11

             Branch data     Line data    Source code
       1                 :             : #pragma once
       2                 :             : 
       3                 :             : /*
       4                 :             : MIT License
       5                 :             : 
       6                 :             : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
       7                 :             : 
       8                 :             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :             : of this software and associated documentation files (the "Software"), to deal
      10                 :             : in the Software without restriction, including without limitation the rights
      11                 :             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :             : copies of the Software, and to permit persons to whom the Software is
      13                 :             : furnished to do so, subject to the following conditions:
      14                 :             : 
      15                 :             : The above copyright notice and this permission notice shall be included in all
      16                 :             : copies or substantial portions of the Software.
      17                 :             : 
      18                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24                 :             : SOFTWARE.
      25                 :             : */
      26                 :             : 
      27                 :             : // ezBmp is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
      28                 :             : 
      29                 :             : #ifndef EZ_BMP
      30                 :             : #define EZ_BMP
      31                 :             : #endif  // EZ_BMP
      32                 :             : 
      33                 :             : #include <fstream>
      34                 :             : #include <vector>
      35                 :             : #include <cstdint>
      36                 :             : #include <stdexcept>
      37                 :             : #include <string>
      38                 :             : 
      39                 :             : namespace ez {
      40                 :             : namespace img {
      41                 :             : 
      42                 :             : /*
      43                 :             : Bitmap picture file saver
      44                 :             : 
      45                 :             : ez::img::Bmp()
      46                 :             :     .setSize(10,10) // width, height 10
      47                 :             :     .setPixel(0,0,255,100,200) // byte form
      48                 :             :     .setPixel(5,5,0.5,0.2,0.8) // linear float form
      49                 :             :     .save("test.bmp"); // save to file test.bmp
      50                 :             : */
      51                 :             : 
      52                 :             : class Bmp {
      53                 :             :     friend class TestBmp;
      54                 :             : 
      55                 :             : private:
      56                 :             :     uint32_t m_width{};
      57                 :             :     uint32_t m_height{};
      58                 :             :     std::vector<uint8_t> m_pixels;
      59                 :             : 
      60                 :             : public:
      61                 :           1 :     Bmp() = default;
      62                 :           1 :     ~Bmp() = default;
      63                 :             : 
      64                 :           1 :     Bmp& setSize(uint32_t vWidth, uint32_t vHeight) {
      65                 :           1 :         m_width = std::move(vWidth);
      66                 :           1 :         m_height = std::move(vHeight);
      67                 :           1 :         m_pixels.resize(m_width * m_height * 3U);
      68                 :           1 :         return *this;
      69                 :           1 :     }
      70                 :             : 
      71                 :           0 :     Bmp& clear() {
      72                 :           0 :         m_width = 0U;
      73                 :           0 :         m_height = 0U;
      74                 :           0 :         m_pixels.clear();
      75                 :           0 :         return *this;
      76                 :           0 :     }
      77                 :             : 
      78                 :       10000 :     Bmp& setPixel(int32_t vX, int32_t vY, int32_t vRed, int32_t vGreen, int32_t vBlue) {
      79                 :       10000 :         auto x = static_cast<uint32_t>(vX);
      80                 :       10000 :         auto y = static_cast<uint32_t>(vY);
      81 [ +  - ][ +  - ]:       10000 :         if (x >= 0 && y < m_width && y >= 0U && x < m_height) {
         [ +  - ][ +  - ]
      82                 :       10000 :             size_t index = static_cast<size_t>((vY * m_width + vX) * 3);
      83                 :             :             // BMP save color in BGR
      84                 :       10000 :             m_pixels[index++] = m_getByteFromInt32(vBlue);
      85                 :       10000 :             m_pixels[index++] = m_getByteFromInt32(vGreen);
      86                 :       10000 :             m_pixels[index] = m_getByteFromInt32(vRed);
      87                 :       10000 :         }
      88                 :       10000 :         return *this;
      89                 :       10000 :     }
      90                 :             : 
      91                 :           0 :     Bmp& setPixel(int32_t vX, int32_t vY, float vRed, float vGreen, float vBlue) {
      92                 :           0 :         return setPixel(vX,  //
      93                 :           0 :                         vY, 
      94                 :           0 :                         m_getByteFromLinearFloat(vRed),
      95                 :           0 :                         m_getByteFromLinearFloat(vGreen),
      96                 :           0 :                         m_getByteFromLinearFloat(vBlue));
      97                 :           0 :     }
      98                 :             : 
      99                 :             :     // Sauvegarde l'image en tant que fichier BMP
     100                 :           1 :     Bmp& write(const std::string& filename) {
     101                 :           1 :         std::ofstream file(filename, std::ios::binary);
     102         [ -  + ]:           1 :         if (!file) {
     103                 :           0 :             throw std::runtime_error("Impossible d'ouvrir le fichier.");
     104                 :           0 :         }
     105                 :             : 
     106                 :           1 :         int paddingSize = (4 - (m_width * 3) % 4) % 4;
     107                 :           1 :         int fileSize = 54 + (m_width * m_height * 3) + (m_height * paddingSize);
     108                 :             : 
     109                 :             :         // En-t�te de fichier BMP
     110                 :           1 :         uint8_t fileHeader[14] = {
     111                 :           1 :             'B',
     112                 :           1 :             'M',  // Signature
     113                 :           1 :             0,
     114                 :           1 :             0,
     115                 :           1 :             0,
     116                 :           1 :             0,  // Taille du fichier
     117                 :           1 :             0,
     118                 :           1 :             0,
     119                 :           1 :             0,
     120                 :           1 :             0,  // R�serv�
     121                 :           1 :             54,
     122                 :           1 :             0,
     123                 :           1 :             0,
     124                 :           1 :             0  // Offset vers les donn�es d'image
     125                 :           1 :         };
     126                 :             : 
     127                 :             :         // Ins�rer la taille du fichier dans l'en-t�te
     128                 :           1 :         fileHeader[2] = fileSize;
     129                 :           1 :         fileHeader[3] = fileSize >> 8;
     130                 :           1 :         fileHeader[4] = fileSize >> 16;
     131                 :           1 :         fileHeader[5] = fileSize >> 24;
     132                 :             : 
     133                 :             :         // En-t�te d'information BMP
     134                 :           1 :         uint8_t infoHeader[40] = {
     135                 :           1 :             40, 0, 0, 0,  // Taille de l'en-t�te d'information
     136                 :           1 :             0,  0, 0, 0,  // Largeur
     137                 :           1 :             0,  0, 0, 0,  // Hauteur
     138                 :           1 :             1,  0,        // Nombre de plans (1)
     139                 :           1 :             24, 0,        // Bits par pixel (24 bits)
     140                 :           1 :             0,  0, 0, 0,  // Compression (aucune)
     141                 :           1 :             0,  0, 0, 0,  // Taille de l'image (non compress�e)
     142                 :           1 :             0,  0, 0, 0,  // R�solution horizontale (pixels par m�tre)
     143                 :           1 :             0,  0, 0, 0,  // R�solution verticale (pixels par m�tre)
     144                 :           1 :             0,  0, 0, 0,  // Couleurs dans la palette
     145                 :           1 :             0,  0, 0, 0   // Couleurs importantes
     146                 :           1 :         };
     147                 :             : 
     148                 :             :         // Ins�rer la largeur et la hauteur dans l'en-t�te d'information
     149                 :           1 :         infoHeader[4] = m_width;
     150                 :           1 :         infoHeader[5] = m_width >> 8;
     151                 :           1 :         infoHeader[6] = m_width >> 16;
     152                 :           1 :         infoHeader[7] = m_width >> 24;
     153                 :           1 :         infoHeader[8] = m_height;
     154                 :           1 :         infoHeader[9] = m_height >> 8;
     155                 :           1 :         infoHeader[10] = m_height >> 16;
     156                 :           1 :         infoHeader[11] = m_height >> 24;
     157                 :             : 
     158                 :             :         // �crire les en-t�tes dans le fichier
     159                 :           1 :         file.write(reinterpret_cast<char*>(fileHeader), sizeof(fileHeader));
     160                 :           1 :         file.write(reinterpret_cast<char*>(infoHeader), sizeof(infoHeader));
     161                 :             : 
     162                 :             :         // �crire les donn�es des pixels
     163         [ +  + ]:         101 :         for (int32_t y = static_cast<int32_t>(m_height - 1); y >= 0; --y) {  // BMP commence du bas vers le haut
     164         [ +  + ]:       10100 :             for (int32_t x = 0; x < static_cast<int32_t>(m_width); ++x) {
     165                 :       10000 :                 size_t index = static_cast<size_t>((y * m_width + x) * 3);
     166                 :       10000 :                 file.write(reinterpret_cast<char*>(&m_pixels[index]), 3);
     167                 :       10000 :             }
     168                 :             :             // Ajout de padding si n�cessaire
     169                 :         100 :             uint8_t padding[3] = {0, 0, 0};
     170                 :         100 :             file.write(reinterpret_cast<char*>(padding), paddingSize);
     171                 :         100 :         }
     172                 :             : 
     173                 :           1 :         file.close();
     174                 :           1 :         return *this;
     175                 :           1 :     }
     176                 :             : 
     177                 :             : private:
     178                 :       30000 :     uint8_t m_getByteFromInt32(int32_t vValue) {
     179         [ -  + ]:       30000 :         if (vValue < 0) {
     180                 :           0 :             vValue = 0;
     181                 :           0 :         }
     182         [ -  + ]:       30000 :         if (vValue > 255) {
     183                 :           0 :             vValue = 255;
     184                 :           0 :         }
     185                 :       30000 :         return static_cast<uint8_t>(vValue);
     186                 :       30000 :     }
     187                 :           0 :     uint8_t m_getByteFromLinearFloat(float vValue) {
     188                 :           0 :         if (vValue < 0.0f) {
     189                 :           0 :             vValue = 0.0f;
     190                 :           0 :         }
     191                 :           0 :         if (vValue > 1.0f) {
     192                 :           0 :             vValue = 1.0f;
     193                 :           0 :         }
     194                 :           0 :         return static_cast<uint8_t>(vValue * 255.0f);
     195                 :           0 :     }
     196                 :             : };
     197                 :             : 
     198                 :             : }  // namespace img
     199                 :             : }  // namespace ez
        

Generated by: LCOV version 2.0-1