<commit_before>//
// LIFReader.java
//

/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ <NAME>, <NAME>, <NAME>,
<NAME> and <NAME>.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 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 Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package loci.formats.in;

import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import loci.formats.*;

/**
 * LIFReader is the file format reader for Leica LIF files.
 *
 * @author <NAME> linkert at wisc.edu
 */
public class LIFReader extends FormatReader {

  // -- Fields --

  /** Current file. */
  protected RandomAccessStream in;

  /** Flag indicating whether current file is little endian. */
  protected boolean littleEndian;

  /** Number of image planes in the file. */
  protected int numImages = 0;

  /** Offsets to memory blocks, paired with their corresponding description. */
  protected Vector offsets;

  /**
   * Dimension information for each image.
   * The first index specifies the image number, and the second specifies
   * the dimension from the following list:
   * 0) width
   * 1) height
   * 2) Z
   * 3) T
   * 4) channels (1 or 3)
   * 5) bits per pixel
   * 6) extra dimensions
   */
  protected int[][] dims;

  /** Number of valid bits per pixel */
  private int[][] validBits;

  private int width;
  private int height;
  private int c;
  private int bpp;
  private Vector xcal;
  private Vector ycal;
  private Vector zcal;
  private Vector seriesNames;

  private Vector channelMins;
  private Vector channelMaxs;

  // -- Constructor --

  /** Constructs a new Leica LIF reader. */
  public LIFReader() { super("Leica Image File Format", "lif"); }

  // -- FormatReader API methods --

  /** Checks if the given block is a valid header for a LIF file. */
  public boolean isThisType(byte[] block) {
    return block[0] == 0x70;
  }

  /** Determines the number of images in the given LIF file. */
  public int getImageCount(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    numImages = dims[series][2] * dims[series][3];
    return numImages * (isRGB(id) ? 1 : dims[series][4]);
  }

  /** Checks if the images in the file are RGB. */
  public boolean isRGB(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return dims[series][4] > 1 && dims[series][4] < 4;
  }

  /** Return true if the data is in little-endian format. */
  public boolean isLittleEndian(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return littleEndian;
  }

  /** Returns whether or not the channels are interleaved. */
  public boolean isInterleaved(String id) throws FormatException, IOException {
    return true;
  }

  /** Return the number of series in this file. */
  public int getSeriesCount(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return dims.length;
  }

