auto YUV::full_range()

in vireo/frame/yuv.cpp [122:207]


auto YUV::full_range(bool full_range) -> YUV {
  THROW_IF(_this->full_range == full_range, InvalidArguments);
  frame::YUV new_yuv(width(), height(), uv_ratio().first, uv_ratio().second, full_range);
  uint8_t* const src[] = {
    (uint8_t* const)plane(frame::Y).bytes().data(),
    (uint8_t* const)plane(frame::U).bytes().data(),
    (uint8_t* const)plane(frame::V).bytes().data()
  };
  uint8_t* const dst[] = {
    (uint8_t* const)new_yuv.plane(frame::Y).bytes().data(),
    (uint8_t* const)new_yuv.plane(frame::U).bytes().data(),
    (uint8_t* const)new_yuv.plane(frame::V).bytes().data()
  };
  const int src_stride[] = {
    plane(frame::Y).row(),
    plane(frame::U).row(),
    plane(frame::V).row()
  };
  const int dst_stride[] = {
    new_yuv.plane(frame::Y).row(),
    new_yuv.plane(frame::U).row(),
    new_yuv.plane(frame::V).row()
  };
  const int width[] = {
    plane(frame::Y).width(),
    plane(frame::U).width(),
    plane(frame::V).width()
  };
  const int height[] = {
    plane(frame::Y).height(),
    plane(frame::U).height(),
    plane(frame::V).height()
  };

#define CLIP3(x, low, high) ({\
  __typeof__(x) _x = x;\
  (((_x) < (low)) ? (low) : ((_x) > (high)) ? (high) : (_x));\
})

  const int16_t   _0 =   0;
  const int16_t  _16 =  16;
  const int16_t _219 = 219;
  const int16_t _224 = 224;
  const int16_t _128 = 128;
  const int16_t _235 = 235;
  const int16_t _240 = 240;
  const int16_t _255 = 255;
  if (full_range) {
    int p = frame::Y;
    for (int y = 0; y < height[p]; ++y) {
      uint8_t* sptr = src[p] + y * src_stride[p];
      uint8_t* dptr = dst[p] + y * dst_stride[p];
      for (int x = 0, w = width[p]; x < w; ++x) {
        *dptr++ = (uint8_t)CLIP3((int16_t)_255 * ((int16_t)*sptr++ - _16) / _219, _0, _255);
      }
    }
    for (auto p: enumeration::Enum<frame::PlaneIndex>(frame::U, frame::V)) {
      for (int y = 0; y < height[p]; ++y) {
        uint8_t* sptr = src[p] + y * src_stride[p];
        uint8_t* dptr = dst[p] + y * dst_stride[p];
        for (int x = 0, w = width[p]; x < w; ++x) {
          *dptr++ = (uint8_t)CLIP3((int16_t)_255 * ((int16_t)*sptr++ - _128) / _224 + _128, _0, _255);
        }
      }
    }
  } else {
    int p = frame::Y;
    for (int y = 0; y < height[p]; ++y) {
      uint8_t* sptr = src[p] + y * src_stride[p];
      uint8_t* dptr = dst[p] + y * dst_stride[p];
      for (int x = 0, w = width[p]; x < w; ++x) {
        *dptr++ = (uint8_t)CLIP3((int16_t)_219 * *sptr++ / _255 + _16, _16, _235);
      }
    }
    for (auto p: enumeration::Enum<frame::PlaneIndex>(frame::U, frame::V)) {
      for (int y = 0; y < height[p]; ++y) {
        uint8_t* sptr = src[p] + y * src_stride[p];
        uint8_t* dptr = dst[p] + y * dst_stride[p];
        for (int x = 0, w = width[p]; x < w; ++x) {
          *dptr++ = (uint8_t)CLIP3((int16_t)_224 * ((int16_t)*sptr++ - _128) / _255 + _128, _16, _240);
        }
      }
    }
  }
  return new_yuv;
}