Merge master.
[dcpomatic.git] / src / lib / image.cc
index 2eb2dbe28b013363e0852684761202ec550613d1..bc64ba3b82373cb34bce1aff4e0f450d93ce5b29 100644 (file)
@@ -322,6 +322,8 @@ Image::make_black ()
        case PIX_FMT_ABGR:
        case PIX_FMT_BGRA:
        case PIX_FMT_RGB555LE:
+       case PIX_FMT_RGB48LE:
+       case PIX_FMT_RGB48BE:
                memset (data()[0], 0, lines(0) * stride()[0]);
                break;
 
@@ -690,3 +692,137 @@ Image::digest () const
 
        return digester.get ();
 }
+
+bool
+operator== (Image const & a, Image const & b)
+{
+       if (a.components() != b.components() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
+               return false;
+       }
+
+       for (int c = 0; c < a.components(); ++c) {
+               if (a.lines(c) != b.lines(c) || a.line_size()[c] != b.line_size()[c] || a.stride()[c] != b.stride()[c]) {
+                       return false;
+               }
+
+               uint8_t* p = a.data()[c];
+               uint8_t* q = b.data()[c];
+               for (int y = 0; y < a.lines(c); ++y) {
+                       if (memcmp (p, q, a.line_size()[c]) != 0) {
+                               return false;
+                       }
+
+                       p += a.stride()[c];
+                       q += b.stride()[c];
+               }
+       }
+
+       return true;
+}
+
+void
+Image::fade (float f)
+{
+       switch (_pixel_format) {
+       case PIX_FMT_YUV420P:
+       case PIX_FMT_YUV422P:
+       case PIX_FMT_YUV444P:
+       case PIX_FMT_YUV411P:
+       case PIX_FMT_YUVJ420P:
+       case PIX_FMT_YUVJ422P:
+       case PIX_FMT_YUVJ444P:
+       case PIX_FMT_RGB24:
+       case PIX_FMT_ARGB:
+       case PIX_FMT_RGBA:
+       case PIX_FMT_ABGR:
+       case PIX_FMT_BGRA:
+       case PIX_FMT_RGB555LE:
+               /* 8-bit */
+               for (int c = 0; c < 3; ++c) {
+                       uint8_t* p = data()[c];
+                       for (int y = 0; y < lines(c); ++y) {
+                               uint8_t* q = p;
+                               for (int x = 0; x < line_size()[c]; ++x) {
+                                       *q = int (float (*q) * f);
+                                       ++q;
+                               }
+                               p += stride()[c];
+                       }
+               }
+               break;
+
+       case PIX_FMT_YUV422P9LE:
+       case PIX_FMT_YUV444P9LE:
+       case PIX_FMT_YUV422P10LE:
+       case PIX_FMT_YUV444P10LE:
+       case PIX_FMT_YUV422P16LE:
+       case PIX_FMT_YUV444P16LE:
+       case AV_PIX_FMT_YUVA420P9LE:
+       case AV_PIX_FMT_YUVA422P9LE:
+       case AV_PIX_FMT_YUVA444P9LE:
+       case AV_PIX_FMT_YUVA420P10LE:
+       case AV_PIX_FMT_YUVA422P10LE:
+       case AV_PIX_FMT_YUVA444P10LE:
+               /* 16-bit little-endian */
+               for (int c = 0; c < 3; ++c) {
+                       int const stride_pixels = stride()[c] / 2;
+                       int const line_size_pixels = line_size()[c] / 2;
+                       uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
+                       for (int y = 0; y < lines(c); ++y) {
+                               uint16_t* q = p;
+                               for (int x = 0; x < line_size_pixels; ++x) {
+                                       *q = int (float (*q) * f);
+                                       ++q;
+                               }
+                               p += stride_pixels;
+                       }
+               }
+               break;
+
+       case PIX_FMT_YUV422P9BE:
+       case PIX_FMT_YUV444P9BE:
+       case PIX_FMT_YUV444P10BE:
+       case PIX_FMT_YUV422P10BE:
+       case AV_PIX_FMT_YUVA420P9BE:
+       case AV_PIX_FMT_YUVA422P9BE:
+       case AV_PIX_FMT_YUVA444P9BE:
+       case AV_PIX_FMT_YUVA420P10BE:
+       case AV_PIX_FMT_YUVA422P10BE:
+       case AV_PIX_FMT_YUVA444P10BE:
+       case AV_PIX_FMT_YUVA420P16BE:
+       case AV_PIX_FMT_YUVA422P16BE:
+       case AV_PIX_FMT_YUVA444P16BE:
+               /* 16-bit big-endian */
+               for (int c = 0; c < 3; ++c) {
+                       int const stride_pixels = stride()[c] / 2;
+                       int const line_size_pixels = line_size()[c] / 2;
+                       uint16_t* p = reinterpret_cast<uint16_t*> (data()[c]);
+                       for (int y = 0; y < lines(c); ++y) {
+                               uint16_t* q = p;
+                               for (int x = 0; x < line_size_pixels; ++x) {
+                                       *q = swap_16 (int (float (swap_16 (*q)) * f));
+                                       ++q;
+                               }
+                               p += stride_pixels;
+                       }
+               }
+               break;
+
+       case PIX_FMT_UYVY422:
+       {
+               int const Y = lines(0);
+               int const X = line_size()[0];
+               uint8_t* p = data()[0];
+               for (int y = 0; y < Y; ++y) {
+                       for (int x = 0; x < X; ++x) {
+                               *p = int (float (*p) * f);
+                               ++p;
+                       }
+               }
+               break;
+       }
+
+       default:
+               throw PixelFormatError ("fade()", _pixel_format);
+       }
+}