test_texture.cpp

Back to Textures

test/pastel/gfx/

// Description: Testing for textures
// DocumentationOf: textures.h

#include "test/test_init.h"

#include <test/pastel/gfx/test_pastelgfx.h>

#include "pastel/sys/array.h"
#include "pastel/sys/view.h"
#include "pastel/sys/extender/indexextenders.h"

#include "pastel/gfx/color.h"
#include "pastel/gfx/texture.h"
#include "pastel/gfx/drawing.h"
#include "pastel/gfx/image_file.h"
#include "pastel/gfx/mipmap.h"
#include "pastel/gfx/ripmap.h"
#include "pastel/gfx/filter.h"

#include "pastel/sys/string.h"

#include "pastel/geometry/planar_projection.h"

#include <boost/bind.hpp>

#include <memory>
#include <iostream>

TEST_CASE("EwaMagnification (Texture)")
{
    integer Width = 400;
    integer Height = 400;

    Array<Color>* textureImagePtr = gfxStorage().get<Array<Color>*>("lena_image");
    ENSURE(textureImagePtr);
    Array<Color>& textureImage = *textureImagePtr;

    MipMap<Color, 2> mipMap(constArrayView(textureImage),
        ArrayExtender<2, Color>(clampExtender()));
    transform(mipMap, fitColor);

    Array<Color, 2> image(Vector2i(Width * 2, Height * 2));

    AlignedBox2 textureBox(0.4, 0.45, 0.55, 0.60);

    AlignedBox2 box(0, 0, Width, Height);

    {
        NearestImage_Texture<Color> texture(textureImage,
            ArrayExtender<2, Color>(clampExtender()));

        drawTexturedBox(
            box + Vector2(0, Height),
            texture,
            arrayView(image),
            textureBox);
    }
    {
        LinearImage_Texture<Color> texture(textureImage);

        drawTexturedBox(
            box + Vector2(Width, Height),
            texture,
            arrayView(image),
            textureBox);
    }
    {
        EwaImage_Texture<Color> texture(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            gaussianFilter(1));

        drawTexturedBox(
            box + Vector2(0, 0),
            texture,
            arrayView(image),
            textureBox);
    }
    {
        EwaImage_Texture<Color> texture(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            lanczosFilter(2));

        drawTexturedBox(
            box + Vector2(Width, 0),
            texture,
            arrayView(image),
            textureBox);
    }

    transform(arrayView(image), fitColor);

    savePcx(image, "texture_ewa_magnification.pcx");
}

TEST_CASE("EwaMagnification2 (Texture)")
{
    integer Width = 400;
    integer Height = 400;

    Array<Color, 2> textureImage(Vector2i(40, 40));

    integer CheckerWidth = 20;
    integer CheckerHeight = 20;

    for (integer y = 0;y < textureImage.height();++y)
    {
        for (integer x = 0;x < textureImage.width();++x)
        {

            const integer xMod = mod(x, 2 * CheckerWidth);
            const integer yMod = mod(y, 2 * CheckerHeight);

            if ((xMod < CheckerWidth) !=
                (yMod >= CheckerHeight))
            {
                textureImage(x, y) = Color(1);
            }
            else
            {
                textureImage(x, y) = Color(0);
            }
        }
    }

    /*
   Array<Color, 2> textureImage;

   loadPcx("texture_checker.pcx", textureImage);
   //loadPcx("lena.pcx", textureImage);
   */

    MipMap<Color, 2> mipMap(constArrayView(textureImage),
        ArrayExtender<2, Color>(clampExtender()));
    transform(mipMap, fitColor);

    Array<Color, 2> image(Vector2i(Width, Height));

    using TexturePtr = std::shared_ptr<Texture<Color>>;

    std::vector<TexturePtr> textureList;
    textureList.push_back(
        TexturePtr(new EwaImage_Texture<Color>(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            gaussianFilter(1))));
    textureList.push_back(
        TexturePtr(new EwaImage_Texture<Color>(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            gaussianFilter(2))));
    textureList.push_back(
        TexturePtr(new EwaImage_Texture<Color>(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            lanczosFilter(2))));
    textureList.push_back(
        TexturePtr(new EwaImage_Texture<Color>(mipMap,
            ArrayExtender<2, Color>(clampExtender()),
            boxFilter())));
    textureList.push_back(
        TexturePtr(new LinearImage_Texture<Color>(textureImage,
            ArrayExtender<2, Color>(clampExtender()))));
    textureList.push_back(
        TexturePtr(new NearestImage_Texture<Color>(textureImage,
            ArrayExtender<2, Color>(clampExtender()))));

    AlignedBox2 textureBox(0.4, 0.4, 0.6, 0.6);
    AlignedBox2 box(0, 0, Width, Height);

    integer textures = textureList.size();
    for (integer i = 0;i < textures;++i)
    {
        drawTexturedBox(
            box + Vector2(0, 0),

            *textureList[i],
            arrayView(image),
            textureBox);

        transform(arrayView(image), fitColor);
        savePcx(image, "texture_checker3_" + textureList[i]->name() +
            "_" + integerToString(i) + ".pcx");
    }
}

