blob: 98eec965f2cd17e6b0613782ec9640f5c78dee9b [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "skcms.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define expect(cond) \
if (!(cond)) (fprintf(stderr, "expect(" #cond ") failed at %s:%d\n",__FILE__,__LINE__),exit(1))
static void test_ICCProfile() {
// Nothing works yet. :)
skcms_ICCProfile profile;
const uint8_t buf[] = { 0x42 };
expect(!skcms_ICCProfile_parse(&profile, buf, sizeof(buf)));
skcms_Matrix3x3 toXYZD50;
expect(!skcms_ICCProfile_toXYZD50(&profile, &toXYZD50));
skcms_TransferFunction transferFunction;
expect(!skcms_ICCProfile_getTransferFunction(&profile, &transferFunction));
}
static void test_Transform() {
// Nothing works yet. :)
skcms_ICCProfile src, dst;
uint8_t buf[16];
for (skcms_PixelFormat fmt = skcms_PixelFormat_RGB_565;
fmt <= skcms_PixelFormat_BGRA_ffff; fmt++) {
expect(!skcms_Transform(buf,fmt,&dst,
buf,fmt,&src, 1));
}
}
static void test_FormatConversions() {
// If we use a single skcms_ICCProfile, we should be able to use skcms_Transform()
// to do skcms_PixelFormat conversions.
skcms_ICCProfile profile;
// We can interpret src as 85 RGB_888 pixels or 64 RGB_8888 pixels.
uint8_t src[256],
dst[85*4];
for (int i = 0; i < 256; i++) {
src[i] = (uint8_t)i;
}
// This should basically be a really complicated memcpy().
expect(skcms_Transform(dst, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_RGBA_8888, &profile, 64));
for (int i = 0; i < 256; i++) {
expect(dst[i] == i);
}
// We can do RGBA -> BGRA swaps two ways:
expect(skcms_Transform(dst, skcms_PixelFormat_BGRA_8888, &profile,
src, skcms_PixelFormat_RGBA_8888, &profile, 64));
for (int i = 0; i < 64; i++) {
expect(dst[4*i+0] == 4*i+2);
expect(dst[4*i+1] == 4*i+1);
expect(dst[4*i+2] == 4*i+0);
expect(dst[4*i+3] == 4*i+3);
}
expect(skcms_Transform(dst, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_BGRA_8888, &profile, 64));
for (int i = 0; i < 64; i++) {
expect(dst[4*i+0] == 4*i+2);
expect(dst[4*i+1] == 4*i+1);
expect(dst[4*i+2] == 4*i+0);
expect(dst[4*i+3] == 4*i+3);
}
// Let's convert RGB_888 to RGBA_8888...
expect(skcms_Transform(dst, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_RGB_888 , &profile, 85));
for (int i = 0; i < 85; i++) {
expect(dst[4*i+0] == 3*i+0);
expect(dst[4*i+1] == 3*i+1);
expect(dst[4*i+2] == 3*i+2);
expect(dst[4*i+3] == 255);
}
// ... and now all the variants of R-B swaps.
expect(skcms_Transform(dst, skcms_PixelFormat_BGRA_8888, &profile,
src, skcms_PixelFormat_BGR_888 , &profile, 85));
for (int i = 0; i < 85; i++) {
expect(dst[4*i+0] == 3*i+0);
expect(dst[4*i+1] == 3*i+1);
expect(dst[4*i+2] == 3*i+2);
expect(dst[4*i+3] == 255);
}
expect(skcms_Transform(dst, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_BGR_888 , &profile, 85));
for (int i = 0; i < 85; i++) {
expect(dst[4*i+0] == 3*i+2);
expect(dst[4*i+1] == 3*i+1);
expect(dst[4*i+2] == 3*i+0);
expect(dst[4*i+3] == 255);
}
expect(skcms_Transform(dst, skcms_PixelFormat_BGRA_8888, &profile,
src, skcms_PixelFormat_RGB_888 , &profile, 85));
for (int i = 0; i < 85; i++) {
expect(dst[4*i+0] == 3*i+2);
expect(dst[4*i+1] == 3*i+1);
expect(dst[4*i+2] == 3*i+0);
expect(dst[4*i+3] == 255);
}
// Let's test in-place transforms.
// RGBA_8888 and RGB_888 aren't the same size, so we shouldn't allow this call.
expect(!skcms_Transform(src, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_RGB_888, &profile, 85));
// These two should work fine.
expect(skcms_Transform(src, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_BGRA_8888, &profile, 64));
for (int i = 0; i < 64; i++) {
expect(src[4*i+0] == 4*i+2);
expect(src[4*i+1] == 4*i+1);
expect(src[4*i+2] == 4*i+0);
expect(src[4*i+3] == 4*i+3);
}
expect(skcms_Transform(src, skcms_PixelFormat_BGRA_8888, &profile,
src, skcms_PixelFormat_RGBA_8888, &profile, 64));
for (int i = 0; i < 64; i++) {
expect(src[4*i+0] == 4*i+0);
expect(src[4*i+1] == 4*i+1);
expect(src[4*i+2] == 4*i+2);
expect(src[4*i+3] == 4*i+3);
}
}
static void test_FormatConversions_565() {
// If we use a single skcms_ICCProfile, we should be able to use skcms_Transform()
// to do skcms_PixelFormat conversions.
skcms_ICCProfile profile;
// This should hit all the unique values of each lane of 565.
uint16_t src[64];
for (int i = 0; i < 64; i++) {
src[i] = (uint16_t)( (i/2) << 0 )
| (uint16_t)( (i/1) << 5 )
| (uint16_t)( (i/2) << 11 );
}
expect(src[ 0] == 0x0000);
expect(src[63] == 0xffff);
uint32_t dst[64];
expect(skcms_Transform(dst, skcms_PixelFormat_RGBA_8888, &profile,
src, skcms_PixelFormat_RGB_565, &profile, 64));
// We'll just spot check these results a bit.
for (int i = 0; i < 64; i++) {
expect((dst[i] >> 24) == 255); // All opaque.
}
expect(dst[ 0] == 0xff000000); // 0 -> 0
expect(dst[20] == 0xff525152); // (10/31) ≈ (82/255) and (20/63) ≈ (81/255)
expect(dst[62] == 0xfffffbff); // (31/31) == (255/255) and (62/63) ≈ (251/255)
expect(dst[63] == 0xffffffff); // 1 -> 1
}
int main(void) {
test_ICCProfile();
test_Transform();
test_FormatConversions();
test_FormatConversions_565();
return 0;
}