All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ij_plugins.debayer2sx.LoopUtils.scala Maven / Gradle / Ivy

The newest version!
/*
 * Image/J Plugins
 * Copyright (C) 2002-2023 Jarek Sacha
 * Author's email: jpsacha at gmail [dot] com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Latest release available at https://github.com/ij-plugins/ijp-DeBayer2SX
 */

package ij_plugins.debayer2sx

import ij.process.{FloatProcessor, ImageProcessor}
import ij_plugins.debayer2sx.process.{FR, sortedRangeParams}

import java.awt.Rectangle

object LoopUtils {

  final def crop(src: FloatProcessor, roi: Rectangle): FloatProcessor = {
    import io.github.metarank.cfor.*

    val width = src.getWidth
    val pixels = src.getPixels.asInstanceOf[Array[Float]]
    val roiX = roi.x
    val roiY = roi.y
    val roiWidth = roi.width
    val roiHeight = roi.height
    val ip2 = new FloatProcessor(roiWidth, roiHeight)
    val pixels2 = ip2.getPixels.asInstanceOf[Array[Float]]
    //    for (ys <- roiY until roiY + roiHeight) {
    cfor(roiY)(_ < roiY + roiHeight, _ + 1) { ys =>
      var offset1 = (ys - roiY) * roiWidth
      var offset2 = ys * width + roiX
      //      for (xs <- 0 until roiWidth) {
      cfor(0)(_ < roiWidth, _ + 1) { _ =>
        pixels2(offset1) = pixels(offset2)
        offset1 += 1
        offset2 += 1
      }
    }
    ip2
  }

  /**
    * Clip values in the image to the range specified by `bpp`.
    *
    * {{{
    *   min = 0
    *   max = 2^bpp - 1
    * }}}
    *
    * @param ip  image to check
    * @param bpp bits per pixel
    */
  final def checkImg(ip: FloatProcessor, bpp: Int): Unit = {
    import io.github.metarank.cfor.*

    val maxVal = (math.pow(2, bpp) - 1).toFloat
    val pixels = ip.getPixels.asInstanceOf[Array[Float]]

    //    for (i <- pixels.indices) {
    cfor(0)(_ < pixels.length, _ + 1) { i =>
      val v = pixels(i)
      if (v > maxVal) {
        pixels(i) = maxVal
      } else if (v < 0) {
        pixels(i) = 0
      }
    }
  }

  @inline
  final def slice(src: FloatProcessor, srcRangeX: Range, srcRangeY: Range): FloatProcessor = {
    import io.github.metarank.cfor.*

    // bay(1:2:m,2:2:n)
    val _srcRangeX = if (srcRangeX == FR) Range(0, src.getWidth) else srcRangeX
    val _srcRangeY = if (srcRangeY == FR) Range(0, src.getHeight) else srcRangeY

    val (xStart, xEnd, xStep) = sortedRangeParams(_srcRangeX)
    val (yStart, yEnd, yStep) = sortedRangeParams(_srcRangeY)

    val srcWidth = src.getWidth
    val srcPixels = src.getPixels.asInstanceOf[Array[Float]]

    val dstWidth = _srcRangeX.length
    val dstHeight = _srcRangeY.length
    val dst = new FloatProcessor(dstWidth, dstHeight)
    val dstPixels = dst.getPixels.asInstanceOf[Array[Float]]

    cfor(yStart)(_ < yEnd, _ + yStep) { y =>
      val srcOffsetY = y * srcWidth
      val dstY = (y - _srcRangeY.start) / _srcRangeY.step
      val dstOffsetY = dstY * dstWidth
      cfor(xStart)(_ < xEnd, _ + xStep) { x =>
        val dstX = (x - _srcRangeX.start) / _srcRangeX.step
        dstPixels(dstX + dstOffsetY) = srcPixels(x + srcOffsetY)
      }
    }
    dst
  }

  /**
    * Copies elements between arrays within specified ranges
    *
    * MATLAB equivalent
    * {{{
    *    G0(:, 1:2:n) = bay(1:2:m, 1:2:n);
    * }}}
    *
    * Scala code
    * {{{
    *    copyRanges(
    *       G0, Range(0, w, 2), FR,
    *       bay, Range(0, w, 2), Range(0, h, 2)
    *    )
    * }}}
    *
    * @param dstIP     destination processor
    * @param dstRangeX destination X range
    * @param dstRangeY destination Y range
    * @param srcIP     source processor
    * @param srcRangeX source X range
    * @param srcRangeY source Y range
    */
  final def copyRanges(
                        dstIP: ImageProcessor,
                        dstRangeX: Range,
                        dstRangeY: Range,
                        srcIP: ImageProcessor,
                        srcRangeX: Range,
                        srcRangeY: Range
                      ): Unit = {
    import io.github.metarank.cfor.*

    val _dstRangeX = if (dstRangeX == FR) Range(0, dstIP.getWidth) else dstRangeX
    val _dstRangeY = if (dstRangeY == FR) Range(0, dstIP.getHeight) else dstRangeY
    val _srcRangeX = if (srcRangeX == FR) Range(0, srcIP.getWidth) else srcRangeX
    val _srcRangeY = if (srcRangeY == FR) Range(0, srcIP.getHeight) else srcRangeY

    val (dstXStart, dstXEnd, dstXStep) = sortedRangeParams(_dstRangeX)
    val (dstYStart, dstYEnd, dstYStep) = sortedRangeParams(_dstRangeY)

    cfor(dstYStart)(_ < dstYEnd, _ + dstYStep) { y =>
      val indexY = (y - _dstRangeY.start) / _dstRangeY.step
      val srcY = _srcRangeY.start + indexY * _srcRangeY.step
      val srcYOffset = srcY * srcIP.getWidth
      val dstYOffset = y * dstIP.getWidth

      cfor(dstXStart)(_ < dstXEnd, _ + dstXStep) { x =>
        val indexX = (x - _dstRangeX.start) / _dstRangeX.step
        val srcX = _srcRangeX.start + indexX * _srcRangeX.step

        val v = srcIP.getf(srcX + srcYOffset)
        dstIP.setf(x + dstYOffset, v)
      }
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy