<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\tests;

use seekquarry\yioop\library\UnitTest;
use seekquarry\yioop\library\processors\JpgProcessor;

/**
 * Tests the reading of a picture written in the four inks a press uses.
 * The drawing library reads such a picture without complaint and drops
 * its black ink, which leaves a magazine cover pale and low in contrast,
 * so those are read here instead. This checks how such a picture says
 * which way its planes are stored and that the arithmetic that turns
 * them into light holds at its ends.
 *
 * @author Chris Pollett
 */
class JpgProcessorTest extends UnitTest
{
    /**
     * setUp does nothing, since every case here works on values it
     * makes for itself rather than on a file.
     */
    public function setUp()
    {
    }
    /**
     * tearDown does nothing, since no case here writes a file.
     */
    public function tearDown()
    {
    }
    /**
     * pictureSaysHowItsPlanesAreStoredTestCase checks the note a
     * printing program leaves in a picture, which says whether its first
     * three planes hold the first three inks or hold one of brightness
     * and two of color. Read as inks, a khaki figure came out green.
     */
    public function pictureSaysHowItsPlanesAreStoredTestCase()
    {
        $note = "\xFF\xD8\xFF\xEE\x00\x0EAdobe\x00\x64\x00\x00\x00\x00" .
            "\x02";
        $this->assertTrue(JpgProcessor::storedAsBrightnessAndColor(
            $note), "a note carrying a two says brightness and color");
        $plain = str_replace("\x02", "\x00", $note);
        $this->assertTrue(!JpgProcessor::storedAsBrightnessAndColor(
            $plain), "a note carrying a zero says the inks outright");
        $this->assertTrue(!JpgProcessor::storedAsBrightnessAndColor(
            "\xFF\xD8\xFF\xE0nothing of the kind"),
            "a picture with no such note says the inks outright");
    }
    /**
     * brightnessAndColorBecomeInksTestCase checks that the first three
     * planes of a picture stored the way a photograph is stored are
     * turned into the first three inks. An ink is the light it takes
     * away, so a plane holding full brightness and no color comes out as
     * no ink at all.
     */
    public function brightnessAndColorBecomeInksTestCase()
    {
        /* white: full brightness, no color either way */
        $planes = [[255], [128], [128], [0]];
        JpgProcessor::inksFromBrightnessAndColor($planes);
        $this->assertEqual(0, $planes[0][0],
            "white lays down none of the first ink");
        $this->assertEqual(0, $planes[1][0],
            "and none of the second");
        $this->assertEqual(0, $planes[2][0],
            "and none of the third");
        /* black: no brightness, no color either way */
        $planes = [[0], [128], [128], [0]];
        JpgProcessor::inksFromBrightnessAndColor($planes);
        $this->assertEqual(255, $planes[0][0],
            "no light at all lays down the first ink at full");
    }
    /**
     * valueIsHeldWithinWhatAPlaneCanHoldTestCase checks that the
     * arithmetic turning brightness and color into light cannot leave a
     * value outside what a plane holds, since it lands a little outside
     * at the ends of the range.
     */
    public function valueIsHeldWithinWhatAPlaneCanHoldTestCase()
    {
        $this->assertEqual(0, JpgProcessor::heldInRange(-40),
            "a value below the bottom is held at the bottom");
        $this->assertEqual(255, JpgProcessor::heldInRange(400),
            "a value above the top is held at the top");
        $this->assertEqual(128, JpgProcessor::heldInRange(127.6),
            "a value between them is rounded to the nearest");
    }
    /**
     * anOrdinaryPictureIsLeftToTheDrawingLibraryTestCase checks that a
     * picture in the three lights a screen uses is handed back by the
     * drawing library rather than read here, since only a picture in the
     * four inks needs the reading done here.
     */
    public function anOrdinaryPictureIsLeftToTheDrawingLibraryTestCase()
    {
        if (!function_exists("imagecreatetruecolor")) {
            return;
        }
        $picture = imagecreatetruecolor(8, 8);
        imagefill($picture, 0, 0,
            imagecolorallocate($picture, 200, 100, 50));
        ob_start();
        imagejpeg($picture);
        $bytes = ob_get_clean();
        $read = JpgProcessor::toImage($bytes);
        $this->assertTrue($read !== false, "an ordinary picture is read");
        $this->assertEqual(8, imagesx($read), "at the width it was made");
        $this->assertTrue(!JpgProcessor::storedAsBrightnessAndColor(
            $bytes), "and it carries no note about brightness and color");
    }
}
