NAP
bitmap.h
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 #pragma once
6 
7 // Local Includes
8 #include "color.h"
9 #include "surfacedescriptor.h"
10 
11 // External Includes
12 #include <nap/resource.h>
13 #include <utility/dllexport.h>
14 #include <nap/signalslot.h>
15 
16 
17 namespace nap
18 {
19  class Texture2D;
20  struct SurfaceDescriptor;
21 
31  class NAPAPI Bitmap : public Resource
32  {
33  friend class BitmapFileBuffer;
34  RTTI_ENABLE(Resource)
35  public:
36 
37  virtual ~Bitmap();
38 
45  virtual bool init(utility::ErrorState& errorState) override;
46 
55  virtual bool initFromFile(const std::string& path, nap::utility::ErrorState& errorState);
56 
62  void initFromDescriptor(const SurfaceDescriptor& surfaceDescriptor);
63 
69  bool save(const std::string& path, utility::ErrorState& errorState);
70 
74  rtti::TypeInfo getColorType() const { return mColorType; }
75 
80  bool empty() const { return mData.empty(); }
81 
85  int getWidth() const { return mSurfaceDescriptor.getWidth(); }
86 
90  int getHeight() const { return mSurfaceDescriptor.getHeight(); }
91 
95  int getNumberOfChannels() const { return mSurfaceDescriptor.getNumChannels(); }
96 
100  void* getData() { return mData.data(); }
101 
105  const void* getData() const { return mData.data(); }
106 
112  size_t getSizeInBytes() const;
113 
136  std::unique_ptr<BaseColor> makePixel() const;
137 
165  void getPixel(int x, int y, BaseColor& outPixel) const;
166 
179  template<typename T>
180  T getPixel(int x, int y) const;
181 
194  void setPixel(int x, int y, const BaseColor& color);
195 
208  template<typename T>
209  void setPixelColor(int x, int y, const T& color);
210 
219  template<typename Type>
220  void getRGBColor(int x, int y, RGBColor<Type>& outColor) const;
221 
230  template<typename Type>
231  RGBColor<Type> getRGBColor(int x, int y) const;
232 
241  template<typename Type>
242  void getRGBAColor(int x, int y, RGBAColor<Type>& outColor) const;
243 
252  template<typename Type>
253  RGBAColor<Type> getRGBAColor(int x, int y) const;
254 
263  template<typename Type>
264  void getColorValue(int x, int y, nap::EColorChannel channel, RColor<Type>& outValue) const;
265 
274  template<typename Type>
275  RColor<Type> getColorValue(int x, int y, nap::EColorChannel channel) const;
276 
282 
287 
288  private:
293  void updatePixelFormat();
294 
298  template<typename T>
299  T* getPixelData(unsigned int x, unsigned int y) const
300  {
301  assert(sizeof(T) == mSurfaceDescriptor.getChannelSize());
302  if (x >= mSurfaceDescriptor.getWidth() || y >= mSurfaceDescriptor.getHeight())
303  return nullptr;
304 
305  // Get index in to array offset by number of channels (pixel level)
306  unsigned int offset = ((y * mSurfaceDescriptor.getWidth()) + x) * mSurfaceDescriptor.getBytesPerPixel();
307 
308  // Update offset (pixel * num_channels * data_size)
309  unsigned char* data_ptr = (unsigned char*)(mData.data()) + offset;
310  return (T*)(data_ptr);
311  }
312 
322  template<typename Type>
323  void getRGBColorData(int x, int y, RGBColor<Type*>& outColorData) const;
324 
334  template<typename Type>
335  void getRGBAColorData(int x, int y, RGBAColor<Type*>& outColorData) const;
336 
346  template<typename Type>
347  RGBAColor<Type*> getRGBAColorData(int x, int y) const;
348 
358  template<typename Type>
359  RGBColor<Type*> getRGBColorData(int x, int y) const;
360 
369  template<typename Type>
370  void getColorValueData(int x, int y, nap::EColorChannel channel, RColor<Type*>& outValue) const;
371 
380  template<typename Type>
381  RColor<Type*> getColorValueData(int x, int y, nap::EColorChannel channel) const;
382 
389  template<typename T>
390  void setPixelData(int x, int y, const nap::BaseColor& color);
391 
392  rtti::TypeInfo mColorType = rtti::TypeInfo::empty();
393  rtti::TypeInfo mValueType = rtti::TypeInfo::empty();
394 
395  private:
396  std::vector<uint8_t> mData;
397  };
398 
404  class NAPAPI BitmapFromFile : public Bitmap
405  {
406  RTTI_ENABLE(Bitmap)
407  public:
414  virtual bool init(utility::ErrorState& errorState) override;
415 
416  std::string mPath;
417  };
418 
419 
421  // Template definitions
423 
424  template<typename Type>
425  void nap::Bitmap::getRGBAColor(int x, int y, RGBAColor<Type>& outColor) const
426  {
427  RGBAColor<Type*> color_data;
428  getRGBAColorData<Type>(x, y, color_data);
429 
430  outColor.setValue(EColorChannel::Red, *(color_data.getValue(EColorChannel::Red)));
432  outColor.setValue(EColorChannel::Blue, *(color_data.getValue(EColorChannel::Blue)));
434  }
435 
436 
437  template<typename Type>
438  void nap::Bitmap::getRGBColor(int x, int y, RGBColor<Type>& outColor) const
439  {
440  RGBColor<Type*> color_data;
441  getRGBColorData<Type>(x, y, color_data);
442 
443  outColor.setValue(EColorChannel::Red, *(color_data.getValue(EColorChannel::Red)));
445  outColor.setValue(EColorChannel::Blue, *(color_data.getValue(EColorChannel::Blue)));
446  }
447 
448 
449  template<typename Type>
450  void nap::Bitmap::getColorValue(int x, int y, nap::EColorChannel channel, RColor<Type>& outValue) const
451  {
452  RColor<Type*> color_value;
453  getColorValueData<Type>(x, y, channel, color_value);
454  outValue.setValue(EColorChannel::Red, *(color_value.getValue(EColorChannel::Red)));
455  }
456 
457 
458  template<typename Type>
460  {
461  RGBColor<Type> color;
462  getRGBColor<Type>(x, y, color);
463  return color;
464  }
465 
466 
467  template<typename Type>
469  {
470  RGBAColor<Type> color;
471  getRGBAColor<Type>(x, y, color);
472  return color;
473  }
474 
475 
476  template<typename Type>
477  void nap::Bitmap::getRGBAColorData(int x, int y, RGBAColor<Type*>& outColor) const
478  {
479  assert(mSurfaceDescriptor.getNumChannels() >= outColor.getNumberOfChannels());
480  assert(outColor.getValueType() == RTTI_OF(Type));
481 
482  Type* pixel_data = getPixelData<Type>(x, y);
483  switch (mSurfaceDescriptor.getChannels())
484  {
486  {
487  outColor.setValue(EColorChannel::Red, pixel_data + 2);
488  outColor.setValue(EColorChannel::Blue, pixel_data + 0);
489  break;
490  }
492  {
493  outColor.setValue(EColorChannel::Red, pixel_data + 0);
494  outColor.setValue(EColorChannel::Blue, pixel_data + 2);
495  break;
496  }
497  default:
498  assert(false);
499  }
500  outColor.setValue(EColorChannel::Green, pixel_data + 1);
501  outColor.setValue(EColorChannel::Alpha, pixel_data + 3);
502  }
503 
504 
505  template<typename Type>
506  RGBAColor<Type*> nap::Bitmap::getRGBAColorData(int x, int y) const
507  {
508  RGBAColor<Type*> rcolor;
509  getRGBAColorData<Type>(x, y, rcolor);
510  return rcolor;
511  }
512 
513 
514  template<typename Type>
515  void nap::Bitmap::getRGBColorData(int x, int y, RGBColor<Type*>& outColor) const
516  {
517  assert(mSurfaceDescriptor.getNumChannels() >= outColor.getNumberOfChannels());
518  assert(outColor.getValueType() == RTTI_OF(Type));
519 
520  Type* pixel_data = getPixelData<Type>(x, y);
521  switch (mSurfaceDescriptor.getChannels())
522  {
524  {
525  outColor.setValue(EColorChannel::Red, pixel_data + 2);
526  outColor.setValue(EColorChannel::Blue, pixel_data + 0);
527  break;
528  }
530  {
531  outColor.setValue(EColorChannel::Red, pixel_data + 0);
532  outColor.setValue(EColorChannel::Blue, pixel_data + 2);
533  break;
534  }
535  default:
536  assert(false);
537  }
538  outColor.setValue(EColorChannel::Green, pixel_data + 1);
539  }
540 
541 
542  template<typename Type>
543  RGBColor<Type*> nap::Bitmap::getRGBColorData(int x, int y) const
544  {
545  RGBColor<Type*> rcolor;
546  getRGBColorData<Type>(x, y, rcolor);
547  return rcolor;
548  }
549 
550 
551  template<typename Type>
552  void nap::Bitmap::getColorValueData(int x, int y, nap::EColorChannel channel, RColor<Type*>& outValue) const
553  {
554  assert(outValue.getValueType() == RTTI_OF(Type));
555  assert(static_cast<int>(channel) < mSurfaceDescriptor.getNumChannels());
556 
557  int idx = static_cast<int>(channel);
558  switch (mSurfaceDescriptor.getChannels())
559  {
561  {
562  idx = channel == EColorChannel::Red ? 2 :
563  channel == EColorChannel::Blue ? 0 : idx;
564  break;
565  }
566  default:
567  break;
568  }
569  Type* pixel_data = getPixelData<Type>(x, y);
570  outValue.setValue(EColorChannel::Red, pixel_data + idx);
571  }
572 
573 
574  template<typename Type>
576  {
577  RColor<Type> rvalue;
578  getColorValue<Type>(x, y, channel, rvalue);
579  return rvalue;
580  }
581 
582 
583  template<typename Type>
584  RColor<Type*> nap::Bitmap::getColorValueData(int x, int y, nap::EColorChannel channel) const
585  {
586  RColor<Type*> rvalue;
587  getColorValueData(x, y, channel, rvalue);
588  return rvalue;
589  }
590 
591 
592  template<typename T>
593  T nap::Bitmap::getPixel(int x, int y) const
594  {
595  // Create a pixel and fill it
596  std::unique_ptr<BaseColor> pixel = makePixel();
597  getPixel(x, y, *pixel);
598 
599  // If they are of the same type it's safe to cast and return
600  if (pixel->get_type().is_derived_from(RTTI_OF(T)))
601  {
602  return *(static_cast<T*>(pixel.get()));
603  }
604  // Otherwise we need to convert
605  return pixel->convert<T>();
606  }
607 
608 
609  template<typename T>
610  void nap::Bitmap::setPixelColor(int x, int y, const T& color)
611  {
612  if (color.getValueType() == mValueType && !(color.isPointer()))
613  {
614  setPixel(x, y, color);
615  return;
616  }
617 
618  std::unique_ptr<BaseColor> new_pixel = makePixel();
619  const BaseColor& source_color = static_cast<const BaseColor&>(color);
620  source_color.convert(*new_pixel);
621  setPixel(x, y, *new_pixel);
622  }
623 
624 
625  template<typename T>
626  void nap::Bitmap::setPixelData(int x, int y, const nap::BaseColor& color)
627  {
628  // We need to make sure that the underlying color value types match
629  // The incoming color can't be a pointer
630  assert(mValueType == color.getValueType());
631  assert(!color.isPointer());
632 
633  switch (color.getNumberOfChannels())
634  {
635  case 1:
636  {
637  const nap::RColor<T>* clr = static_cast<const nap::RColor<T>*>(&color);
638  nap::RColor<T*> data = this->getColorValueData<T>(x, y, nap::EColorChannel::Red);
639  (*data.getRed()) = clr->getRed();
640  break;
641  }
642  case 3:
643  {
644  const nap::RGBColor<T>* clr = static_cast<const nap::RGBColor<T>*>(&color);
645  nap::RGBColor<T*> data = this->getRGBColorData<T>(x, y);
646  (*data.getRed()) = clr->getRed();
647  (*data.getGreen()) = clr->getGreen();
648  (*data.getBlue()) = clr->getBlue();
649  break;
650  }
651  case 4:
652  {
653  const nap::RGBAColor<T>* clr = static_cast<const nap::RGBAColor<T>*>(&color);
654  nap::RGBAColor<T*> data = this->getRGBAColorData<T>(x, y);
655  (*data.getRed()) = clr->getRed();
656  (*data.getGreen()) = clr->getGreen();
657  (*data.getBlue()) = clr->getBlue();
658  (*data.getAlpha()) = clr->getAlpha();
659  break;
660  }
661  default:
662  assert(false);
663  }
664  }
665 }
666 
nap::Color< T, 4 >::getValueType
rtti::TypeInfo getValueType() const override
Definition: color.h:234
nap::BitmapFileBuffer
Definition: bitmapfilebuffer.h:15
nap::RGBColor
Definition: color.h:373
nap::ESurfaceChannels::RGBA
@ RGBA
RGBA red, green, blue and alpha component.
nap::RGBAColor::getRed
T getRed() const
Definition: color.h:483
nap::RGBAColor
Definition: color.h:444
nap::BaseColor::convert
void convert(BaseColor &target) const
nap::BitmapFromFile
Definition: bitmap.h:404
nap::utility::ErrorState
Definition: errorstate.h:19
nap::Bitmap::getNumberOfChannels
int getNumberOfChannels() const
Definition: bitmap.h:95
nap::EColorChannel::Red
@ Red
Red Color Channel: 0.
nap::Bitmap::mBitmapUpdated
Signal mBitmapUpdated
Definition: bitmap.h:286
nap::RColor
Definition: color.h:535
nap::BitmapFromFile::mPath
std::string mPath
Property 'Path': the path to the image on disk.
Definition: bitmap.h:416
nap::RGBAColor::getAlpha
T getAlpha() const
Definition: color.h:516
nap::Color< T, 4 >::setValue
void setValue(EColorChannel channel, T value)
Definition: color.h:653
nap::EColorChannel::Green
@ Green
Green Color Channel: 1.
nap::EColorChannel::Alpha
@ Alpha
Alpha Color Channel: 3.
nap::Signal
Definition: signalslot.h:28
nap::RGBColor::getBlue
T getBlue() const
Definition: color.h:425
nap::SurfaceDescriptor
Definition: surfacedescriptor.h:46
nap::Bitmap::getRGBColor
void getRGBColor(int x, int y, RGBColor< Type > &outColor) const
Definition: bitmap.h:438
nap::ESurfaceChannels::BGRA
@ BGRA
BGRA blue, green, red and alpha component.
nap::Bitmap::getRGBAColor
void getRGBAColor(int x, int y, RGBAColor< Type > &outColor) const
Definition: bitmap.h:425
nap::uniform::constant::color
constexpr const char * color
color value (0-1)
Definition: constantshader.h:17
nap::RGBColor::getRed
T getRed() const
Definition: color.h:403
nap::Bitmap::getColorType
rtti::TypeInfo getColorType() const
Definition: bitmap.h:74
nap::Bitmap::getWidth
int getWidth() const
Definition: bitmap.h:85
nap::BaseColor::getNumberOfChannels
int getNumberOfChannels() const
Definition: color.h:62
nap::Bitmap::empty
bool empty() const
Definition: bitmap.h:80
nap::Bitmap::getData
const void * getData() const
Definition: bitmap.h:105
nap::Bitmap::mSurfaceDescriptor
SurfaceDescriptor mSurfaceDescriptor
Definition: bitmap.h:281
nap::RColor::getRed
T getRed() const
Definition: color.h:565
nap::Bitmap
Definition: bitmap.h:31
nap::Bitmap::setPixelColor
void setPixelColor(int x, int y, const T &color)
Definition: bitmap.h:610
nap::SurfaceDescriptor::getHeight
int getHeight() const
Definition: surfacedescriptor.h:64
nap::Bitmap::getColorValue
void getColorValue(int x, int y, nap::EColorChannel channel, RColor< Type > &outValue) const
Definition: bitmap.h:450
nap::SurfaceDescriptor::getChannels
ESurfaceChannels getChannels() const
Definition: surfacedescriptor.h:99
nap::Bitmap::getHeight
int getHeight() const
Definition: bitmap.h:90
nap::RGBAColor::getGreen
T getGreen() const
Definition: color.h:494
nap
Definition: templateapp.h:17
nap::Bitmap::getPixel
void getPixel(int x, int y, BaseColor &outPixel) const
nap::Resource
Definition: resource.h:19
nap::SurfaceDescriptor::getNumChannels
int getNumChannels() const
nap::SurfaceDescriptor::getBytesPerPixel
int getBytesPerPixel() const
nap::SurfaceDescriptor::getChannelSize
int getChannelSize() const
nap::rtti::TypeInfo
rttr::type TypeInfo
Definition: typeinfo.h:140
nap::EColorChannel::Blue
@ Blue
Blue Color Channel: 2.
nap::SurfaceDescriptor::getWidth
int getWidth() const
Definition: surfacedescriptor.h:59
nap::RGBAColor::getBlue
T getBlue() const
Definition: color.h:505
nap::Bitmap::getData
void * getData()
Definition: bitmap.h:100
nap::Color< T, 4 >::getValue
T getValue(EColorChannel channel) const
Definition: color.h:645
nap::BaseColor
Definition: color.h:37
nap::EColorChannel
EColorChannel
Definition: color.h:17
nap::RGBColor::getGreen
T getGreen() const
Definition: color.h:414