TEST_CASE("Samplers (Texture)")
{
    Array<Color, 2> image(Vector2i(750, 500));
    Array<Color, 2> textureImage;

    loadPcx("lena.pcx", textureImage);

    MipMap<Color, 2> mipMap(constArrayView(textureImage),
        ArrayExtender<2, Color>(clampExtender()));
    transform(mipMap, fitColor);

    MipImage_Texture<Color> mipmapSampler(mipMap);

    Color colorSet[] = 
    {
        Color(1, 1, 1), 
        Color(1, 0, 0), 
        Color(0, 1, 0),
        Color(0, 0, 1)
    };

    drawTexturedBox(
        AlignedBox2(0, 400, 100, 500),
        linearColorTexture<Color, 2>(
            range(colorSet)),
        arrayView(image));

    drawTexturedBox(
        AlignedBox2(150, 400, 250, 500),
        colorTexture<Color, 2>(Color(0.5, 0, 1)),
        arrayView(image));

    // Comparison of filtering techniques.

    drawTexturedBox(
        AlignedBox2(0, 250, 100, 350),
        nearestImageTexture(textureImage),
        arrayView(image));

    drawTexturedBox(
        AlignedBox2(150, 250, 250, 350),
        mipmapSampler,
        arrayView(image));

    EwaImage_Texture<Color> texture(mipMap);

    drawTexturedBox(
        AlignedBox2(450, 250, 550, 350),
        texture,
        arrayView(image));

    // Something else.

    /*
   drawTexturedBox(
       AlignedBox2(0, 0, 200, 200),
       nearestImageTexture(clampedConstView(constSubView(constArrayView(textureImage), AlignedBox2i(100, 100, 150, 150)))),
       arrayView(image));

   drawTexturedBox(
       AlignedBox2(250, 0, 450, 200),
       linearImageTexture(clampedConstView(constSubView(constArrayView(textureImage), AlignedBox2i(100, 100, 150, 150)))),
       arrayView(image));
   */

    drawTexturedBox(
        AlignedBox2(100, 100, 300, 225),
        mipmapSampler,
        arrayView(image),
        AlignedBox2(0, 0, 1, 1),
        transparentColorMixer<Color>(0.25));

    drawView(
        constSubView(constArrayView(textureImage), AlignedBox2i(200, 200, 300, 300)),
        Vector2i(300, 400),
        arrayView(image));

    savePcx(image, "textures_texturebox.pcx");

    clear(Color(0), arrayView(image));

    drawTexturedBox(
        AlignedBox2(0, 0, 500, 500),
        nearestImageTexture(textureImage, ArrayExtender<2, Color>(clampExtender())),
        arrayView(image),
        AlignedBox2(0.5, 0.5, 5.0, 5.0));

    savePcx(image, "textures_clampedtexturebox.pcx");

    drawTexturedBox(
        AlignedBox2(0, 0, 500, 500),
        nearestImageTexture(textureImage, ArrayExtender<2, Color>(repeatExtender())),
        arrayView(image),
        AlignedBox2(0.5, 0.5, 5.0, 5.0));

    savePcx(image, "textures_repeatedtexturebox.pcx");

    drawTexturedBox(
        AlignedBox2(0, 0, 500, 500),
        nearestImageTexture(textureImage, ArrayExtender<2, Color>(mirrorExtender())),
        arrayView(image),
        AlignedBox2(0.5, 0.5, 5.0, 5.0));

    savePcx(image, "textures_mirroredtexturebox.pcx");

    drawTexturedBox(
        AlignedBox2(0, 0, 500, 500),
        nearestImageTexture(textureImage),
        arrayView(image),
        AlignedBox2(0.5, 0.5, 5.0, 5.0));

    savePcx(image, "textures_borderedtexturebox.pcx");
}

