content: /*
   * Copyright (C) 2019 Adaptech s.r.o., Robert Pösel
   * Copyright (C) 2010 Google Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
   * use this file except in compliance with the License. You may obtain a copy of
   * the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations under
   * the License.
   */
  
  package com.googlecode.leptonica.android;
  
  /**
   * Image adaptive mapping methods.
   *
   * @author alanv@google.com (Alan Viverette)
   */
  @SuppressWarnings("WeakerAccess")
  public class AdaptiveMap {
  	static {
  		System.loadLibrary("jpeg");
  		System.loadLibrary("pngx");
  		System.loadLibrary("leptonica");
  	}
  
  	// Background normalization constants
  
  	/**
  	 * Image reduction value; possible values are 1, 2, 4, 8
  	 */
  	private final static int NORM_REDUCTION = 16;
  
  	/**
  	 * Desired tile size; actual size may vary
  	 */
  	private final static int NORM_SIZE = 3;
  
  	/**
  	 * Background brightness value; values over 200 may result in clipping
  	 */
  	private final static int NORM_BG_VALUE = 200;
  
  	// Adaptive contrast normalization constants
  
  	public final static int DEFAULT_TILE_WIDTH = 10;
  
  	public final static int DEFAULT_TILE_HEIGHT = 15;
  
  	public final static int DEFAULT_MIN_COUNT = 40;
  
  	public final static int DEFAULT_X_SMOOTH_SIZE = 2;
  
  	public final static int DEFAULT_Y_SMOOTH_SIZE = 1;
  
  	/**
  	 * Normalizes an image's background using default parameters.
  	 *
  	 * @param pixs A source pix image.
  	 * @return the source pix image with a normalized background
  	 */
  	public static Pix backgroundNormMorph(Pix pixs) {
  		return backgroundNormMorph(pixs, NORM_REDUCTION, NORM_SIZE, NORM_BG_VALUE);
  	}
  
  	/**
  	 * Normalizes an image's background to a specified value.
  	 * <p>
  	 * Notes:
  	 * <ol>
  	 * <li>This is a top-level interface for normalizing the image intensity by
  	 * mapping the image so that the background is near the input value 'bgval'.
  	 * <li>The input image is either grayscale or rgb.
  	 * <li>For each component in the input image, the background value is
  	 * estimated using a grayscale closing; hence the 'Morph' in the function
  	 * name.
  	 * <li>An optional binary mask can be specified, with the foreground pixels
  	 * typically over image regions. The resulting background map values will be
  	 * determined by surrounding pixels that are not under the mask foreground.
  	 * The origin (0,0) of this mask is assumed to be aligned with the origin of
  	 * the input image. This binary mask must not fully cover pixs, because then
  	 * there will be no pixels in the input image available to compute the
  	 * background.
  	 * <li>The map is computed at reduced size (given by 'reduction') from the
  	 * input pixs and optional pixim. At this scale, pixs is closed to remove
  	 * the background, using a square Sel of odd dimension. The product of
  	 * reduction * size should be large enough to remove most of the text
  	 * foreground.
  	 * <li>No convolutional smoothing needs to be done on the map before
  	 * inverting it.
  	 * <li>A 'bgval' target background value for the normalized image. This
  	 * should be at least 128. If set too close to 255, some clipping will occur
  	 * in the result.
  	 * </ol>
  	 *
  	 * @param pixs          A source pix image.
  	 * @param normReduction Reduction at which morphological closings are done.
  	 * @param normSize      Size of square Sel for the closing.
  	 * @param normBgValue   Target background value.
  	 * @return the source pix image with a normalized background
  	 */
  	public static Pix backgroundNormMorph(
  			Pix pixs, int normReduction, int normSize, int normBgValue) {
  		if (pixs == null)
  			throw new IllegalArgumentException("Source pix must be non-null");
  
  		long nativePix = nativeBackgroundNormMorph(
  				pixs.getNativePix(), normReduction, normSize, normBgValue);
  
  		if (nativePix == 0)
  			throw new RuntimeException("Failed to normalize image background");
  
  		return new Pix(nativePix);
  	}
  
  	/**
  	 * Adaptively attempts to expand the contrast to the full dynamic range in
  	 * each tile using default parameters.
  	 *
  	 * @param pixs A source pix image
  	 * @return a new image with expanded contrast range
  	 * @see #pixContrastNorm(Pix, int, int, int, int, int)
  	 */
  	public static Pix pixContrastNorm(Pix pixs) {
  		return pixContrastNorm(pixs, DEFAULT_TILE_WIDTH, DEFAULT_TILE_HEIGHT,
  				DEFAULT_MIN_COUNT, DEFAULT_X_SMOOTH_SIZE, DEFAULT_Y_SMOOTH_SIZE);
  	}
  
  	/**
  	 * Adaptively attempts to expand the contrast to the full dynamic range in
  	 * each tile.
  	 * <p>
  	 * Notes:
  	 * <ol>
  	 * <li>If the contrast in a tile is smaller than minDiff, it uses the min
  	 * and max pixel values from neighboring tiles.  It also can use
  	 * convolution to smooth the min and max values from neighboring tiles.
  	 * After all that processing, it is possible that the actual pixel values
  	 * in the tile are outside the computed [min ... max] range for local
  	 * contrast normalization. Such pixels are taken to be at either 0 (if
  	 * below the min) or 255 (if above the max).
  	 * <li>sizeX and sizeY give the tile size; they are typically at least 20.
  	 * <li>minDiff is used to eliminate results for tiles where it is likely
  	 * that either fg or bg is missing.  A value around 50 or more is
  	 * reasonable.
  	 * <li>The full width and height of the convolution kernel are (2 * smoothx
  	 * + 1) and (2 * smoothy + 1).  Some smoothing is typically useful, and we
  	 * limit the smoothing half-widths to the range from 0 to 8. Use 0 for no
  	 * smoothing.
  	 * <li>A linear TRC (gamma = 1.0) is applied to increase the contrast in
  	 * each tile. The result can subsequently be globally corrected, by
  	 * applying pixGammaTRC() with arbitrary values of gamma and the 0 and 255
  	 * points of the mapping.
  	 * </ol>
  	 *
  	 * @param pixs    A source pix image
  	 * @param sizeX   Tile width
  	 * @param sizeY   Tile height
  	 * @param minDiff Minimum difference to accept as valid
  	 * @param smoothX Half-width of convolution kernel applied to min and max
  	 *                arrays
  	 * @param smoothY Half-height of convolution kernel applied to min and max
  	 *                arrays
  	 * @return a new image with expanded contrast range
  	 */
  	public static Pix pixContrastNorm(
  			Pix pixs, int sizeX, int sizeY, int minDiff, int smoothX, int smoothY) {
  		if (pixs == null)
  			throw new IllegalArgumentException("Source pix must be non-null");
  
  		long nativePix = nativePixContrastNorm(
  				pixs.getNativePix(), sizeX, sizeY, minDiff, smoothX, smoothY);
  
  		if (nativePix == 0)
  			throw new RuntimeException("Failed to normalize image contrast");
  
  		return new Pix(nativePix);
  	}
  
  	// ***************
  	// * NATIVE CODE *
  	// ***************
  
  	private static native long nativeBackgroundNormMorph(
  			long nativePix, int reduction, int size, int bgval);
  
  	private static native long nativePixContrastNorm(
  			long nativePix, int sizeX, int sizeY, int minDiff, int smoothX, int smoothY);
  }
  