content: /*
   * Copyright (C) 2019 Adaptech s.r.o., Robert Pösel
   * Copyright (C) 2014 Robert Theis
   *
   * 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;
  
  import java.lang.annotation.Retention;
  
  import androidx.annotation.IntDef;
  
  import static java.lang.annotation.RetentionPolicy.SOURCE;
  
  /**
   * Composite image processing operations.
   */
  @SuppressWarnings("WeakerAccess")
  public class MorphApp {
  	static {
  		System.loadLibrary("jpeg");
  		System.loadLibrary("pngx");
  		System.loadLibrary("leptonica");
  	}
  
  	// Morphological tophat flags
  	@Retention(SOURCE)
  	@IntDef({L_TOPHAT_BLACK, L_TOPHAT_WHITE})
  	public @interface TophatType {
  	}
  
  	public static final int L_TOPHAT_WHITE = 0;
  	public static final int L_TOPHAT_BLACK = 1;
  
  	public static final int DEFAULT_WIDTH = 7;
  
  	public static final int DEFAULT_HEIGHT = 7;
  
  	/**
  	 * Performs a tophat transform.
  	 * <p>
  	 * Notes:
  	 * <ol>
  	 * <li> Sel is a brick with all elements being hits
  	 * <li> If hsize = vsize = 1, returns an image with all 0 data.
  	 * <li> The L_TOPHAT_WHITE flag emphasizes small bright regions, whereas
  	 * the L_TOPHAT_BLACK flag emphasizes small dark regions. The L_TOPHAT_WHITE
  	 * tophat can be accomplished by doing a L_TOPHAT_BLACK tophat on the
  	 * inverse, or v.v.
  	 * </ol>
  	 *
  	 * @param pixs  Source pix (8bpp)
  	 * @param hsize (of Sel; must be odd; origin implicitly in center)
  	 * @param vsize (ditto)
  	 * @param type  L_TOPHAT_WHITE: image - opening or L_TOPHAT_BLACK: closing - image
  	 * @return a new Pix image
  	 */
  	public static Pix pixTophat(Pix pixs, int hsize, int vsize, @TophatType int type) {
  		if (pixs == null)
  			throw new IllegalArgumentException("Source pix must be non-null");
  		if (pixs.getDepth() != 8)
  			throw new IllegalArgumentException("Source pix depth must be 8bpp");
  		if (hsize < 1 || vsize < 1)
  			throw new IllegalArgumentException("hsize or vsize < 1");
  		if (type < 0 || type > 1)
  			throw new IllegalArgumentException("Type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE");
  
  		long nativePix = nativePixTophat(pixs.getNativePix(), hsize, vsize,
  				type);
  
  		if (nativePix == 0)
  			throw new RuntimeException("Failed to perform Tophat on image");
  
  		return new Pix(nativePix);
  	}
  
  	/**
  	 * Performs a tophat-like operation emphasizing small dark regions using
  	 * default values.
  	 *
  	 * @param pixs Source pix (8bpp)
  	 * @return a new Pix image
  	 * @see #pixFastTophat(Pix, int, int, int)
  	 */
  	public static Pix pixFastTophatBlack(Pix pixs) {
  		return pixFastTophat(pixs, DEFAULT_WIDTH, DEFAULT_HEIGHT, L_TOPHAT_BLACK);
  	}
  
  	/**
  	 * Performs a tophat-like operation emphasizing small bright regions using
  	 * default values.
  	 *
  	 * @param pixs Source pix (8bpp)
  	 * @return a new Pix image
  	 * @see #pixFastTophat(Pix, int, int, int)
  	 */
  	public static Pix pixFastTophatWhite(Pix pixs) {
  		return pixFastTophat(pixs, DEFAULT_WIDTH, DEFAULT_HEIGHT, L_TOPHAT_WHITE);
  	}
  
  	/**
  	 * Performs a tophat-like operation.
  	 * <p>
  	 * Notes:
  	 * <ol>
  	 * <li> Don't be fooled. This is NOT a tophat.  It is a tophat-like
  	 * operation, where the result is similar to what you'd get if you used an
  	 * erosion instead of an opening, or a dilation instead of a closing.
  	 *
  	 * <li> Instead of opening or closing at full resolution, it does a fast
  	 * downscale/minmax operation, then a quick small smoothing at low res, a
  	 * replicative expansion of the "background" to full res, and finally a
  	 * removal of the background level from the input image.  The smoothing
  	 * step may not be important.
  	 *
  	 * <li> It does not remove noise as well as a tophat, but it is 5 to 10
  	 * times faster. If you need the preciseness of the tophat, don't use this.
  	 * <li> The L_TOPHAT_WHITE flag emphasizes small bright regions, whereas
  	 * the L_TOPHAT_BLACK flag emphasizes small dark regions.
  	 * </ol>
  	 *
  	 * @param pixs  Source pix (8bpp)
  	 * @param xsize width of max/min op, smoothing; any integer &gt;= 1
  	 * @param ysize height of max/min op, smoothing; any integer &gt;= 1
  	 * @param type  L_TOPHAT_WHITE: image - min, or L_TOPHAT_BLACK: max - image
  	 * @return a new Pix image
  	 */
  	public static Pix pixFastTophat(Pix pixs, int xsize, int ysize, @TophatType int type) {
  		if (pixs == null)
  			throw new IllegalArgumentException("Source pix must be non-null");
  		if (pixs.getDepth() != 8)
  			throw new IllegalArgumentException("Source pix depth must be 8bpp");
  		if (xsize < 1 || ysize < 1)
  			throw new IllegalArgumentException("size < 1");
  		if (type < 0 || type > 1)
  			throw new IllegalArgumentException("Type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE");
  
  		long nativePix = nativePixFastTophat(pixs.getNativePix(), xsize, ysize,
  				type);
  
  		if (nativePix == 0)
  			throw new RuntimeException("Failed to perform pixFastTophat on image");
  
  		return new Pix(nativePix);
  	}
  
  	// ***************
  	// * NATIVE CODE *
  	// ***************
  
  	private static native long nativePixTophat(long nativePix, int hsize, int vsize, int type);
  
  	private static native long nativePixFastTophat(long nativePix, int xsize, int ysize, int type);
  }
  