namespace
{

    void drawTestQuad(
        const Tuple<Vector2, 4>& quad,
        const Tuple<Vector2, 4>& textureQuad,
        const Texture<Color>& texture,
        const std::string& testName,
        const std::string& name)
    {
        real yMax = -(real)Infinity();
        for (integer i = 0;i < 4;++i)
        {
            if (quad[i].y() > yMax)
            {
                yMax = quad[i].y();
            }
        }

        Array<Color, 2> image(Vector2i(500, ceil(yMax)));

        drawProjectiveQuad(
            quad,
            texture,
            arrayView(image),
            textureQuad);

        savePcx(image, "texture_" + testName + "_" + name + ".pcx");
    }

}

TEST_CASE("Checker (Texture)")
{
    Array<Color, 2> image(Vector2i(500, 500));
    Array<Color, 2> textureImage(Vector2i(40, 40));

    integer CheckerWidth = 20;
    integer CheckerHeight = 20;

    for (integer y = 0;y < textureImage.height();++y)
    {
        for (integer x = 0;x < textureImage.width();++x)
        {

            const integer xMod = mod(x, 2 * CheckerWidth);
            const integer yMod = mod(y, 2 * CheckerHeight);

            if ((xMod < CheckerWidth) !=
                (yMod >= CheckerHeight))
            {
                textureImage(x, y) = Color(1);
            }
            else
            {
                textureImage(x, y) = Color(0);
            }
        }
    }

    savePcx(textureImage, "texture_checker.pcx");

    MipMap<Color, 2> mipMap(constArrayView(textureImage),
        ArrayExtender<2, Color>(repeatExtender()), boxFilter());
    transform(mipMap, fitColor);

    RipMap<Color, 2> ripMap(constArrayView(textureImage));
    transform(ripMap, fitColor);

    Array<Color, 2> lenaTextureImage;
    loadPcx("lena.pcx", lenaTextureImage);

    MipMap<Color, 2> lenaMipMap(constArrayView(lenaTextureImage));
    transform(lenaMipMap, fitColor);

    RipMap<Color, 2> lenaRipMap(constArrayView(lenaTextureImage));
    transform(lenaRipMap, fitColor);

    ConstIndexExtenderPtr extender = repeatExtender();

    EwaImage_Texture<Color> textureEwaGaussian1(
        mipMap, ArrayExtender<2, Color>(extender), gaussianFilter(1));
    EwaImage_Texture<Color> textureEwaGaussian2(
        mipMap, ArrayExtender<2, Color>(extender), gaussianFilter(2));
    EwaImage_Texture<Color> textureEwaLanczos2(
        mipMap, ArrayExtender<2, Color>(extender), lanczosFilter(2));
    EwaImage_Texture<Color> textureEwaMitchell(
        mipMap, ArrayExtender<2, Color>(extender), mitchellFilter());
    EwaImage_Texture<Color> textureEwaBox(
        mipMap, ArrayExtender<2, Color>(extender), boxFilter());
    EwaImage_Texture<Color> textureEwaTriangle(
        mipMap, ArrayExtender<2, Color>(extender), triangleFilter());
    MipImage_Texture<Color> textureMip(
        mipMap, ArrayExtender<2, Color>(extender));
    RipImage_Texture<Color> textureRip(
        ripMap, ArrayExtender<2, Color>(extender));

    std::vector<std::pair<std::string, Texture<Color>*> > textureList;

    textureList.emplace_back(std::string("ewa_gaussian1"), (Texture<Color>*)&textureEwaGaussian1);
    textureList.emplace_back(std::string("ewa_gaussian2"), (Texture<Color>*)&textureEwaGaussian2);
    textureList.emplace_back(std::string("ewa_lanczos2"), (Texture<Color>*)&textureEwaLanczos2);
    textureList.emplace_back(std::string("ewa_mitchell"), (Texture<Color>*)&textureEwaMitchell);
    textureList.emplace_back(std::string("ewa_box"), (Texture<Color>*)&textureEwaBox);
    textureList.emplace_back(std::string("ewa_triangle"), (Texture<Color>*)&textureEwaTriangle);
    textureList.emplace_back(std::string("mip"), (Texture<Color>*)&textureMip);
    textureList.emplace_back(std::string("rip"), (Texture<Color>*)&textureRip);

    integer textures = textureList.size();

    {
        Tuple<Vector2, 4> quad(
            Vector2(250, 0),
            Vector2(500, 150),
            Vector2(250, 175),
            Vector2(0, 150));

        Tuple<Vector2, 4> textureQuad(
            Vector2(0, 0),
            Vector2(2, 0),
            Vector2(2, 2),
            Vector2(0, 2));

        for (integer i = 0;i < textures;++i)
        {

            drawTestQuad(quad, textureQuad, *textureList[i].second,
                "checker1", textureList[i].first);
        }
    }

    /*
   MipMap<Color, 2> distortMipMap(constArrayView(image));
   EwaImage_Texture<Color> distortTexture(distortMipMap);
   transform(distortMipMap, fitColor);

   clear(Color(0), arrayView(image));

   drawProjectiveQuad(
       Tuple<Vector2, 4>(
       Vector2(0, 0),
       Vector2(500, 0),
       Vector2(500, 500),
       Vector2(0, 500)),
       distortTexture,
       arrayView(image),
       Tuple<Vector2, 4>(
       Vector2(0.5, 0),
       Vector2(1, (real)150 / 500),
       Vector2(0.5, (real)175 / 500),
       Vector2(0, (real)150 / 500)));

   savePcx(image, "texture_checker1_distorted2x.pcx");
   */

    mipMap.swap(lenaMipMap);
    ripMap.swap(lenaRipMap);

    for (integer i = 0;i < textures;++i)
    {
        Tuple<Vector2, 4> quad(
            Vector2(250, 0),
            Vector2(500, 150),
            Vector2(250, 175),
            Vector2(0, 150));

        Tuple<Vector2, 4> textureQuad(
            Vector2(0, 0),
            Vector2(1, 0),
            Vector2(1, 1),
            Vector2(0, 1));

        drawTestQuad(quad, textureQuad, *textureList[i].second,
            "lena1", textureList[i].first);
    }

    /*
       MipMap<Color, 2> distortMipMap(constArrayView(image));
       EwaImage_Texture<Color> distortTexture(distortMipMap);
       transform(distortMipMap, fitColor);

       clear(Color(0), arrayView(image));

       drawProjectiveQuad(
           Tuple<Vector2, 4>(
           Vector2(0, 0),
           Vector2(500, 0),
           Vector2(500, 500),
           Vector2(0, 500)),
           distortTexture,
           arrayView(image),
           Tuple<Vector2, 4>(
           Vector2(0.5, 0),
           Vector2(1, (real)150 / 500),
           Vector2(0.5, (real)175 / 500),
           Vector2(0, (real)150 / 500)));

       savePcx(image, "texture_lena1_ewa_distorted2x.pcx");
   */

    mipMap.swap(lenaMipMap);
    ripMap.swap(lenaRipMap);

    {
        Tuple<Vector2, 4> quad(
            Vector2(0, 0),
            Vector2(500, 0),
            Vector2(255, 150),
            Vector2(245, 150));

        Tuple<Vector2, 4> textureQuad(
            Vector2(0, 0),
            Vector2(20, 0),
            Vector2(20, 800),
            Vector2(0, 800));

        for (integer i = 0;i < textures;++i)
        {
            drawTestQuad(quad, textureQuad, *textureList[i].second,
                "checker2", textureList[i].first);
        }
    }

    /*
   {
       clear(Color(0), arrayView(image));

       Tuple<Vector2, 4> quad(
           Vector2(0, 0),
           Vector2(500, 0),
           Vector2(300, 250),
           Vector2(200, 250));

       Tuple<Vector2, 4> textureQuad(
           Vector2(0, 0),
           Vector2(10, 0),
           Vector2(10, 100),
           Vector2(0, 100));

       clear(Color(0), arrayView(image));

       EwaImage_Texture<Color> texture(mipMap);

       drawProjectiveQuad(
           quad,
           mixTexture(
           colorTexture<Color>(Color(0)),
           transformTexture(
           mixTexture(
           linearImageTexture(repeatedConstView(constArrayView(lenaTextureImage))),
           colorTexture<Color>(Color(1)),
           linearColorTexture<real>(0, 0, 1, 1)),
           AffineTransformation<real>(identityMatrix<Real>(2, 2) * 10, Vector2())),
           texture),
           arrayView(image),
           textureQuad);

       savePcx(image, "texture_texture_mix.pcx");
   }
   */
}

