summaryrefslogtreecommitdiffstats
path: root/dom/canvas/gtest
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/canvas/gtest
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/canvas/gtest')
-rw-r--r--dom/canvas/gtest/TestImageBitmapColorUtils.cpp2585
-rw-r--r--dom/canvas/gtest/TestWebGLElementArrayCache.cpp206
-rw-r--r--dom/canvas/gtest/moz.build17
3 files changed, 2808 insertions, 0 deletions
diff --git a/dom/canvas/gtest/TestImageBitmapColorUtils.cpp b/dom/canvas/gtest/TestImageBitmapColorUtils.cpp
new file mode 100644
index 000000000..85ebe42ce
--- /dev/null
+++ b/dom/canvas/gtest/TestImageBitmapColorUtils.cpp
@@ -0,0 +1,2585 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "ImageBitmapColorUtils.h"
+#include "mozilla/dom/ImageBitmapBinding.h"
+#include "libyuv.h"
+
+using namespace mozilla::dom;
+
+template<typename T>
+class Image {
+public:
+ explicit Image(int aChannelCount)
+ : mChannelCount(aChannelCount), mData(nullptr)
+ {
+ }
+
+ virtual ~Image() {
+ if (mData) delete[] mData;
+ }
+
+ int mChannelCount;
+ T* mData;
+};
+
+template<typename T>
+class SimpleImage : public Image<T>
+{
+public:
+ SimpleImage(int aWidth, int aHeight, int aChannelCount)
+ : Image<T>(aChannelCount)
+ , mWidth(aWidth)
+ , mHeight(aHeight)
+ , mStride(aWidth * aChannelCount * sizeof(T))
+ {
+ Image<T>::mData = new T[mHeight * mStride];
+ }
+
+ virtual ~SimpleImage() {}
+
+ T GetPixelValue(int i, int j, int c) const
+ {
+ // The unit of mStride is byte.
+ const uint8_t* data = (const uint8_t*)Image<T>::mData;
+ return *((T*)(data + i * mStride) + j * Image<T>::mChannelCount + c);
+ }
+
+ int mWidth;
+ int mHeight;
+ int mStride;
+};
+
+class RGBA32DataSinglePixel : public SimpleImage<uint8_t> {
+public:
+ RGBA32DataSinglePixel(int r, int g, int b, int a)
+ : SimpleImage(1, 1, 4)
+ {
+ mData[0] = r;
+ mData[1] = g;
+ mData[2] = b;
+ mData[3] = a;
+ }
+};
+
+class RGB24Data : public SimpleImage<uint8_t> {
+public:
+ RGB24Data()
+ : SimpleImage(3, 3, 3)
+ {
+ int i = 0;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 0;
+ mData[i + 3] = 255; mData[i + 4] = 0; mData[i + 5] = 0;
+ mData[i + 6] = 0; mData[i + 7] = 255; mData[i + 8] = 0;
+
+ i = 1 * mStride;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 255;
+ mData[i + 3] = 255; mData[i + 4] = 255; mData[i + 5] = 0;
+ mData[i + 6] = 0; mData[i + 7] = 255; mData[i + 8] = 255;
+
+ i = 2 * mStride;
+ mData[i + 0] = 255; mData[i + 1] = 0; mData[i + 2] = 255;
+ mData[i + 3] = 255; mData[i + 4] = 255; mData[i + 5] = 255;
+ mData[i + 6] = 128; mData[i + 7] = 128; mData[i + 8] = 128;
+ }
+};
+
+class BGR24Data : public SimpleImage<uint8_t> {
+public:
+ BGR24Data()
+ : SimpleImage(3, 3, 3)
+ {
+ int i = 0;
+ mData[i + 2] = 0; mData[i + 1] = 0; mData[i + 0] = 0;
+ mData[i + 5] = 255; mData[i + 4] = 0; mData[i + 3] = 0;
+ mData[i + 8] = 0; mData[i + 7] = 255; mData[i + 6] = 0;
+
+ i = 1 * mStride;
+ mData[i + 2] = 0; mData[i + 1] = 0; mData[i + 0] = 255;
+ mData[i + 5] = 255; mData[i + 4] = 255; mData[i + 3] = 0;
+ mData[i + 8] = 0; mData[i + 7] = 255; mData[i + 6] = 255;
+
+ i = 2 * mStride;
+ mData[i + 2] = 255; mData[i + 1] = 0; mData[i + 0] = 255;
+ mData[i + 5] = 255; mData[i + 4] = 255; mData[i + 3] = 255;
+ mData[i + 8] = 128; mData[i + 7] = 128; mData[i + 6] = 128;
+ }
+};
+
+class RGBA32Data : public SimpleImage<uint8_t> {
+public:
+ RGBA32Data()
+ : SimpleImage(3, 3, 4)
+ {
+ int i = 0;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 0; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 0; mData[i + 6] = 0; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 255; mData[i + 10] = 0; mData[i + 11] = 255;
+
+ i = 1 * mStride;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 255; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 255; mData[i + 6] = 0; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 255; mData[i + 10] = 255; mData[i + 11] = 255;
+
+ i = 2 * mStride;
+ mData[i + 0] = 255; mData[i + 1] = 0; mData[i + 2] = 255; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 255; mData[i + 6] = 255; mData[i + 7] = 255;
+ mData[i + 8] = 128; mData[i + 9] = 128; mData[i + 10] = 128; mData[i + 11] = 255;
+ }
+};
+
+class BGRA32Data : public SimpleImage<uint8_t> {
+public:
+ BGRA32Data()
+ : SimpleImage(3, 3, 4)
+ {
+ int i = 0;
+ mData[i + 2] = 0; mData[i + 1] = 0; mData[i + 0] = 0; mData[i + 3] = 255;
+ mData[i + 6] = 255; mData[i + 5] = 0; mData[i + 4] = 0; mData[i + 7] = 255;
+ mData[i + 10] = 0; mData[i + 9] = 255; mData[i + 8] = 0; mData[i + 11] = 255;
+
+ i = 1 * mStride;
+ mData[i + 2] = 0; mData[i + 1] = 0; mData[i + 0] = 255; mData[i + 3] = 255;
+ mData[i + 6] = 255; mData[i + 5] = 255; mData[i + 4] = 0; mData[i + 7] = 255;
+ mData[i + 10] = 0; mData[i + 9] = 255; mData[i + 8] = 255; mData[i + 11] = 255;
+
+ i = 2 * mStride;
+ mData[i + 2] = 255; mData[i + 1] = 0; mData[i + 0] = 255; mData[i + 3] = 255;
+ mData[i + 6] = 255; mData[i + 5] = 255; mData[i + 4] = 255; mData[i + 7] = 255;
+ mData[i + 10] = 128; mData[i + 9] = 128; mData[i + 8] = 128; mData[i + 11] = 255;
+ }
+};
+
+class RGBA32Image : public SimpleImage<uint8_t>
+{
+public:
+ RGBA32Image(int aWidth, int aHeight, int aChannelCount)
+ : SimpleImage(aWidth, aHeight, aChannelCount)
+ {}
+
+ const uint8_t* GetPixel(int x, int y) const {
+ return mData + mStride * y + x * mChannelCount;
+ }
+};
+
+class RGBA32DataFromYUV444PData : public RGBA32Image {
+public:
+ RGBA32DataFromYUV444PData()
+ : RGBA32Image(3, 3, 4)
+ {
+// libyuv: (16, 128, 128) --> (0, 0, 0, 255)
+// libyuv: (82, 90, 240) --> (254, 0, 0, 255)
+// libyuv: (144, 54, 34) --> (0, 253, 1, 255)
+// libyuv: (41, 240, 110) --> (0, 0, 251, 255)
+// libyuv: (210, 16, 146) --> (253, 253, 2, 255)
+// libyuv: (169, 166, 16) --> (0, 253, 252, 255)
+// libyuv: (107, 202, 222) --> (255, 0, 252, 255)
+// libyuv: (235, 128, 128) --> (253, 253, 253, 255)
+// libyuv: (126, 128, 128) --> (127, 127, 127, 255)
+
+ int i = 0;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 0; mData[i + 3] = 255;
+ mData[i + 4] = 254; mData[i + 5] = 0; mData[i + 6] = 0; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 253; mData[i + 10] = 1; mData[i + 11] = 255;
+
+ i = 1 * mStride;
+ mData[i + 0] = 0; mData[i + 1] = 0; mData[i + 2] = 251; mData[i + 3] = 255;
+ mData[i + 4] = 253; mData[i + 5] = 253; mData[i + 6] = 2; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 253; mData[i + 10] = 252; mData[i + 11] = 255;
+
+ i = 2 * mStride;
+ mData[i + 0] = 255; mData[i + 1] = 0; mData[i + 2] = 252; mData[i + 3] = 255;
+ mData[i + 4] = 253; mData[i + 5] = 253; mData[i + 6] = 253; mData[i + 7] = 255;
+ mData[i + 8] = 127; mData[i + 9] = 127; mData[i + 10] = 127; mData[i + 11] = 255;
+ }
+};
+
+class RGBA32DataFromYUV422PData : public RGBA32Image {
+public:
+ RGBA32DataFromYUV422PData()
+ : RGBA32Image(3, 3, 4)
+ {
+// libyuv: (16, 109, 184) --> (89, 0, 0, 255)
+// libyuv: (82, 109, 184) --> (165, 38, 38, 255)
+// libyuv: (144, 54, 34) --> (0, 253, 1, 255)
+// libyuv: (41, 128, 128) --> (28, 28, 28, 255)
+// libyuv: (210, 128, 128) --> (224, 224, 224, 255)
+// libyuv: (169, 166, 16) --> (0, 253, 252, 255)
+// libyuv: (107, 165, 175) --> (180, 52, 178, 255)
+// libyuv: (235, 165, 175) --> (255, 200, 255, 255)
+// libyuv: (126, 128, 128) --> (127, 127, 127, 255)
+
+ int i = 0;
+ mData[i + 0] = 89; mData[i + 1] = 0; mData[i + 2] = 0; mData[i + 3] = 255;
+ mData[i + 4] = 165; mData[i + 5] = 38; mData[i + 6] = 38; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 253; mData[i + 10] = 1; mData[i + 11] = 255;
+
+ i = 1 * mStride;
+ mData[i + 0] = 28; mData[i + 1] = 28; mData[i + 2] = 28; mData[i + 3] = 255;
+ mData[i + 4] = 224; mData[i + 5] = 224; mData[i + 6] = 224; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 253; mData[i + 10] = 252; mData[i + 11] = 255;
+
+ i = 2 * mStride;
+ mData[i + 0] = 180; mData[i + 1] = 52; mData[i + 2] = 178; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 200; mData[i + 6] = 255; mData[i + 7] = 255;
+ mData[i + 8] = 127; mData[i + 9] = 127; mData[i + 10] = 127; mData[i + 11] = 255;
+ }
+};
+
+class RGBA32DataFromYUV420PData : public RGBA32Image {
+public:
+ RGBA32DataFromYUV420PData()
+ : RGBA32Image(3, 3, 4)
+ {
+// libyuv: (16, 119, 156) --> (44, 0, 0, 255)
+// libyuv: (82, 119, 156) --> (120, 57, 58, 255)
+// libyuv: (144, 110, 25) --> (0, 238, 112, 255)
+// libyuv: (41, 119, 156) --> (73, 9, 11, 255)
+// libyuv: (210, 119, 156) --> (255, 205, 206, 255)
+// libyuv: (169, 110, 25) --> (12, 255, 141, 255)
+// libyuv: (107, 165, 175) --> (180, 52, 178, 255)
+// libyuv: (235, 165, 175) --> (255, 200, 255, 255)
+// libyuv: (126, 128, 128) --> (127, 127, 127, 255)
+
+ int i = 0;
+ mData[i + 0] = 44; mData[i + 1] = 0; mData[i + 2] = 0; mData[i + 3] = 255;
+ mData[i + 4] = 120; mData[i + 5] = 57; mData[i + 6] = 58; mData[i + 7] = 255;
+ mData[i + 8] = 0; mData[i + 9] = 238; mData[i + 10] = 112; mData[i + 11] = 255;
+
+ i = 1 * mStride;
+ mData[i + 0] = 73; mData[i + 1] = 9; mData[i + 2] = 11; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 205; mData[i + 6] = 206; mData[i + 7] = 255;
+ mData[i + 8] = 12; mData[i + 9] = 255; mData[i + 10] = 141; mData[i + 11] = 255;
+
+ i = 2 * mStride;
+ mData[i + 0] = 180; mData[i + 1] = 52; mData[i + 2] = 178; mData[i + 3] = 255;
+ mData[i + 4] = 255; mData[i + 5] = 200; mData[i + 6] = 255; mData[i + 7] = 255;
+ mData[i + 8] = 127; mData[i + 9] = 127; mData[i + 10] = 127; mData[i + 11] = 255;
+ }
+};
+
+class GrayData : public SimpleImage<uint8_t> {
+public:
+ GrayData()
+ : SimpleImage(3, 3, 1)
+ {
+ int i = 0;
+ mData[i + 0] = 0; mData[i + 1] = 76; mData[i + 2] = 149;
+
+ i = 1 * mStride;
+ mData[i + 0] = 29; mData[i + 1] = 225; mData[i + 2] = 178;
+
+ i = 2 * mStride;
+ mData[i + 0] = 105; mData[i + 1] = 255; mData[i + 2] = 127;
+ }
+};
+
+class YUVImage : public Image<uint8_t>
+{
+public:
+ YUVImage(int aYWidth, int aYHeight, int aYStride,
+ int aUWidth, int aUHeight, int aUStride,
+ int aVWidth, int aVHeight, int aVStride)
+ : Image(3)
+ , mYWidth(aYWidth), mYHeight(aYHeight), mYStride(aYStride)
+ , mUWidth(aUWidth), mUHeight(aUHeight), mUStride(aUStride)
+ , mVWidth(aVWidth), mVHeight(aVHeight), mVStride(aVStride)
+ {
+ mData = new uint8_t[mYHeight * mYStride + mUHeight * mUStride + mVHeight * mVStride];
+ }
+
+ uint8_t* YBuffer() const { return mData; }
+ uint8_t* UBuffer() const { return YBuffer() + mYHeight * mYStride; }
+ uint8_t* VBuffer() const { return UBuffer() + mUHeight * mUStride; }
+
+ int mYWidth;
+ int mYHeight;
+ int mYStride;
+ int mUWidth;
+ int mUHeight;
+ int mUStride;
+ int mVWidth;
+ int mVHeight;
+ int mVStride;
+};
+
+class NVImage : public Image<uint8_t>
+{
+public:
+ NVImage(int aYWidth, int aYHeight, int aYStride,
+ int aUVWidth, int aUVHeight, int aUVStride)
+ : Image(3)
+ , mYWidth(aYWidth), mYHeight(aYHeight), mYStride(aYStride)
+ , mUVWidth(aUVWidth), mUVHeight(aUVHeight), mUVStride(aUVStride)
+ {
+ mData = new uint8_t[mYHeight * mYStride + mUVHeight * mUVStride];
+ }
+
+ uint8_t* YBuffer() const { return mData; }
+ uint8_t* UVBuffer() const { return YBuffer() + mYHeight * mYStride; }
+
+ int mYWidth;
+ int mYHeight;
+ int mYStride;
+ int mUVWidth;
+ int mUVHeight;
+ int mUVStride;
+};
+
+class YUV444PData : public YUVImage
+{
+public:
+ YUV444PData()
+ :YUVImage(3, 3, 3, 3, 3, 3, 3, 3, 3)
+ {
+// libyuv: (0, 0, 0) --> (16, 128, 128)
+// libyuv: (255, 0, 0) --> (82, 90, 240)
+// libyuv: (0, 255, 0) --> (144, 54, 34)
+// libyuv: (0, 0, 255) --> (41, 240, 110)
+// libyuv: (255, 255, 0) --> (210, 16, 146)
+// libyuv: (0, 255, 255) --> (169, 166, 16)
+// libyuv: (255, 0, 255) --> (107, 202, 222)
+// libyuv: (255, 255, 255) --> (235, 128, 128)
+// libyuv: (128, 128, 128) --> (126, 128, 128)
+
+ YBuffer()[0] = 16; YBuffer()[1] = 82; YBuffer()[2] = 144;
+ YBuffer()[3] = 41; YBuffer()[4] = 210; YBuffer()[5] = 169;
+ YBuffer()[6] = 107; YBuffer()[7] = 235; YBuffer()[8] = 126;
+
+ UBuffer()[0] = 128; UBuffer()[1] = 90; UBuffer()[2] = 54;
+ UBuffer()[3] = 240; UBuffer()[4] = 16; UBuffer()[5] = 166;
+ UBuffer()[6] = 202; UBuffer()[7] = 128; UBuffer()[8] = 128;
+
+ VBuffer()[0] = 128; VBuffer()[1] = 240; VBuffer()[2] = 34;
+ VBuffer()[3] = 110; VBuffer()[4] = 146; VBuffer()[5] = 16;
+ VBuffer()[6] = 222; VBuffer()[7] = 128; VBuffer()[8] = 128;
+ }
+};
+
+class YUV422PData : public YUVImage
+{
+public:
+ YUV422PData()
+ :YUVImage(3, 3, 3, 2, 3, 2, 2, 3, 2)
+ {
+ YBuffer()[0] = 16; YBuffer()[1] = 82; YBuffer()[2] = 144;
+ YBuffer()[3] = 41; YBuffer()[4] = 210; YBuffer()[5] = 169;
+ YBuffer()[6] = 107; YBuffer()[7] = 235; YBuffer()[8] = 126;
+
+ UBuffer()[0] = 109; UBuffer()[1] = 54;
+ UBuffer()[2] = 128; UBuffer()[3] = 166;
+ UBuffer()[4] = 165; UBuffer()[5] = 128;
+
+ VBuffer()[0] = 184; VBuffer()[1] = 34;
+ VBuffer()[2] = 128; VBuffer()[3] = 16;
+ VBuffer()[4] = 175; VBuffer()[5] = 128;
+ }
+};
+
+class YUV420PData : public YUVImage
+{
+public:
+ YUV420PData()
+ :YUVImage(3, 3, 3, 2, 2, 2, 2, 2, 2)
+ {
+ YBuffer()[0] = 16; YBuffer()[1] = 82; YBuffer()[2] = 144;
+ YBuffer()[3] = 41; YBuffer()[4] = 210; YBuffer()[5] = 169;
+ YBuffer()[6] = 107; YBuffer()[7] = 235; YBuffer()[8] = 126;
+
+ UBuffer()[0] = 119; UBuffer()[1] = 110;
+ UBuffer()[2] = 165; UBuffer()[3] = 128;
+
+ VBuffer()[0] = 156; VBuffer()[1] = 25;
+ VBuffer()[2] = 175; VBuffer()[3] = 128;
+ }
+};
+
+class NV12Data : public NVImage
+{
+public:
+ NV12Data()
+ :NVImage(3, 3, 3, 2, 2, 4)
+ {
+ YBuffer()[0] = 16; YBuffer()[1] = 82; YBuffer()[2] = 144;
+ YBuffer()[3] = 41; YBuffer()[4] = 210; YBuffer()[5] = 169;
+ YBuffer()[6] = 107; YBuffer()[7] = 235; YBuffer()[8] = 126;
+
+ // U
+ UVBuffer()[0] = 119;
+ UVBuffer()[2] = 110;
+ UVBuffer()[4] = 165;
+ UVBuffer()[6] = 128;
+
+ // V
+ UVBuffer()[1] = 156;
+ UVBuffer()[3] = 25;
+ UVBuffer()[5] = 175;
+ UVBuffer()[7] = 128;
+ }
+};
+
+class NV21Data : public NVImage
+{
+public:
+ NV21Data()
+ :NVImage(3, 3, 3, 2, 2, 4)
+ {
+ YBuffer()[0] = 16; YBuffer()[1] = 82; YBuffer()[2] = 144;
+ YBuffer()[3] = 41; YBuffer()[4] = 210; YBuffer()[5] = 169;
+ YBuffer()[6] = 107; YBuffer()[7] = 235; YBuffer()[8] = 126;
+
+ // U
+ UVBuffer()[1] = 119;
+ UVBuffer()[3] = 110;
+ UVBuffer()[5] = 165;
+ UVBuffer()[7] = 128;
+
+ // V
+ UVBuffer()[0] = 156;
+ UVBuffer()[2] = 25;
+ UVBuffer()[4] = 175;
+ UVBuffer()[6] = 128;
+ }
+};
+
+class HSVData : public SimpleImage<float>
+{
+public:
+ HSVData()
+ : SimpleImage(3, 3, 3)
+ {
+ int i = 0;
+ mData[i + 0] = 0.0f; mData[i + 1] = 0.0f; mData[i + 2] = 0.0f;
+ mData[i + 3] = 0.0f; mData[i + 4] = 1.0f; mData[i + 5] = 1.0f;
+ mData[i + 6] = 120.0f; mData[i + 7] = 1.0f; mData[i + 8] = 1.0f;
+
+ i += mWidth * mChannelCount;
+ mData[i + 0] = 240.0f; mData[i + 1] = 1.0f; mData[i + 2] = 1.0f;
+ mData[i + 3] = 60.0f; mData[i + 4] = 1.0f; mData[i + 5] = 1.0f;
+ mData[i + 6] = 180.0f; mData[i + 7] = 1.0f; mData[i + 8] = 1.0f;
+
+ i += mWidth * mChannelCount;
+ mData[i + 0] = 300.0f; mData[i + 1] = 1.0f; mData[i + 2] = 1.0f;
+ mData[i + 3] = 0.0f; mData[i + 4] = 0.0f; mData[i + 5] = 1.0f;
+ mData[i + 6] = 0.0f; mData[i + 7] = 0.0f; mData[i + 8] = 0.50196081f;
+ }
+};
+
+class LabData : public SimpleImage<float>
+{
+public:
+ LabData()
+ : SimpleImage(3, 3, 3)
+ {
+ int i = 0;
+ mData[i + 0] = 0.0f; mData[i + 1] = 0.0f; mData[i + 2] = 0.0f;
+ mData[i + 3] = 53.240585f; mData[i + 4] = 80.094185f; mData[i + 5] = 67.201538f;
+ mData[i + 6] = 87.7351f; mData[i + 7] = -86.181252f; mData[i + 8] = 83.177483f;
+
+ i += mWidth * mChannelCount;
+ mData[i + 0] = 32.29567f; mData[i + 1] = 79.186989f; mData[i + 2] = -107.86176f;
+ mData[i + 3] = 97.139511f; mData[i + 4] = -21.552414f; mData[i + 5] = 94.475792f;
+ mData[i + 6] = 91.113297f; mData[i + 7] = -48.088551f; mData[i + 8] = -14.130962f;
+
+ i += mWidth * mChannelCount;
+ mData[i + 0] = 60.323502f; mData[i + 1] = 98.235161f; mData[i + 2] = -60.825493f;
+ mData[i + 3] = 100.0f; mData[i + 4] = 0.0f; mData[i + 5] = 0.0f;
+ mData[i + 6] = 53.585014f; mData[i + 7] = 0.0f; mData[i + 8] = 0.0f;
+ }
+};
+
+/*
+ * From RGB24.
+ */
+
+TEST(ImageBitmapColorUtils, RGB24ToRGB24_)
+{
+ const RGB24Data srcData;
+ const RGB24Data dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGB24ToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToBGR24_)
+{
+ const RGB24Data srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGB24ToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToRGBA32)
+{
+ const RGB24Data srcData;
+ const RGBA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGB24ToRGBA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ 255);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToBGRA32)
+{
+ const RGB24Data srcData;
+ const BGRA32Data dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGB24ToBGRA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ 255);
+ }
+ }
+}
+
+
+//static void tryLibyuv(int r, int g, int b)
+//{
+// const RGBA32DataSinglePixel srcData(r, g, b, 255);
+// YUVImage result_(1, 1, 1, 1, 1, 1, 1, 1, 1);
+//
+// int length = result_.mYHeight * result_.mYStride +
+// result_.mUHeight * result_.mUStride +
+// result_.mVHeight * result_.mVStride;
+//
+// int rv = libyuv::ABGRToI420(srcData.mData, srcData.mStride,
+// result_.YBuffer(), result_.mYStride,
+// result_.UBuffer(), result_.mUStride,
+// result_.VBuffer(), result_.mVStride,
+// result_.mWidth, result_.mHeight);
+//
+// printf_stderr("\nlibyuv: (%hhu, %hhu, %hhu) --> (%hhu, %hhu, %hhu) \n",
+// r, g, b,
+// result_.YBuffer()[0],
+// result_.UBuffer()[0],
+// result_.VBuffer()[0]);
+//}
+
+//static void tryLibyuv(int y, int u, int v)
+//{
+// uint8_t* yuvPixel = new uint8_t[3];
+// uint8_t* rgbaPixel = new uint8_t[4];
+//
+// yuvPixel[0] = y;
+// yuvPixel[1] = u;
+// yuvPixel[2] = v;
+//
+// int rv = libyuv::I420ToABGR(yuvPixel + 0, 1,
+// yuvPixel + 1, 1,
+// yuvPixel + 2, 1,
+// rgbaPixel, 4,
+// 1, 1);
+//
+// printf_stderr("\nlibyuv: (%hhu, %hhu, %hhu) --> (%hhu, %hhu, %hhu, %hhu) \n",
+// yuvPixel[0], yuvPixel[1], yuvPixel[2],
+// rgbaPixel[0], rgbaPixel[1], rgbaPixel[2], rgbaPixel[3]);
+//}
+
+TEST(ImageBitmapColorUtils, RGB24ToYUV444P)
+{
+ const RGB24Data srcData;
+ const YUV444PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride);
+
+ int rv = RGB24ToYUV444P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToYUV422P)
+{
+ const RGB24Data srcData;
+ const YUV422PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride);
+
+ int rv = RGB24ToYUV422P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToYUV420P)
+{
+ const RGB24Data srcData;
+ const YUV420PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride);
+
+ int rv = RGB24ToYUV420P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToNV12)
+{
+ const RGB24Data srcData;
+ const NV12Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = RGB24ToNV12(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToNV21)
+{
+ const RGB24Data srcData;
+ const NV21Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = RGB24ToNV21(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToHSV)
+{
+ const RGB24Data srcData;
+ const HSVData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = RGB24ToHSV(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToLab)
+{
+ const RGB24Data srcData;
+ const LabData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = RGB24ToLab(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGB24ToGray8)
+{
+ const RGB24Data srcData;
+ const GrayData dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, 1);
+
+ int rv = RGB24ToGray8(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ dstData.mData[i * dstData.mStride + j]);
+ }
+ }
+}
+
+/*
+ * From BGR24.
+ */
+
+TEST(ImageBitmapColorUtils, BGR24ToRGB24_)
+{
+ const BGR24Data srcData;
+ const RGB24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGR24ToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToBGR24_)
+{
+ const BGR24Data srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGR24ToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToRGBA32)
+{
+ const BGR24Data srcData;
+ const RGBA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGR24ToRGBA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ 255);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToBGRA32)
+{
+ const BGR24Data srcData;
+ const BGRA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGR24ToBGRA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ 255);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToYUV444P)
+{
+ const BGR24Data srcData;
+ const YUV444PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride);
+
+ int rv = BGR24ToYUV444P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToYUV422P)
+{
+ const BGR24Data srcData;
+ const YUV422PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride);
+
+ int rv = BGR24ToYUV422P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToYUV420P)
+{
+ const BGR24Data srcData;
+ const YUV420PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride);
+
+ int rv = BGR24ToYUV420P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToNV12)
+{
+ const BGR24Data srcData;
+ const NV12Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = BGR24ToNV12(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToNV21)
+{
+ const BGR24Data srcData;
+ const NV21Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = BGR24ToNV21(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToHSV)
+{
+ const BGR24Data srcData;
+ const HSVData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = BGR24ToHSV(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToLab)
+{
+ const BGR24Data srcData;
+ const LabData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = BGR24ToLab(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGR24ToGray8)
+{
+ const BGR24Data srcData;
+ const GrayData dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, 1);
+
+ int rv = BGR24ToGray8(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ dstData.mData[i * dstData.mStride + j]);
+ }
+ }
+}
+
+/*
+ * From RGBA32.
+ */
+TEST(ImageBitmapColorUtils, RGBA32ToRGB24)
+{
+ const RGBA32Data srcData;
+ const RGB24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGBA32ToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToBGR24)
+{
+ const RGBA32Data srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = RGBA32ToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToYUV444P)
+{
+ const RGBA32Data srcData;
+ const YUV444PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride);
+
+ int rv = RGBA32ToYUV444P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToYUV422P)
+{
+ const RGBA32Data srcData;
+ const YUV422PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride);
+
+ int rv = RGBA32ToYUV422P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToYUV420P)
+{
+ const RGBA32Data srcData;
+ const YUV420PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride);
+
+ int rv = RGBA32ToYUV420P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToNV12)
+{
+ const RGBA32Data srcData;
+ const NV12Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = RGBA32ToNV12(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToNV21)
+{
+ const RGBA32Data srcData;
+ const NV21Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = RGBA32ToNV21(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToHSV)
+{
+ const RGBA32Data srcData;
+ const HSVData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = RGBA32ToHSV(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToLab)
+{
+ const RGBA32Data srcData;
+ const LabData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = RGBA32ToLab(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, RGBA32ToGray8)
+{
+ const RGBA32Data srcData;
+ const GrayData dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, 1);
+
+ int rv = RGBA32ToGray8(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ dstData.mData[i * dstData.mStride + j]);
+ }
+ }
+}
+
+/*
+ * From BGRA32.
+ */
+TEST(ImageBitmapColorUtils, BGRA32ToRGB24)
+{
+ const BGRA32Data srcData;
+ const RGB24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGRA32ToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToBGR24)
+{
+ const BGRA32Data srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = BGRA32ToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.mData[i * dstData.mStride + j * dstData.mChannelCount + 2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToYUV444P)
+{
+ const BGRA32Data srcData;
+ const YUV444PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth, srcData.mHeight, srcData.mStride);
+
+ int rv = BGRA32ToYUV444P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToYUV422P)
+{
+ const BGRA32Data srcData;
+ const YUV422PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight, srcData.mStride);
+
+ int rv = BGRA32ToYUV422P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToYUV420P)
+{
+ const BGRA32Data srcData;
+ const YUV420PData dstData;
+
+ YUVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride);
+
+ int rv = BGRA32ToYUV420P(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UBuffer(), result_.mUStride,
+ result_.VBuffer(), result_.mVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUHeight; ++i) {
+ for (int j = 0; j < dstData.mUWidth; ++j) {
+ EXPECT_EQ(dstData.UBuffer()[i * dstData.mUStride + j],
+ result_.UBuffer()[i * result_.mUStride + j]);
+ EXPECT_EQ(dstData.VBuffer()[i * dstData.mVStride + j],
+ result_.VBuffer()[i * result_.mVStride + j]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToNV12)
+{
+ const BGRA32Data srcData;
+ const NV12Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = BGRA32ToNV12(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToNV21)
+{
+ const BGRA32Data srcData;
+ const NV21Data dstData;
+
+ NVImage result_(srcData.mWidth, srcData.mHeight, srcData.mStride,
+ srcData.mWidth / 2 + 1, srcData.mHeight / 2 + 1, srcData.mStride + 10);
+
+ int rv = BGRA32ToNV21(srcData.mData, srcData.mStride,
+ result_.YBuffer(), result_.mYStride,
+ result_.UVBuffer(), result_.mUVStride,
+ result_.mYWidth, result_.mYHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mYHeight; ++i) {
+ for (int j = 0; j < dstData.mYWidth; ++j) {
+ EXPECT_EQ(dstData.YBuffer()[i * dstData.mYStride + j],
+ result_.YBuffer()[i * result_.mYStride + j]);
+ }
+ }
+
+ for (int i = 0; i < dstData.mUVHeight; ++i) {
+ for (int j = 0; j < dstData.mUVWidth; ++j) {
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 0],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 0]);
+ EXPECT_EQ(dstData.UVBuffer()[i * dstData.mUVStride + j * 2 + 1],
+ result_.UVBuffer()[i * result_.mUVStride + j * 2 + 1]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToHSV)
+{
+ const BGRA32Data srcData;
+ const HSVData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = BGRA32ToHSV(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToLab)
+{
+ const BGRA32Data srcData;
+ const LabData dstData;
+
+ SimpleImage<float> result_(srcData.mWidth, srcData.mHeight, 3);
+
+ int rv = BGRA32ToLab(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const double actualValue = result_.GetPixelValue(i, j, c);
+ const double expectedValue = dstData.GetPixelValue(i, j, c);
+ const double diff = std::abs(actualValue - expectedValue);
+ EXPECT_LT(diff, 1.0);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, BGRA32ToGray8)
+{
+ const BGRA32Data srcData;
+ const GrayData dstData;
+
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, 1);
+
+ int rv = BGRA32ToGray8(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < dstData.mHeight; ++i) {
+ for (int j = 0; j < dstData.mWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ dstData.mData[i * dstData.mStride + j]);
+ }
+ }
+}
+
+/*
+ * From YUV444P.
+ */
+TEST(ImageBitmapColorUtils, YUV444PToRGB24)
+{
+ const YUV444PData srcData;
+ const RGBA32DataFromYUV444PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV444PToRGB24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV444PToBGR24)
+{
+ const YUV444PData srcData;
+ const RGBA32DataFromYUV444PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV444PToBGR24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV444PToRGBA32)
+{
+ const YUV444PData srcData;
+ const RGBA32DataFromYUV444PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV444PToRGBA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV444PToBGRA32)
+{
+ const YUV444PData srcData;
+ const RGBA32DataFromYUV444PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV444PToBGRA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV444PToGray8)
+{
+ const YUV444PData srcData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 1);
+
+ int rv = YUV444PToGray8(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ srcData.YBuffer()[i * srcData.mYStride + j]);
+ }
+ }
+}
+
+/*
+ * From YUV422P.
+ */
+TEST(ImageBitmapColorUtils, YUV422PToRGB24)
+{
+ const YUV422PData srcData;
+ const RGBA32DataFromYUV422PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV422PToRGB24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV422PToBGR24)
+{
+ const YUV422PData srcData;
+ const RGBA32DataFromYUV422PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV422PToBGR24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV422PToRGBA32)
+{
+ const YUV422PData srcData;
+ const RGBA32DataFromYUV422PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV422PToRGBA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV422PToBGRA32)
+{
+ const YUV422PData srcData;
+ const RGBA32DataFromYUV422PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV422PToBGRA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV422PToGray8)
+{
+ const YUV422PData srcData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 1);
+
+ int rv = YUV422PToGray8(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ srcData.YBuffer()[i * srcData.mYStride + j]);
+ }
+ }
+}
+
+/*
+ * From YUV420P.
+ */
+TEST(ImageBitmapColorUtils, YUV420PToRGB24)
+{
+ const YUV420PData srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV420PToRGB24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV420PToBGR24)
+{
+ const YUV420PData srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = YUV420PToBGR24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV420PToRGBA32)
+{
+ const YUV420PData srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV420PToRGBA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV420PToBGRA32)
+{
+ const YUV420PData srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = YUV420PToBGRA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, YUV420PToGray8)
+{
+ const YUV420PData srcData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 1);
+
+ int rv = YUV420PToGray8(srcData.YBuffer(), srcData.mYStride,
+ srcData.UBuffer(), srcData.mUStride,
+ srcData.VBuffer(), srcData.mVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ srcData.YBuffer()[i * srcData.mYStride + j]);
+ }
+ }
+}
+
+/*
+ * From NV12.
+ */
+TEST(ImageBitmapColorUtils, NV12ToRGB24)
+{
+ const NV12Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = NV12ToRGB24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV12ToBGR24)
+{
+ const NV12Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = NV12ToBGR24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV12ToRGBA32)
+{
+ const NV12Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = NV12ToRGBA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV12ToBGRA32)
+{
+ const NV12Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = NV12ToBGRA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV12ToGray8)
+{
+ const NV12Data srcData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 1);
+
+ int rv = NV12ToGray8(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ srcData.YBuffer()[i * srcData.mYStride + j]);
+ }
+ }
+}
+
+/*
+ * From NV21.
+ */
+TEST(ImageBitmapColorUtils, NV21ToRGB24)
+{
+ const NV21Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = NV21ToRGB24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV21ToBGR24)
+{
+ const NV21Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 3);
+
+ int rv = NV21ToBGR24(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV21ToRGBA32)
+{
+ const NV21Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = NV21ToRGBA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV21ToBGRA32)
+{
+ const NV21Data srcData;
+ const RGBA32DataFromYUV420PData dstData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, dstData.mChannelCount);
+
+ int rv = NV21ToBGRA32(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 0],
+ dstData.GetPixel(j, i)[2]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 1],
+ dstData.GetPixel(j, i)[1]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 2],
+ dstData.GetPixel(j, i)[0]);
+ EXPECT_EQ(result_.mData[i * result_.mStride + j * result_.mChannelCount + 3],
+ dstData.GetPixel(j, i)[3]);
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, NV21ToGray8)
+{
+ const NV21Data srcData;
+ SimpleImage<uint8_t> result_(srcData.mYWidth, srcData.mYHeight, 1);
+
+ int rv = NV21ToGray8(srcData.YBuffer(), srcData.mYStride,
+ srcData.UVBuffer(), srcData.mUVStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mYHeight; ++i) {
+ for (int j = 0; j < srcData.mYWidth; ++j) {
+ EXPECT_EQ(result_.mData[i * result_.mStride + j],
+ srcData.YBuffer()[i * srcData.mYStride + j]);
+ }
+ }
+}
+
+/*
+ * From HSV.
+ */
+TEST(ImageBitmapColorUtils, HSVToRGB24)
+{
+ const HSVData srcData;
+ const RGB24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = HSVToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ EXPECT_EQ(result_.GetPixelValue(i, j, c),
+ dstData.GetPixelValue(i, j, c));
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, HSVToBGR24)
+{
+ const HSVData srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = HSVToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ EXPECT_EQ(result_.GetPixelValue(i, j, c),
+ dstData.GetPixelValue(i, j, c));
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, HSVToRGBA32)
+{
+ const HSVData srcData;
+ const RGBA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = HSVToRGBA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ EXPECT_EQ(result_.GetPixelValue(i, j, c),
+ dstData.GetPixelValue(i, j, c));
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, HSVToBGRA32)
+{
+ const HSVData srcData;
+ const BGRA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = HSVToBGRA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ EXPECT_EQ(result_.GetPixelValue(i, j, c),
+ dstData.GetPixelValue(i, j, c));
+ }
+ }
+ }
+}
+
+/*
+ * From Lab.
+ */
+TEST(ImageBitmapColorUtils, LabToRGB24)
+{
+ const LabData srcData;
+ const RGB24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = LabToRGB24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const uint8_t actualValue = result_.GetPixelValue(i, j, c);
+ const uint8_t expectedValue = dstData.GetPixelValue(i, j, c);
+ const int diff = std::abs(actualValue - expectedValue);
+ EXPECT_LE(diff, 1);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, LabToBGR24)
+{
+ const LabData srcData;
+ const BGR24Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = LabToBGR24(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const uint8_t actualValue = result_.GetPixelValue(i, j, c);
+ const uint8_t expectedValue = dstData.GetPixelValue(i, j, c);
+ const int diff = std::abs(actualValue - expectedValue);
+ EXPECT_LE(diff, 1);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, LabToRGBA32)
+{
+ const LabData srcData;
+ const RGBA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = LabToRGBA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const uint8_t actualValue = result_.GetPixelValue(i, j, c);
+ const uint8_t expectedValue = dstData.GetPixelValue(i, j, c);
+ const int diff = std::abs(actualValue - expectedValue);
+ EXPECT_LE(diff, 1);
+ }
+ }
+ }
+}
+
+TEST(ImageBitmapColorUtils, LabToBGRA32)
+{
+ const LabData srcData;
+ const BGRA32Data dstData;
+ SimpleImage<uint8_t> result_(srcData.mWidth, srcData.mHeight, dstData.mChannelCount);
+
+ int rv = LabToBGRA32(srcData.mData, srcData.mStride,
+ result_.mData, result_.mStride,
+ result_.mWidth, result_.mHeight);
+
+ ASSERT_TRUE(rv == 0);
+
+ for (int i = 0; i < srcData.mHeight; ++i) {
+ for (int j = 0; j < srcData.mWidth; ++j) {
+ for (int c = 0; c < dstData.mChannelCount; ++c) {
+ const uint8_t actualValue = result_.GetPixelValue(i, j, c);
+ const uint8_t expectedValue = dstData.GetPixelValue(i, j, c);
+ const int diff = std::abs(actualValue - expectedValue);
+ EXPECT_LE(diff, 1);
+ }
+ }
+ }
+}
diff --git a/dom/canvas/gtest/TestWebGLElementArrayCache.cpp b/dom/canvas/gtest/TestWebGLElementArrayCache.cpp
new file mode 100644
index 000000000..c8ffc8701
--- /dev/null
+++ b/dom/canvas/gtest/TestWebGLElementArrayCache.cpp
@@ -0,0 +1,206 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Assertions.h"
+
+#include "WebGLElementArrayCache.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include "nscore.h"
+#include "nsTArray.h"
+
+void
+MakeRandomVector(nsTArray<uint8_t>& a, size_t size)
+{
+ a.SetLength(size);
+ // only the most-significant bits of rand() are reasonably random.
+ // RAND_MAX can be as low as 0x7fff, and we need 8 bits for the result, so we can only
+ // ignore the 7 least significant bits.
+ for (size_t i = 0; i < size; i++)
+ a[i] = static_cast<uint8_t>((unsigned int)(rand()) >> 7);
+}
+
+template<typename T>
+T
+RandomInteger(T a, T b)
+{
+ T result(a + rand() % (b - a + 1));
+ return result;
+}
+
+template<typename T>
+GLenum
+GLType()
+{
+ switch (sizeof(T)) {
+ case 4: return LOCAL_GL_UNSIGNED_INT;
+ case 2: return LOCAL_GL_UNSIGNED_SHORT;
+ case 1: return LOCAL_GL_UNSIGNED_BYTE;
+ default:
+ MOZ_RELEASE_ASSERT(false);
+ return 0;
+ }
+}
+
+void
+CheckValidate(bool expectSuccess, mozilla::WebGLElementArrayCache& c, GLenum type,
+ uint32_t maxAllowed, size_t first, size_t count)
+{
+ const bool success = c.Validate(type, maxAllowed, first, count);
+ ASSERT_TRUE(success == expectSuccess);
+}
+
+template<typename T>
+void
+CheckValidateOneTypeVariousBounds(mozilla::WebGLElementArrayCache& c, size_t firstByte,
+ size_t countBytes)
+{
+ size_t first = firstByte / sizeof(T);
+ size_t count = countBytes / sizeof(T);
+
+ GLenum type = GLType<T>();
+
+ T max = 0;
+ for (size_t i = 0; i < count; i++)
+ if (c.Element<T>(first + i) > max)
+ max = c.Element<T>(first + i);
+
+ CheckValidate(true, c, type, max, first, count);
+ CheckValidate(true, c, type, T(-1), first, count);
+ if (T(max + 1)) CheckValidate(true, c, type, T(max + 1), first, count);
+ if (max > 0) {
+ CheckValidate(false, c, type, max - 1, first, count);
+ CheckValidate(false, c, type, 0, first, count);
+ }
+}
+
+void CheckValidateAllTypes(mozilla::WebGLElementArrayCache& c, size_t firstByte,
+ size_t countBytes)
+{
+ CheckValidateOneTypeVariousBounds<uint8_t>(c, firstByte, countBytes);
+ CheckValidateOneTypeVariousBounds<uint16_t>(c, firstByte, countBytes);
+ CheckValidateOneTypeVariousBounds<uint32_t>(c, firstByte, countBytes);
+}
+
+template<typename T>
+void
+CheckSanity()
+{
+ const size_t numElems = 64; // should be significantly larger than tree leaf size to
+ // ensure we exercise some nontrivial tree-walking
+ T data[numElems] = {1,0,3,1,2,6,5,4}; // intentionally specify only 8 elements for now
+ size_t numBytes = numElems * sizeof(T);
+ ASSERT_TRUE(numBytes == sizeof(data));
+
+ GLenum type = GLType<T>();
+
+ mozilla::WebGLElementArrayCache c;
+ c.BufferData(data, numBytes);
+ CheckValidate(true, c, type, 6, 0, 8);
+ CheckValidate(false, c, type, 5, 0, 8);
+ CheckValidate(true, c, type, 3, 0, 3);
+ CheckValidate(false, c, type, 2, 0, 3);
+ CheckValidate(true, c, type, 6, 2, 4);
+ CheckValidate(false, c, type, 5, 2, 4);
+
+ c.BufferSubData(5*sizeof(T), data, sizeof(T));
+ CheckValidate(true, c, type, 5, 0, 8);
+ CheckValidate(false, c, type, 4, 0, 8);
+
+ // now test a somewhat larger size to ensure we exceed the size of a tree leaf
+ for(size_t i = 0; i < numElems; i++)
+ data[i] = numElems - i;
+ c.BufferData(data, numBytes);
+ CheckValidate(true, c, type, numElems, 0, numElems);
+ CheckValidate(false, c, type, numElems - 1, 0, numElems);
+
+ ASSERT_TRUE(numElems > 10);
+ CheckValidate(true, c, type, numElems - 10, 10, numElems - 10);
+ CheckValidate(false, c, type, numElems - 11, 10, numElems - 10);
+}
+
+template<typename T>
+void
+CheckUintOverflow()
+{
+ // This test is only for integer types smaller than uint32_t
+ static_assert(sizeof(T) < sizeof(uint32_t), "This test is only for integer types \
+ smaller than uint32_t");
+
+ const size_t numElems = 64; // should be significantly larger than tree leaf size to
+ // ensure we exercise some nontrivial tree-walking
+ T data[numElems];
+ size_t numBytes = numElems * sizeof(T);
+ ASSERT_TRUE(numBytes == sizeof(data));
+
+ GLenum type = GLType<T>();
+
+ mozilla::WebGLElementArrayCache c;
+
+ for(size_t i = 0; i < numElems; i++)
+ data[i] = numElems - i;
+ c.BufferData(data, numBytes);
+
+ // bug 825205
+ uint32_t bigValWrappingToZero = uint32_t(T(-1)) + 1;
+ CheckValidate(true, c, type, bigValWrappingToZero, 0, numElems);
+ CheckValidate(true, c, type, bigValWrappingToZero - 1, 0, numElems);
+ CheckValidate(false, c, type, 0, 0, numElems);
+}
+
+TEST(WebGLElementArrayCache, Test)
+{
+ srand(0); // do not want a random seed here.
+
+ CheckSanity<uint8_t>();
+ CheckSanity<uint16_t>();
+ CheckSanity<uint32_t>();
+
+ CheckUintOverflow<uint8_t>();
+ CheckUintOverflow<uint16_t>();
+
+ nsTArray<uint8_t> v, vsub;
+ mozilla::WebGLElementArrayCache b;
+
+ for (int maxBufferSize = 1; maxBufferSize <= 4096; maxBufferSize *= 2) {
+ // See bug 800612. We originally had | repeat = min(maxBufferSize, 20) |
+ // and a real bug was only caught on Windows and not on Linux due to rand()
+ // producing different values. In that case, the minimum value by which to replace
+ // this 20 to reproduce the bug on Linux, was 25. Replacing it with 64 should give
+ // us some comfort margin.
+ int repeat = std::min(maxBufferSize, 64);
+ for (int i = 0; i < repeat; i++) {
+ size_t size = RandomInteger<size_t>(0, maxBufferSize);
+ MakeRandomVector(v, size);
+ b.BufferData(v.Elements(), size);
+ CheckValidateAllTypes(b, 0, size);
+
+ for (int j = 0; j < 16; j++) {
+ for (int bufferSubDataCalls = 1; bufferSubDataCalls <= 8; bufferSubDataCalls *= 2) {
+ for (int validateCalls = 1; validateCalls <= 8; validateCalls *= 2) {
+
+ size_t offset = 0, subsize = 0;
+
+ for (int k = 0; k < bufferSubDataCalls; k++) {
+ offset = RandomInteger<size_t>(0, size);
+ subsize = RandomInteger<size_t>(0, size - offset);
+ MakeRandomVector(vsub, subsize);
+ b.BufferSubData(offset, vsub.Elements(), subsize);
+ }
+
+ for (int k = 0; k < validateCalls; k++) {
+ offset = RandomInteger<size_t>(0, size);
+ subsize = RandomInteger<size_t>(0, size - offset);
+ CheckValidateAllTypes(b, offset, subsize);
+ }
+ } // validateCalls
+ } // bufferSubDataCalls
+ } // j
+ } // i
+ } // maxBufferSize
+}
+
diff --git a/dom/canvas/gtest/moz.build b/dom/canvas/gtest/moz.build
new file mode 100644
index 000000000..a87b6fe6b
--- /dev/null
+++ b/dom/canvas/gtest/moz.build
@@ -0,0 +1,17 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ 'TestImageBitmapColorUtils.cpp',
+ 'TestWebGLElementArrayCache.cpp',
+]
+
+LOCAL_INCLUDES += [
+ '/dom/canvas',
+ '/media/libyuv/include'
+]
+
+FINAL_LIBRARY = 'xul-gtest'