<?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
 *
 * This class holds the orders H.264 visits the values of a block in.
 * Theora and VP8 use the same orders.
 */
namespace seekquarry\yioop\library\av_processing;
/**
 * H264Scan holds the orders H.264 visits the values of a block in. Theora
 * and VP8 use the same orders.
 */
final class H264Scan
{
    /**
     * ZZ4 says where each of the sixteen places of a four by four block
     * sits in the picture. The format visits a block's places
     * corner to corner rather than row by row, so a decoder needs
     * this to put the values back where they belong.
     */
    public const ZZ4 = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15];
    /**
     * ZZ8 says where each of the sixty-four places of an eight by eight
     * block sits in the picture, for the same corner to corner
     * order.
     */
    public const ZZ8 = [
         0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33,
         40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50,
         43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46,
         53, 60, 61, 54, 47, 55, 62, 63,
    ];
    /**
     * DEFAULT_4X4_INTRA is the default four by four intra the format fixes.
     * @var mixed
     */
    public const DEFAULT_4X4_INTRA
        = [6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42];
    /**
     * DEFAULT_4X4_INTER is the default four by four inter the format fixes.
     * @var mixed
     */
    public const DEFAULT_4X4_INTER
        = [10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34];
    /**
     * DEFAULT_8X8_INTRA is the default eight by eight intra the format fixes.
     * @var mixed
     */
    public const DEFAULT_8X8_INTRA = [
         6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, 23, 23,
         23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27,
         29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, 33, 33, 33, 33, 33,
         36, 36, 36, 36, 38, 38, 38, 40, 40, 42,
    ];
    /**
     * DEFAULT_8X8_INTER is the default eight by eight inter the format fixes.
     * @var mixed
     */
    public const DEFAULT_8X8_INTER = [
         9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, 21, 21,
         21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, 24, 24, 24, 24,
         25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28,
         30, 30, 30, 30, 32, 32, 32, 33, 33, 35,
    ];
    /**
     * CHROMA_QP is table 8-15, 8-bit: the quantizer index -> the color
     * quantizer.
     */
    public const CHROMA_QP = [
         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
         20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 34,
         35, 35, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 39,
    ];
    /**
     * V4 is the adjustments a four by four block's values are scaled by, chosen
     * by whether the row and column are odd or even.
     */
    public const V4 = [
        [10, 16, 13], [11, 18, 14], [13, 20, 16],
        [14, 23, 18], [16, 25, 20], [18, 29, 23],
    ];
    /**
     * V8 is the fixed adjustments for an eight by eight block, Table 8-15.
     */
    public const V8 = [
        [20, 18, 32, 19, 25, 24], [22, 19, 35, 21, 28, 26], [26, 23, 42, 24, 33,
         31],
        [28, 25, 45, 26, 35, 33], [32, 28, 51, 30, 40, 38], [36, 32, 58, 34, 46,
         43],
    ];
    /**
     * eightColumnTransform works out which V8 column applies at raster position
     * (x,y) of an eight by eight block
     *
     * @param int $across how far across the block
     * @param int $down how far down the block
     * @return int what was read
     */
    public static function eightColumnTransform(int $across, int $down): int
    {
        $i = $down % 4;
        $j = $across % 4;
        if ($i === 0 && $j === 0) return 0;
        if (($down & 1) === 1 && ($across & 1) === 1) return 1;
        if ($i === 2 && $j === 2) return 2;
        if (($i === 0 && ($across & 1) === 1)
            || (($down & 1) === 1 && $j === 0)) return 3;
        if (($i === 0 && $j === 2) || ($i === 2 && $j === 0)) return 4;
        return 5;
    }
}