TEST_CASE("Mix (Texture)")
{
    Array<Color, 2> aTexture;
    loadPcx("lena.pcx", aTexture);

    Array<Color, 2> bTexture;
    loadPcx("kodak_test_images/kodim19.pcx", bTexture);

    Array<Color, 2> image(Vector2i(750, 750), Color(0));

    MipMap<Color, 2> aMipMap(constArrayView(aTexture));
    transform(aMipMap, fitColor);

    MipMap<Color, 2> bMipMap(constArrayView(bTexture));
    transform(bMipMap, fitColor);

    integer iconSize = 250;
    integer iconSpace = iconSize;

    AlignedBox2 iconBox(0, 0, iconSize, iconSize);

    drawTexturedBox(
        iconBox + Vector2(0, 0),
        combineTexture(
        mipImageTexture(aMipMap),
        mipImageTexture(bMipMap),
        transparentColorMixer<Color>(0.5)),
        arrayView(image));

    drawTexturedBox(
        iconBox + Vector2(iconSpace, 0),
        combineTexture(
        mipImageTexture(aMipMap),
        mipImageTexture(bMipMap),
        functorColorMixer<Color>(std::minus<Color>())),
        arrayView(image));

    drawTexturedBox(
        iconBox + Vector2(iconSpace, iconSpace),
        combineTexture(
        mipImageTexture(aMipMap),
        mipImageTexture(bMipMap),
        functorColorMixer<Color>(std::plus<Color>())),
        arrayView(image));

    drawTexturedBox(
        iconBox + Vector2(0, iconSpace),
        combineTexture(
        mipImageTexture(aMipMap),
        mipImageTexture(bMipMap),
        functorColorMixer<Color>(std::multiplies<Color>())),
        arrayView(image));

    drawTexturedBox(
        iconBox + Vector2(0, iconSpace * 2),
        mipImageTexture(aMipMap),
        arrayView(image));

    drawTexturedBox(
        iconBox + Vector2(iconSpace * 2, 0),
        mipImageTexture(bMipMap),
        arrayView(image));

    savePcx(image, "texture_mix.pcx");
}