{
  "version": 3,
  "sources": ["../src/index.ts", "../src/geotiff-loader.ts", "../src/lib/load-geotiff.ts", "../src/lib/utils/tiff-utils.ts", "../src/lib/tiff-pixel-source.ts", "../src/lib/ome/ome-indexers.ts", "../src/lib/ome/utils.ts", "../src/lib/ome/ome-utils.ts", "../src/lib/ome/omexml.ts", "../src/lib/ome/load-ome-tiff.ts"],
  "sourcesContent": ["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nexport {GeoTIFFLoader} from './geotiff-loader';\n\nexport {loadGeoTiff} from './lib/load-geotiff';\nexport {TiffPixelSource} from './lib/tiff-pixel-source';\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {TypedArray, LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';\nimport {fromArrayBuffer} from 'geotiff';\n\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';\n\n// Return type definition for GeoTIFF loader\ntype GeoTIFFData = {\n  crs?: string;\n  bounds: number[];\n  metadata: Record<string, unknown>;\n\n  width: number;\n  height: number;\n  data: TypedArray;\n};\n\n/** GeoTIFF load options */\nexport type GeoTIFFLoaderOptions = LoaderOptions & {\n  geotiff?: {\n    enableAlpha: boolean;\n  };\n};\n\n/** GeoTIFF loader */\nexport const GeoTIFFLoader = {\n  dataType: null as unknown as GeoTIFFData,\n  batchType: null as never,\n\n  id: 'geotiff',\n  name: 'GeoTIFF',\n  module: 'geotiff',\n  version: VERSION,\n  options: {\n    geotiff: {\n      enableAlpha: true\n    }\n  },\n  mimeTypes: ['image/tiff', 'image/geotiff'],\n  extensions: ['geotiff', 'tiff', 'geotif', 'tif'],\n  parse: parseGeoTIFF\n} as const satisfies LoaderWithParser<GeoTIFFData, never, GeoTIFFLoaderOptions>;\n\nexport function isTiff(arrayBuffer: ArrayBuffer): boolean {\n  const dataView = new DataView(arrayBuffer);\n  // Byte offset\n  const endianness = dataView.getUint16(0);\n  let littleEndian: boolean;\n  switch (endianness) {\n    case 0x4949:\n      littleEndian = true;\n      break;\n    case 0x4d4d:\n      littleEndian = false;\n      break;\n    default:\n      return false;\n    // throw new Error(`invalid byte order: 0x${endianness.toString(16)}`);\n  }\n\n  // Magic number\n  if (dataView.getUint16(2, littleEndian) !== 42) {\n    return false;\n  }\n\n  return true;\n}\n\n/**\n * Loads a GeoTIFF file containing a RGB image.\n */\nasync function parseGeoTIFF(\n  data: ArrayBuffer,\n  options?: GeoTIFFLoaderOptions\n): Promise<GeoTIFFData> {\n  // Load using Geotiff.js\n  const tiff = await fromArrayBuffer(data);\n\n  // Assumes we only have one image inside TIFF\n  const image = await tiff.getImage();\n\n  // Read image and size\n  // TODO: Add support for worker pools here.\n  // TODO: Add support for more image formats.\n  const rgbData = await image.readRGB({\n    enableAlpha: options?.geotiff?.enableAlpha\n  });\n\n  const width = image.getWidth();\n  const height = image.getHeight();\n\n  // Create a new ImageData object\n  const imageData = new Uint8ClampedArray(rgbData as unknown as Uint8Array);\n\n  // Get geo data\n  const bounds = image.getBoundingBox();\n  const metadata = image.getGeoKeys();\n\n  // ProjectedCSTypeGeoKey is the only key we support for now, we assume it is an EPSG code\n  let crs: string | undefined;\n  if (metadata?.ProjectedCSTypeGeoKey) {\n    crs = `EPSG:${metadata.ProjectedCSTypeGeoKey}`;\n  }\n\n  // Return GeoReferenced image data\n  return {\n    crs,\n    bounds,\n    width,\n    height,\n    data: imageData,\n    metadata\n  };\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {fromUrl, fromBlob, GeoTIFF} from 'geotiff';\n\n// import {\n//   // createPoolProxy,\n//   createOffsetsProxy,\n//   checkProxies\n// } from './utils/proxies.ts.disabled';\n// import Pool from './lib/Pool';\n\nimport {loadOmeTiff, isOmeTiff} from './ome/load-ome-tiff';\nimport type {TiffPixelSource} from './tiff-pixel-source';\n\n/** Options for initializing a tiff pixel source. */\ninterface GeoTIFFOptions {\n  /** Headers passed to each underlying request. */\n  headers?: Record<string, unknown>;\n  /** Performance enhancment to index the remote tiff source using pre-computed byte-offsets. Generated via https://github.com/ilan-gold/generate-tiff-offsets */\n  offsets?: number[];\n  /** Indicates whether a multi-threaded pool of image decoders should be used to decode tiles. */\n  pool?: boolean;\n}\n\ninterface GeoTIFFData {\n  data: TiffPixelSource<string[]>[];\n  metadata: Record<string, unknown>;\n}\n\n/**\n * Opens an OME-TIFF via URL and returns data source and associated metadata for first image.\n *\n * @param source url string, File/Blob object, or GeoTIFF object\n * @param opts options for initializing a tiff pixel source.\n *  - `opts.headers` are passed to each underlying fetch request.\n *  - `opts.offsets` are a performance enhancment to index the remote tiff source using pre-computed byte-offsets.\n *  - `opts.pool` indicates whether a multi-threaded pool of image decoders should be used to decode tiles (default = true).\n * @return data source and associated OME-Zarr metadata.\n */\nexport async function loadGeoTiff(\n  source: string | Blob | GeoTIFF,\n  opts: GeoTIFFOptions = {}\n): Promise<GeoTIFFData> {\n  const {headers, offsets} = opts;\n\n  // Create tiff source\n  let tiff: GeoTIFF;\n  if (source instanceof GeoTIFF) {\n    tiff = source;\n  } else if (typeof source === 'string') {\n    tiff = await fromUrl(source, headers);\n  } else {\n    tiff = await fromBlob(source);\n  }\n\n  // if (pool) {\n  /*\n   * Creates a worker pool to decode tiff tiles. Wraps tiff\n   * in a Proxy that injects 'pool' into `tiff.readRasters`.\n   */\n  // tiff = createPoolProxy(tiff, new Pool());\n  // }\n\n  if (offsets) {\n    /*\n     * Performance enhancement. If offsets are provided, we\n     * create a proxy that intercepts calls to `tiff.getImage`\n     * and injects the pre-computed offsets.\n     */\n    // tiff = createOffsetsProxy(tiff, offsets);\n  }\n\n  /*\n   * Inspect tiff source for our performance enhancing proxies.\n   * Prints warnings to console if `offsets` or `pool` are missing.\n   */\n  // checkProxies(tiff);\n\n  const firstImage = await tiff.getImage(0);\n\n  if (isOmeTiff(firstImage)) {\n    return loadOmeTiff(tiff, firstImage);\n  }\n\n  throw new Error('GeoTIFF not recognized.');\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {PixelSource} from '../../types';\n\nexport function ensureArray<T>(x: T | T[]) {\n  return Array.isArray(x) ? x : [x];\n}\n\n/*\n * Converts 32-bit integer color representation to RGBA tuple.\n * Used to serialize colors from OME-XML metadata.\n *\n * > console.log(intToRgba(100100));\n * > // [0, 1, 135, 4]\n */\nexport function intToRgba(int: number) {\n  if (!Number.isInteger(int)) {\n    throw Error('Not an integer.');\n  }\n\n  // Write number to int32 representation (4 bytes).\n  const buffer = new ArrayBuffer(4);\n  const view = new DataView(buffer);\n  view.setInt32(0, int, false); // offset === 0, littleEndian === false\n\n  // Take u8 view and extract number for each byte (1 byte for R/G/B/A).\n  const bytes = new Uint8Array(buffer);\n  return Array.from(bytes) as [number, number, number, number];\n}\n\n/*\n * Helper method to determine whether pixel data is interleaved or not.\n * > isInterleaved([1, 24, 24]) === false;\n * > isInterleaved([1, 24, 24, 3]) === true;\n */\nexport function isInterleaved(shape: number[]) {\n  const lastDimSize = shape[shape.length - 1];\n  return lastDimSize === 3 || lastDimSize === 4;\n}\n\nexport function getImageSize<T extends string[]>(source: PixelSource<T>) {\n  const interleaved = isInterleaved(source.shape);\n  const [height, width] = source.shape.slice(interleaved ? -3 : -2);\n  return {height, width};\n}\n\nexport const SIGNAL_ABORTED = '__vivSignalAborted';\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {GeoTIFFImage} from 'geotiff';\nimport {getImageSize, isInterleaved, SIGNAL_ABORTED} from './utils/tiff-utils';\n\nimport type {\n  PixelSource,\n  PixelSourceSelection,\n  PixelSourceMeta,\n  Dtype,\n  Labels,\n  RasterSelection,\n  TileSelection,\n  PixelData,\n  TypedArray\n} from '../types';\n\ntype ReadRasterOptions = Record<string, any>;\n\nexport class TiffPixelSource<S extends string[]> implements PixelSource<S> {\n  public dtype: Dtype;\n  public tileSize: number;\n  public shape: number[];\n  public labels: Labels<S>;\n  public meta: PixelSourceMeta | undefined;\n  private _indexer: (sel: PixelSourceSelection<S>) => Promise<GeoTIFFImage>;\n\n  // eslint-disable-next-line max-params\n  constructor(\n    indexer: (sel: PixelSourceSelection<S>) => Promise<GeoTIFFImage>,\n    dtype: Dtype,\n    tileSize: number,\n    shape: number[],\n    labels: Labels<S>,\n    meta?: PixelSourceMeta\n  ) {\n    this._indexer = indexer;\n    this.dtype = dtype;\n    this.tileSize = tileSize;\n    this.shape = shape;\n    this.labels = labels;\n    this.meta = meta;\n  }\n\n  async getRaster({selection, signal}: RasterSelection<S>) {\n    const image = await this._indexer(selection);\n    return this._readRasters(image, {signal});\n  }\n\n  async getTile({x, y, selection, signal}: TileSelection<S>) {\n    const {height, width} = this._getTileExtent(x, y);\n    const x0 = x * this.tileSize;\n    const y0 = y * this.tileSize;\n    const window = [x0, y0, x0 + width, y0 + height];\n\n    const image = await this._indexer(selection);\n    return this._readRasters(image, {window, width, height, signal});\n  }\n\n  private async _readRasters(image: GeoTIFFImage, props?: ReadRasterOptions) {\n    const interleave = isInterleaved(this.shape);\n    const raster = await image.readRasters({interleave, ...props});\n\n    if (props?.signal?.aborted) {\n      throw SIGNAL_ABORTED;\n    }\n\n    /*\n     * geotiff.js returns objects with different structure\n     * depending on `interleave`. It's weird, but this seems to work.\n     */\n    const data = (interleave ? raster : raster[0]) as TypedArray;\n    return {\n      data,\n      width: raster.width,\n      height: raster.height\n    } as PixelData;\n  }\n\n  /*\n   * Computes tile size given x, y coord.\n   */\n  private _getTileExtent(x: number, y: number) {\n    const {height: zoomLevelHeight, width: zoomLevelWidth} = getImageSize(this);\n    let height = this.tileSize;\n    let width = this.tileSize;\n    const maxXTileCoord = Math.floor(zoomLevelWidth / this.tileSize);\n    const maxYTileCoord = Math.floor(zoomLevelHeight / this.tileSize);\n    if (x === maxXTileCoord) {\n      width = zoomLevelWidth % this.tileSize;\n    }\n    if (y === maxYTileCoord) {\n      height = zoomLevelHeight % this.tileSize;\n    }\n    return {height, width};\n  }\n\n  onTileError(err: Error) {\n    console.error(err); // eslint-disable-line no-console\n  }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {GeoTIFFImage, GeoTIFF} from 'geotiff';\nimport type {OMEXML} from '../ome/omexml';\n\nexport type ImageFileDirectory = any;\n\nexport type OmeTiffSelection = {t: number; c: number; z: number};\nexport type OmeTiffIndexer = (sel: OmeTiffSelection, z: number) => Promise<GeoTIFFImage>;\n\n/*\n * An \"indexer\" for a GeoTIFF-based source is a function that takes a\n * \"selection\" (e.g. { z, t, c }) and returns a Promise for the GeoTIFFImage\n * object corresponding to that selection.\n *\n * For OME-TIFF images, the \"selection\" object is the same regardless of\n * the format version. However, modern version of Bioformats have a different\n * memory layout for pyramidal resolutions. Thus, we have two different \"indexers\"\n * depending on which format version is detected.\n *\n * TODO: We currently only support indexing the first image in the OME-TIFF with\n * our indexers. There can be multiple images in an OME-TIFF, so supporting these\n * images will require extending these indexers or creating new methods.\n */\n\n/*\n * Returns an indexer for legacy Bioformats images. This assumes that\n * downsampled resolutions are stored sequentially in the OME-TIFF.\n */\nexport function getOmeLegacyIndexer(tiff: GeoTIFF, rootMeta: OMEXML): OmeTiffIndexer {\n  const imgMeta = rootMeta[0];\n  const {SizeT, SizeC, SizeZ} = imgMeta.Pixels;\n  const ifdIndexer = getOmeIFDIndexer(imgMeta);\n\n  return (sel: OmeTiffSelection, pyramidLevel: number) => {\n    // Get IFD index at base pyramid level\n    const index = ifdIndexer(sel);\n    // Get index of first image at pyramidal level\n    const pyramidIndex = pyramidLevel * SizeZ * SizeT * SizeC;\n    // Return image at IFD index for pyramidal level\n    return tiff.getImage(index + pyramidIndex);\n  };\n}\n\n/*\n * Returns an indexer for modern Bioforamts images that store multiscale\n * resolutions using SubIFDs.\n *\n * The ifdIndexer returns the 'index' to the base resolution for a\n * particular 'selection'. The SubIFDs to the downsampled resolutions\n * of the 'selection' are stored within the `baseImage.fileDirectory`.\n * We use the SubIFDs to get the IFD for the corresponding sub-resolution.\n *\n * NOTE: This function create a custom IFD cache rather than mutating\n * `GeoTIFF.ifdRequests` with a random offset. The IFDs are cached in\n * an ES6 Map that maps a string key that identifies the selection uniquely\n * to the corresponding IFD.\n */\nexport function getOmeSubIFDIndexer(tiff: GeoTIFF, rootMeta: OMEXML): OmeTiffIndexer {\n  const imgMeta = rootMeta[0];\n  const ifdIndexer = getOmeIFDIndexer(imgMeta);\n  const ifdCache: Map<string, Promise<ImageFileDirectory>> = new Map();\n\n  return async (sel: OmeTiffSelection, pyramidLevel: number) => {\n    const index = ifdIndexer(sel);\n    const baseImage = await tiff.getImage(index);\n\n    // It's the highest resolution, no need to look up SubIFDs.\n    if (pyramidLevel === 0) {\n      return baseImage;\n    }\n\n    const {SubIFDs} = baseImage.fileDirectory;\n    if (!SubIFDs) {\n      throw Error('Indexing Error: OME-TIFF is missing SubIFDs.');\n    }\n\n    // Get IFD for the selection at the pyramidal level\n    const key = `${sel.t}-${sel.c}-${sel.z}-${pyramidLevel}`;\n    if (!ifdCache.has(key)) {\n      // Only create a new request if we don't have the key.\n      const subIfdOffset = SubIFDs[pyramidLevel - 1];\n      ifdCache.set(key, tiff.parseFileDirectoryAt(subIfdOffset));\n    }\n    const ifd = await ifdCache.get(key);\n\n    // Create a new image object manually from IFD\n    // https://github.com/geotiffjs/geotiff.js/blob/8ef472f41b51d18074aece2300b6a8ad91a21ae1/src/geotiff.js#L447-L453\n    return new (baseImage.constructor as any)(\n      ifd.fileDirectory,\n      ifd.geoKeyDirectory,\n      // @ts-expect-error\n      tiff.dataView,\n      tiff.littleEndian,\n      tiff.cache,\n      tiff.source\n    ) as GeoTIFFImage;\n  };\n}\n\n/*\n * Returns a function that computes the image index based on the dimension\n * order and dimension sizes.\n */\nfunction getOmeIFDIndexer(imgMeta: OMEXML[0]): (sel: OmeTiffSelection) => number {\n  const {SizeC, SizeZ, SizeT, DimensionOrder} = imgMeta.Pixels;\n  switch (DimensionOrder) {\n    case 'XYZCT': {\n      return ({t, c, z}) => t * SizeZ * SizeC + c * SizeZ + z;\n    }\n    case 'XYZTC': {\n      return ({t, c, z}) => c * SizeZ * SizeT + t * SizeZ + z;\n    }\n    case 'XYCTZ': {\n      return ({t, c, z}) => z * SizeC * SizeT + t * SizeC + c;\n    }\n    case 'XYCZT': {\n      return ({t, c, z}) => t * SizeC * SizeZ + z * SizeC + c;\n    }\n    case 'XYTCZ': {\n      return ({t, c, z}) => z * SizeT * SizeC + c * SizeT + t;\n    }\n    case 'XYTZC': {\n      return ({t, c, z}) => c * SizeT * SizeZ + z * SizeT + t;\n    }\n    default: {\n      throw new Error(`Invalid OME-XML DimensionOrder, got ${DimensionOrder}.`);\n    }\n  }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {OMEXML} from '../ome/omexml';\nimport type {Labels} from '../../types';\n\n/*\n * Creates typed labels from DimensionOrder.\n * > imgMeta.Pixels.DimensionOrder === 'XYCZT'\n * > getLabels(imgMeta.Pixels) === ['t', 'z', 'c', 'y', 'x']\n */\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype Sel<Dim extends string> = Dim extends `${infer Z}${infer X}${infer A}${infer B}${infer C}`\n  ? [C, B, A]\n  : 'error';\nexport function getLabels(dimOrder: OMEXML[0]['Pixels']['DimensionOrder']) {\n  return dimOrder.toLowerCase().split('').reverse() as Labels<Sel<Lowercase<typeof dimOrder>>>;\n}\n\n/*\n * Creates an ES6 map of 'label' -> index\n * > const labels = ['a', 'b', 'c', 'd'];\n * > const dims = getDims(labels);\n * > dims('a') === 0;\n * > dims('b') === 1;\n * > dims('c') === 2;\n * > dims('hi!'); // throws\n */\nexport function getDims<S extends string>(labels: S[]) {\n  const lookup = new Map(labels.map((name, i) => [name, i]));\n  if (lookup.size !== labels.length) {\n    throw Error('Labels must be unique, found duplicated label.');\n  }\n  return (name: S) => {\n    const index = lookup.get(name);\n    if (index === undefined) {\n      throw Error('Invalid dimension.');\n    }\n    return index;\n  };\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {getDims, getLabels} from './utils';\nimport type {OMEXML, UnitsLength} from './omexml';\n\nexport const DTYPE_LOOKUP = {\n  uint8: 'Uint8',\n  uint16: 'Uint16',\n  uint32: 'Uint32',\n  float: 'Float32',\n  double: 'Float64',\n  int8: 'Int8',\n  int16: 'Int16',\n  int32: 'Int32'\n} as const;\n\nexport function getOmePixelSourceMeta({Pixels}: OMEXML[0]) {\n  // e.g. 'XYZCT' -> ['t', 'c', 'z', 'y', 'x']\n  const labels = getLabels(Pixels.DimensionOrder);\n\n  // Compute \"shape\" of image\n  const dims = getDims(labels);\n  const shape: number[] = Array(labels.length).fill(0);\n  shape[dims('t')] = Pixels.SizeT;\n  shape[dims('c')] = Pixels.SizeC;\n  shape[dims('z')] = Pixels.SizeZ;\n\n  // Push extra dimension if data are interleaved.\n  if (Pixels.Interleaved) {\n    // @ts-ignore\n    labels.push('_c');\n    shape.push(3);\n  }\n\n  // Creates a new shape for different level of pyramid.\n  // Assumes factor-of-two downsampling.\n  const getShape = (level: number) => {\n    const s = [...shape];\n    s[dims('x')] = Pixels.SizeX >> level;\n    s[dims('y')] = Pixels.SizeY >> level;\n    return s;\n  };\n\n  if (!(Pixels.Type in DTYPE_LOOKUP)) {\n    throw Error(`Pixel type ${Pixels.Type} not supported.`);\n  }\n\n  const dtype = DTYPE_LOOKUP[Pixels.Type as keyof typeof DTYPE_LOOKUP];\n  if (Pixels.PhysicalSizeX && Pixels.PhysicalSizeY) {\n    const physicalSizes: {\n      [k: string]: {size: number; unit: UnitsLength};\n    } = {\n      x: {\n        size: Pixels.PhysicalSizeX,\n        unit: Pixels.PhysicalSizeXUnit\n      },\n      y: {\n        size: Pixels.PhysicalSizeY,\n        unit: Pixels.PhysicalSizeYUnit\n      }\n    };\n    if (Pixels.PhysicalSizeZ) {\n      physicalSizes.z = {\n        size: Pixels.PhysicalSizeZ,\n        unit: Pixels.PhysicalSizeZUnit\n      };\n    }\n    return {labels, getShape, physicalSizes, dtype};\n  }\n\n  return {labels, getShape, dtype};\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {XMLParser} from 'fast-xml-parser';\nimport {ensureArray, intToRgba} from '../utils/tiff-utils';\n\n// WARNING: Changes to the parser options _will_ effect the types in types/omexml.d.ts.\nconst xmlParser = new XMLParser({\n  // Nests attributes withtout prefix under 'attr' key for each node\n  attributeNamePrefix: '',\n  attributesGroupName: 'attr',\n\n  // Parses numbers for both attributes and nodes\n  parseTagValue: true,\n  parseAttributeValue: true,\n\n  // Forces attributes to be parsed\n  ignoreAttributes: false\n});\n\nconst parse = (str: string): Root => xmlParser.parse(str);\n\nexport function fromString(str: string) {\n  const res = parse(str);\n  if (!res.OME) {\n    throw Error('Failed to parse OME-XML metadata.');\n  }\n  return ensureArray(res.OME.Image).map((img) => {\n    const Channels = ensureArray(img.Pixels.Channel).map((c) => {\n      if ('Color' in c.attr) {\n        return {...c.attr, Color: intToRgba(c.attr.Color)};\n      }\n      return {...c.attr};\n    });\n    const {AquisitionDate = '', Description = ''} = img;\n    const image = {\n      ...img.attr,\n      AquisitionDate,\n      Description,\n      Pixels: {\n        ...img.Pixels.attr,\n        Channels\n      }\n    };\n    return {\n      ...image,\n      format() {\n        const {Pixels} = image;\n\n        const sizes = (['X', 'Y', 'Z'] as const)\n          .map((name) => {\n            const size = Pixels[`PhysicalSize${name}` as const];\n            const unit = Pixels[`PhysicalSize${name}Unit` as const];\n            return size && unit ? `${size} ${unit}` : '-';\n          })\n          .join(' x ');\n\n        return {\n          'Acquisition Date': image.AquisitionDate,\n          'Dimensions (XY)': `${Pixels.SizeX} x ${Pixels.SizeY}`,\n          'Pixels Type': Pixels.Type,\n          'Pixels Size (XYZ)': sizes,\n          'Z-sections/Timepoints': `${Pixels.SizeZ} x ${Pixels.SizeT}`,\n          Channels: Pixels.SizeC\n        };\n      }\n    };\n  });\n}\n\nexport type OMEXML = ReturnType<typeof fromString>;\nexport type DimensionOrder = 'XYZCT' | 'XYZTC' | 'XYCTZ' | 'XYCZT' | 'XYTCZ' | 'XYTZC';\n\n// Structure of node is determined by the PARSER_OPTIONS.\ntype Node<T, A> = T & {attr: A};\ntype Attrs<Fields extends string, T = string> = {[K in Fields]: T};\n\ntype OMEAttrs = Attrs<'xmlns' | 'xmlns:xsi' | 'xsi:schemaLocation'>;\ntype OME = Node<{Insturment: Insturment; Image: Image | Image[]}, OMEAttrs>;\n\ntype Insturment = Node<\n  {Objective: Node<{}, Attrs<'ID' | 'Model' | 'NominalMagnification'>>},\n  Attrs<'ID'>\n>;\n\ninterface ImageNodes {\n  AquisitionDate?: string;\n  Description?: string;\n  Pixels: Pixels;\n  InstrumentRef: Node<{}, {ID: string}>;\n  ObjectiveSettings: Node<{}, {ID: string}>;\n}\ntype Image = Node<ImageNodes, Attrs<'ID' | 'Name'>>;\n\ntype PixelType =\n  | 'int8'\n  | 'int16'\n  | 'int32'\n  | 'uint8'\n  | 'uint16'\n  | 'uint32'\n  | 'float'\n  | 'bit'\n  | 'double'\n  | 'complex'\n  | 'double-complex';\n\nexport type UnitsLength =\n  | 'Ym'\n  | 'Zm'\n  | 'Em'\n  | 'Pm'\n  | 'Tm'\n  | 'Gm'\n  | 'Mm'\n  | 'km'\n  | 'hm'\n  | 'dam'\n  | 'm'\n  | 'dm'\n  | 'cm'\n  | 'mm'\n  | '\u00B5m'\n  | 'nm'\n  | 'pm'\n  | 'fm'\n  | 'am'\n  | 'zm'\n  | 'ym'\n  | '\u00C5'\n  | 'thou'\n  | 'li'\n  | 'in'\n  | 'ft'\n  | 'yd'\n  | 'mi'\n  | 'ua'\n  | 'ly'\n  | 'pc'\n  | 'pt'\n  | 'pixel'\n  | 'reference frame';\n\ntype PhysicalSize<Name extends string> = `PhysicalSize${Name}`;\ntype PhysicalSizeUnit<Name extends string> = `PhysicalSize${Name}Unit`;\ntype Size<Names extends string> = `Size${Names}`;\n\ntype PixelAttrs = Attrs<\n  PhysicalSize<'X' | 'Y' | 'Z'> | 'SignificantBits' | Size<'T' | 'C' | 'Z' | 'Y' | 'X'>,\n  number\n> &\n  Attrs<PhysicalSizeUnit<'X' | 'Y' | 'Z'>, UnitsLength> &\n  Attrs<'BigEndian' | 'Interleaved', boolean> & {\n    ID: string;\n    DimensionOrder: DimensionOrder;\n    Type: PixelType;\n  };\n\ntype Pixels = Node<\n  {\n    Channel: Channel | Channel[];\n    TiffData: Node<{}, Attrs<'IFD' | 'PlaneCount'>>;\n  },\n  PixelAttrs\n>;\n\ntype ChannelAttrs =\n  | {\n      ID: string;\n      SamplesPerPixel: number;\n      Name?: string;\n    }\n  | {\n      ID: string;\n      SamplesPerPixel: number;\n      Name?: string;\n      Color: number;\n    };\n\ntype Channel = Node<{}, ChannelAttrs>;\n\ntype Root = {OME: OME};\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {GeoTIFF, GeoTIFFImage} from 'geotiff';\n\nimport {TiffPixelSource} from '../tiff-pixel-source';\nimport {getOmeLegacyIndexer, getOmeSubIFDIndexer, OmeTiffIndexer} from './ome-indexers';\nimport {getOmePixelSourceMeta} from './ome-utils';\nimport {fromString} from './omexml';\nimport type {OmeTiffSelection} from './ome-indexers';\n\nexport const isOmeTiff = (img: GeoTIFFImage) => img.fileDirectory.ImageDescription.includes('<OME');\n\nexport async function loadOmeTiff(tiff: GeoTIFF, firstImage: GeoTIFFImage) {\n  // Get first image from tiff and inspect OME-XML metadata\n  const {\n    ImageDescription,\n    SubIFDs,\n    PhotometricInterpretation: photometricInterpretation\n  } = firstImage.fileDirectory;\n  const omexml = fromString(ImageDescription);\n\n  /*\n   * Image pyramids are stored differently between versions of Bioformats.\n   * Thus we need a different indexer depending on which format we have.\n   */\n  let levels: number;\n  let pyramidIndexer: OmeTiffIndexer;\n\n  if (SubIFDs) {\n    // Image is >= Bioformats 6.0 and resolutions are stored using SubIFDs.\n    levels = SubIFDs.length + 1;\n    pyramidIndexer = getOmeSubIFDIndexer(tiff, omexml);\n  } else {\n    // Image is legacy format; resolutions are stored as separate images.\n    levels = omexml.length;\n    pyramidIndexer = getOmeLegacyIndexer(tiff, omexml);\n  }\n\n  // TODO: The OmeTIFF loader only works for the _first_ image in the metadata.\n  const imgMeta = omexml[0];\n  const {labels, getShape, physicalSizes, dtype} = getOmePixelSourceMeta(imgMeta);\n  const tileSize = firstImage.getTileWidth();\n  const meta = {photometricInterpretation, physicalSizes};\n\n  const data = Array.from({length: levels}).map((_, resolution) => {\n    const shape = getShape(resolution);\n    const indexer = (sel: OmeTiffSelection) => pyramidIndexer(sel, resolution);\n    const source = new TiffPixelSource(indexer, dtype, tileSize, shape, labels, meta);\n    return source;\n  });\n\n  return {data, metadata: imgMeta};\n}\n"],
  "mappings": "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",
  "names": ["import_geotiff"]
}
