<commit_before>// @flow

import { ENUM, RANGE } from "constants/controlTypes";

import type { ColorRGBA } from "types";

import { cloneCanvas, fillBufferPixel, getBufferIndex, rgba } from "./util";

const BAYER_2X2 = "BAYER_2X2";
const BAYER_3X3 = "BAYER_3X3";
const BAYER_4X4 = "BAYER_4X4";
const BAYER_8X8 = "BAYER_8X8";

export type Threshold = "BAYER_2X2" | "BAYER_3X3" | "BAYER_4X4" | "BAYER_8X8";

export const optionTypes = {
  levels: {
    type: RANGE,
    range: [0, 255],
    default: 2
  },
  size: {
    type: ENUM,
    options: [
      {
        name: "Bayer 2×2",
        value: BAYER_2X2
      },
      {
        name: "Bayer 3×3",
        value: BAYER_3X3
      },
      {
        name: "Bayer 4×4",
        value: BAYER_4X4
      },
      {
        name: "Bayer 8×8",
        value: BAYER_8X8
      }
    ],
    default: BAYER_4X4
  }
};

const scaleMatrix = (mat: Array<Array<number>>, scale: number) =>
  mat.map(row => row.map(col => col * scale));

// map[x][y]
const thresholdMaps = {
  [BAYER_2X2]: {
    width: 2,
    thresholdMap: scaleMatrix([[0, 2], [3, 1]], 1 / 4)
  },
  [BAYER_3X3]: {
    width: 3,
    thresholdMap: scaleMatrix([[0, 7, 3], [6, 5, 2], [4, 1, 8]], 1 / 9)
  },
  [BAYER_4X4]: {
    width: 4,
    thresholdMap: scaleMatrix(
      [[0, 8, 2, 10], [12, 4, 14, 6], [3, 11, 1, 9], [15, 7, 13, 5]],
      1 / 16
    )
  },
  [BAYER_8X8]: {
    width: 8,
    thresholdMap: scaleMatrix(
      [
        [0, 48, 12, 60, 3, 51, 15, 63],
        [32, 16, 44, 28, 35, 19, 47, 31],
        [8, 56, 4, 52, 11, 59, 7, 55],
        [40, 24, 36, 20, 43, 27, 39, 23],
        [2, 50, 14, 62, 1, 49, 13, 61],
        [34, 18, 46, 30, 33, 17, 45, 29],
        [10, 58, 6, 54, 9, 57, 5, 53],
        [42, 26, 38, 22, 41, 25, 37, 21]
      ],
      1 / 64
    )
  }
};

const ordered = (
  input: HTMLCanvasElement,
  options: { thresholdMap: Threshold, levels: number } = {
    thresholdMap: optionTypes.size.default,
    levels: optionTypes.levels.default
  }
): HTMLCanvasElement => {
  const getColor = (
    color: ColorRGBA,
    levels: number,
    tx: number,
    ty: number,
    threshold: [number[]]
  ): ColorRGBA => {
    const thresholdValue = threshold[tx][ty];
    const step = 255 / (levels - 1);

    // $FlowFixMe
    return color.map(c => {
      const newColor = c + step * (thresholdValue - 0.5);
      const bucket = Math.round(newColor / step);
      return Math.round(bucket * step);
    });
  };

  const output = cloneCanvas(input, false);

  const inputCtx = input.getContext("2d");
  const outputCtx = output.getContext("2d");

  if (!inputCtx || !outputCtx) {<commit_msg>Fix minor mixup on ordered dithering row/col indices<commit_after>// @flow

import { ENUM, RANGE } from "constants/controlTypes";

import type { ColorRGBA } from "types";

import { cloneCanvas, fillBufferPixel, getBufferIndex, rgba } from "./util";

const BAYER_2X2 = "BAYER_2X2";
const BAYER_3X3 = "BAYER_3X3";
const BAYER_4X4 = "BAYER_4X4";
const BAYER_8X8 = "BAYER_8X8";

export type Threshold = "BAYER_2X2" | "BAYER_3X3" | "BAYER_4X4" | "BAYER_8X8";

export const optionTypes = {
  levels: {
    type: RANGE,
    range: [0, 255],
    default: 2
  },
  size: {
    type: ENUM,
    options: [
      {
        name: "Bayer 2×2",
        value: BAYER_2X2
      },
      {
        name: "Bayer 3×3",
        value: BAYER_3X3
      },
      {
        name: "Bayer 4×4",
        value: BAYER_4X4
      },
      {
        name: "Bayer 8×8",
        value: BAYER_8X8
      }
    ],
    default: BAYER_4X4
  }
};

const scaleMatrix = (mat: Array<Array<number>>, scale: number) =>
  mat.map(row => row.map(col => col * scale));

// map[y][x]
const thresholdMaps = {
  [BAYER_2X2]: {
    width: 2,
    thresholdMap: scaleMatrix([[0, 2], [3, 1]], 1 / 4)
  },
  [BAYER_3X3]: {
    width: 3,
    thresholdMap: scaleMatrix([[0, 7, 3], [6, 5, 2], [4, 1, 8]], 1 / 9)
  },
  [BAYER_4X4]: {
    width: 4,
    thresholdMap: scaleMatrix(
      [[0, 8, 2, 10], [12, 4, 14, 6], [3, 11, 1, 9], [15, 7, 13, 5]],
      1 / 16
    )
  },
  [BAYER_8X8]: {
    width: 8,
    thresholdMap: scaleMatrix(
      [
        [0, 48, 12, 60, 3, 51, 15, 63],
        [32, 16, 44, 28, 35, 19, 47, 31],
        [8, 56, 4, 52, 11, 59, 7, 55],
        [40, 24, 36, 20, 43, 27, 39, 23],
        [2, 50, 14, 62, 1, 49, 13, 61],
        [34, 18, 46, 30, 33, 17, 45, 29],
        [10, 58, 6, 54, 9, 57, 5, 53],
        [42, 26, 38, 22, 41, 25, 37, 21]
      ],
      1 / 64
    )
  }
};

const ordered = (
  input: HTMLCanvasElement,
  options: { thresholdMap: Threshold, levels: number } = {
    thresholdMap: optionTypes.size.default,
    levels: optionTypes.levels.default
  }
): HTMLCanvasElement => {
  const getColor = (
    color: ColorRGBA,
    levels: number,
    tx: number,
    ty: number,
    threshold: [number[]]
  ): ColorRGBA => {
    const thresholdValue = threshold[ty][tx];
    const step = 255 / (levels - 1);

    // $FlowFixMe
    return color.map(c => {
      const newColor = c + step * (thresholdValue - 0.5);
      const bucket = Math.round(newColor / step);
      return Math.round(bucket * step);
    });
  };

  const output = cloneCanvas(input, false);

  const inputCtx = input.getContext("2d");
  const outputCtx = output.getContext("2d");

  if (!inputCtx || !outputCtx) {
{'fraction_non_alphanumeric': 0.17010406811731316, 'fraction_numerical': 0.08703878902554399, 'mean_word_length': 2.3266205160478286, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '80031', 'n_tokens_mistral': 2447, 'n_tokens_neox': 2118, 'n_words': 549}