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 
110  size_t getSizeInBytes() const;
111 
115  const SurfaceDescriptor& getDescriptor() const { return mSurfaceDescriptor; }
116 
139  std::unique_ptr<BaseColor> makePixel() const;
140 
168  void getPixel(int x, int y, BaseColor& outPixel) const;
169 
182  template<typename T>
183  T getPixel(int x, int y) const;
184 
197  void setPixel(int x, int y, const BaseColor& color);
198 
211  template<typename T>
212  void setPixelColor(int x, int y, const T& color);
213 
222  template<typename Type>
223  void getRGBColor(int x, int y, RGBColor<Type>& outColor) const;
224 
233  template<typename Type>
234  RGBColor<Type> getRGBColor(int x, int y) const;
235 
244  template<typename Type>
245  void getRGBAColor(int x, int y, RGBAColor<Type>& outColor) const;
246 
255  template<typename Type>
256  RGBAColor<Type> getRGBAColor(int x, int y) const;
257 
266  template<typename Type>
267  void getColorValue(int x, int y, nap::EColorChannel channel, RColor<Type>& outValue) const;
268 
277  template<typename Type>
278  RColor<Type> getColorValue(int x, int y, nap::EColorChannel channel) const;
279 
285 
290 
291  private:
296  void updatePixelFormat();
297 
301  template<typename T>
302  T* getPixelData(unsigned int x, unsigned int y) const
303  {
304  assert(sizeof(T) == mSurfaceDescriptor.getChannelSize());
305  if (x >= mSurfaceDescriptor.getWidth() || y >= mSurfaceDescriptor.getHeight())
306  return nullptr;
307 
308  // Get index in to array offset by number of channels (pixel level)
309  unsigned int offset = ((y * mSurfaceDescriptor.getWidth()) + x) * mSurfaceDescriptor.getBytesPerPixel();
310 
311  // Update offset (pixel * num_channels * data_size)
312  unsigned char* data_ptr = (unsigned char*)(mData.data()) + offset;
313  return (T*)(data_ptr);
314  }
315 
325  template<typename Type>
326  void getRGBColorData(int x, int y, RGBColor<Type*>& outColorData) const;
327 
337  template<typename Type>
338  void getRGBAColorData(int x, int y, RGBAColor<Type*>& outColorData) const;
339 
349  template<typename Type>
350  RGBAColor<Type*> getRGBAColorData(int x, int y) const;
351 
361  template<typename Type>
362  RGBColor<Type*> getRGBColorData(int x, int y) const;
363 
372  template<typename Type>
373  void getColorValueData(int x, int y, nap::EColorChannel channel, RColor<Type*>& outValue) const;
374 
383  template<typename Type>
384  RColor<Type*> getColorValueData(int x, int y, nap::EColorChannel channel) const;
385 
392  template<typename T>
393  void setPixelData(int x, int y, const nap::BaseColor& color);
394 
395  rtti::TypeInfo mColorType = rtti::TypeInfo::empty();
396  rtti::TypeInfo mValueType = rtti::TypeInfo::empty();
397 
398  private:
399  std::vector<uint8_t> mData;
400  };
401 
407  class NAPAPI BitmapFromFile : public Bitmap
408  {
409  RTTI_ENABLE(Bitmap)
410  public:
417  virtual bool init(utility::ErrorState& errorState) override;
418 
419  std::string mPath;
420  };
421 
422 
424  // Template definitions
426 
427  template<typename Type>
428  void nap::Bitmap::getRGBAColor(int x, int y, RGBAColor<Type>& outColor) const
429  {
430  RGBAColor<Type*> color_data;
431  getRGBAColorData<Type>(x, y, color_data);
432 
433  outColor.setValue(EColorChannel::Red, *(color_data.getValue(EColorChannel::Red)));
435  outColor.setValue(EColorChannel::Blue, *(color_data.getValue(EColorChannel::Blue)));
437  }
438 
439 
440  template<typename Type>
441  void nap::Bitmap::getRGBColor(int x, int y, RGBColor<Type>& outColor) const
442  {
443  RGBColor<Type*> color_data;
444  getRGBColorData<Type>(x, y, color_data);
445 
446  outColor.setValue(EColorChannel::Red, *(color_data.getValue(EColorChannel::Red)));
448  outColor.setValue(EColorChannel::Blue, *(color_data.getValue(EColorChannel::Blue)));
449  }
450 
451 
452  template<typename Type>
453  void nap::Bitmap::getColorValue(int x, int y, nap::EColorChannel channel, RColor<Type>& outValue) const
454  {
455  RColor<Type*> color_value;
456  getColorValueData<Type>(x, y, channel, color_value);
457  outValue.setValue(EColorChannel::Red, *(color_value.getValue(EColorChannel::Red)));
458  }
459 
460 
461  template<typename Type>
463  {
464  RGBColor<Type> color;
465  getRGBColor<Type>(x, y, color);
466  return color;
467  }
468 
469 
470  template<typename Type>
472  {
473  RGBAColor<Type> color;
474  getRGBAColor<Type>(x, y, color);
475  return color;
476  }
477 
478 
479  template<typename Type>
480  void nap::Bitmap::getRGBAColorData(int x, int y, RGBAColor<Type*>& outColor) const
481  {
482  assert(mSurfaceDescriptor.getNumChannels() >= outColor.getNumberOfChannels());
483  assert(outColor.getValueType() == RTTI_OF(Type));
484 
485  Type* pixel_data = getPixelData<Type>(x, y);
486  switch (mSurfaceDescriptor.getChannels())
487  {
489  {
490  outColor.setValue(EColorChannel::Red, pixel_data + 2);
491  outColor.setValue(EColorChannel::Blue, pixel_data + 0);
492  break;
493  }
495  {
496  outColor.setValue(EColorChannel::Red, pixel_data + 0);
497  outColor.setValue(EColorChannel::Blue, pixel_data + 2);
498  break;
499  }
500  default:
501  assert(false);
502  }
503  outColor.setValue(EColorChannel::Green, pixel_data + 1);
504  outColor.setValue(EColorChannel::Alpha, pixel_data + 3);
505  }
506 
507 
508  template<typename Type>
509  RGBAColor<Type*> nap::Bitmap::getRGBAColorData(int x, int y) const
510  {
511  RGBAColor<Type*> rcolor;
512  getRGBAColorData<Type>(x, y, rcolor);
513  return rcolor;
514  }
515 
516 
517  template<typename Type>
518  void nap::Bitmap::getRGBColorData(int x, int y, RGBColor<Type*>& outColor) const
519  {
520  assert(mSurfaceDescriptor.getNumChannels() >= outColor.getNumberOfChannels());
521  assert(outColor.getValueType() == RTTI_OF(Type));
522 
523  Type* pixel_data = getPixelData<Type>(x, y);
524  switch (mSurfaceDescriptor.getChannels())
525  {
527  {
528  outColor.setValue(EColorChannel::Red, pixel_data + 2);
529  outColor.setValue(EColorChannel::Blue, pixel_data + 0);
530  break;
531  }
533  {
534  outColor.setValue(EColorChannel::Red, pixel_data + 0);
535  outColor.setValue(EColorChannel::Blue, pixel_data + 2);
536  break;
537  }
538  default:
539  assert(false);
540  }
541  outColor.setValue(EColorChannel::Green, pixel_data + 1);
542  }
543 
544 
545  template<typename Type>
546  RGBColor<Type*> nap::Bitmap::getRGBColorData(int x, int y) const
547  {
548  RGBColor<Type*> rcolor;
549  getRGBColorData<Type>(x, y, rcolor);
550  return rcolor;
551  }
552 
553 
554  template<typename Type>
555  void nap::Bitmap::getColorValueData(int x, int y, nap::EColorChannel channel, RColor<Type*>& outValue) const
556  {
557  assert(outValue.getValueType() == RTTI_OF(Type));
558  assert(static_cast<int>(channel) < mSurfaceDescriptor.getNumChannels());
559 
560  int idx = static_cast<int>(channel);
561  switch (mSurfaceDescriptor.getChannels())
562  {
564  {
565  idx = channel == EColorChannel::Red ? 2 :
566  channel == EColorChannel::Blue ? 0 : idx;
567  break;
568  }
569  default:
570  break;
571  }
572  Type* pixel_data = getPixelData<Type>(x, y);
573  outValue.setValue(EColorChannel::Red, pixel_data + idx);
574  }
575 
576 
577  template<typename Type>
579  {
580  RColor<Type> rvalue;
581  getColorValue<Type>(x, y, channel, rvalue);
582  return rvalue;
583  }
584 
585 
586  template<typename Type>
587  RColor<Type*> nap::Bitmap::getColorValueData(int x, int y, nap::EColorChannel channel) const
588  {
589  RColor<Type*> rvalue;
590  getColorValueData(x, y, channel, rvalue);
591  return rvalue;
592  }
593 
594 
595  template<typename T>
596  T nap::Bitmap::getPixel(int x, int y) const
597  {
598  // Create a pixel and fill it
599  std::unique_ptr<BaseColor> pixel = makePixel();
600  getPixel(x, y, *pixel);
601 
602  // If they are of the same type it's safe to cast and return
603  if (pixel->get_type().is_derived_from(RTTI_OF(T)))
604  {
605  return *(static_cast<T*>(pixel.get()));
606  }
607  // Otherwise we need to convert
608  return pixel->convert<T>();
609  }
610 
611 
612  template<typename T>
613  void nap::Bitmap::setPixelColor(int x, int y, const T& color)
614  {
615  if (color.getValueType() == mValueType && !(color.isPointer()))
616  {
617  setPixel(x, y, color);
618  return;
619  }
620 
621  std::unique_ptr<BaseColor> new_pixel = makePixel();
622  const BaseColor& source_color = static_cast<const BaseColor&>(color);
623  source_color.convert(*new_pixel);
624  setPixel(x, y, *new_pixel);
625  }
626 
627 
628  template<typename T>
629  void nap::Bitmap::setPixelData(int x, int y, const nap::BaseColor& color)
630  {
631  // We need to make sure that the underlying color value types match
632  // The incoming color can't be a pointer
633  assert(mValueType == color.getValueType());
634  assert(!color.isPointer());
635 
636  switch (color.getNumberOfChannels())
637  {
638  case 1:
639  {
640  const nap::RColor<T>* clr = static_cast<const nap::RColor<T>*>(&color);
641  nap::RColor<T*> data = this->getColorValueData<T>(x, y, nap::EColorChannel::Red);
642  (*data.getRed()) = clr->getRed();
643  break;
644  }
645  case 3:
646  {
647  const nap::RGBColor<T>* clr = static_cast<const nap::RGBColor<T>*>(&color);
648  nap::RGBColor<T*> data = this->getRGBColorData<T>(x, y);
649  (*data.getRed()) = clr->getRed();
650  (*data.getGreen()) = clr->getGreen();
651  (*data.getBlue()) = clr->getBlue();
652  break;
653  }
654  case 4:
655  {
656  const nap::RGBAColor<T>* clr = static_cast<const nap::RGBAColor<T>*>(&color);
657  nap::RGBAColor<T*> data = this->getRGBAColorData<T>(x, y);
658  (*data.getRed()) = clr->getRed();
659  (*data.getGreen()) = clr->getGreen();
660  (*data.getBlue()) = clr->getBlue();
661  (*data.getAlpha()) = clr->getAlpha();
662  break;
663  }
664  default:
665  assert(false);
666  }
667  }
668 }
669 
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:407
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:289
nap::RColor
Definition: color.h:535
nap::BitmapFromFile::mPath
std::string mPath
Property 'Path': the path to the image on disk.
Definition: bitmap.h:419
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:25
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:441
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:428
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:284
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:613
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:453
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::getDescriptor
const SurfaceDescriptor & getDescriptor() const
Definition: bitmap.h:115
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:141
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