  /* @see loci.formats.IFormatReader#getChannelGlobalMinimum(String, int) */
  public Double getChannelGlobalMinimum(String id, int theC)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    return new Double(((Integer) channelMins.get(series)).intValue());
  }

  /* @see loci.formats.IFormatReader#getChannelGlobalMaximum(String, int) */
  public Double getChannelGlobalMaximum(String id, int theC)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    return new Double(((Integer) channelMaxs.get(series)).intValue());
  }

  /* @see loci.formats.IFormatReader#isMinMaxPopulated(String) */
  public boolean isMinMaxPopulated(String id)
    throws FormatException, IOException
  {
    return true;
  }

  /** Obtains the specified image from the given LIF file as a byte array. */
  public byte[] openBytes(String id, int no)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    bpp = dims[series][5];
    while (bpp % 8 != 0) bpp++;
    byte[] buf = new byte[sizeX[series] * sizeY[series] *
      (bpp / 8) * sizeC[series]];
    return openBytes(id, no, buf);
  }

  public byte[] openBytes(String id, int no, byte[] buf)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    if (no < 0 || no >= getImageCount(id)) {
      throw new FormatException("Invalid image number: " + no);
    }
    bpp = dims[series][5];
    while (bpp % 8 != 0) bpp++;
    int bytes = bpp / 8;
    if (buf.length < sizeX[series] * sizeY[series] * bytes * sizeC[series]) {
      throw new FormatException("Buffer too small.");
    }

    int offset = ((Long) offsets.get(series)).intValue();
    in.seek(offset +
      sizeX[series] * sizeY[series] * bytes * no * sizeC[series]);
    in.read(buf);
    updateMinMax(buf, no);
    return buf;
  }

  /** Obtains the specified image from the given LIF file. */
  public BufferedImage openImage(String id, int no)
    throws FormatException, IOException
  {<commit_msg>Calculate plane size based on the RGB channel count, not sizeC.<commit_after>//
// LIFReader.java
//

/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ <NAME>, <NAME>, <NAME>,
<NAME> and <NAME>.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 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 Library General Public License for more details.

You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package loci.formats.in;

import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import loci.formats.*;

/**
 * LIFReader is the file format reader for Leica LIF files.
 *
 * @author <NAME> linkert at wisc.edu
 */
public class LIFReader extends FormatReader {

  // -- Fields --

  /** Current file. */
  protected RandomAccessStream in;

  /** Flag indicating whether current file is little endian. */
  protected boolean littleEndian;

  /** Number of image planes in the file. */
  protected int numImages = 0;

  /** Offsets to memory blocks, paired with their corresponding description. */
  protected Vector offsets;

  /**
   * Dimension information for each image.
   * The first index specifies the image number, and the second specifies
   * the dimension from the following list:
   * 0) width
   * 1) height
   * 2) Z
   * 3) T
   * 4) channels (1 or 3)
   * 5) bits per pixel
   * 6) extra dimensions
   */
  protected int[][] dims;

  /** Number of valid bits per pixel */
  private int[][] validBits;

  private int width;
  private int height;
  private int c;
  private int bpp;
  private Vector xcal;
  private Vector ycal;
  private Vector zcal;
  private Vector seriesNames;

  private Vector channelMins;
  private Vector channelMaxs;

  // -- Constructor --

  /** Constructs a new Leica LIF reader. */
  public LIFReader() { super("Leica Image File Format", "lif"); }

  // -- FormatReader API methods --

  /** Checks if the given block is a valid header for a LIF file. */
  public boolean isThisType(byte[] block) {
    return block[0] == 0x70;
  }

  /** Determines the number of images in the given LIF file. */
  public int getImageCount(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    numImages = dims[series][2] * dims[series][3];
    return numImages * (isRGB(id) ? 1 : dims[series][4]);
  }

  /** Checks if the images in the file are RGB. */
  public boolean isRGB(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return dims[series][4] > 1 && dims[series][4] < 4;
  }

  /** Return true if the data is in little-endian format. */
  public boolean isLittleEndian(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return littleEndian;
  }

  /** Returns whether or not the channels are interleaved. */
  public boolean isInterleaved(String id) throws FormatException, IOException {
    return true;
  }

  /** Return the number of series in this file. */
  public int getSeriesCount(String id) throws FormatException, IOException {
    if (!id.equals(currentId)) initFile(id);
    return dims.length;
  }

  /* @see loci.formats.IFormatReader#getChannelGlobalMinimum(String, int) */
  public Double getChannelGlobalMinimum(String id, int theC)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    return new Double(((Integer) channelMins.get(series)).intValue());
  }

  /* @see loci.formats.IFormatReader#getChannelGlobalMaximum(String, int) */
  public Double getChannelGlobalMaximum(String id, int theC)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    return new Double(((Integer) channelMaxs.get(series)).intValue());
  }

  /* @see loci.formats.IFormatReader#isMinMaxPopulated(String) */
  public boolean isMinMaxPopulated(String id)
    throws FormatException, IOException
  {
    return true;
  }

  /** Obtains the specified image from the given LIF file as a byte array. */
  public byte[] openBytes(String id, int no)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    bpp = dims[series][5];
    while (bpp % 8 != 0) bpp++;
    byte[] buf = new byte[sizeX[series] * sizeY[series] *
      (bpp / 8) * getRGBChannelCount(id)];
    return openBytes(id, no, buf);
  }

  public byte[] openBytes(String id, int no, byte[] buf)
    throws FormatException, IOException
  {
    if (!id.equals(currentId)) initFile(id);
    if (no < 0 || no >= getImageCount(id)) {
      throw new FormatException("Invalid image number: " + no);
    }
    bpp = dims[series][5];
    while (bpp % 8 != 0) bpp++;
    int bytes = bpp / 8;
    if (buf.length < sizeX[series] * sizeY[series] * bytes * 
      getRGBChannelCount(id)) 
    {
      throw new FormatException("Buffer too small.");
    }

    int offset = ((Long) offsets.get(series)).intValue();
    in.seek(offset +
      sizeX[series] * sizeY[series] * bytes * no * getRGBChannelCount(id));
   
    in.read(buf);
    updateMinMax(buf, no);
    return buf;
  }

  /** Obtains the specified image from the given LIF file. */
  public BufferedImage openImage(String id, int no)
    throws FormatException, IOException
  {
{'fraction_non_alphanumeric': 0.1110818636483285, 'fraction_numerical': 0.008774238834781083, 'mean_word_length': 3.4663009404388716, 'pattern_counts': {'":': 0, '<': 21, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '642673', 'n_tokens_mistral': 3499, 'n_tokens_neox': 3328, 'n_words': 1232}