From 8437bec1e14a78335db6d9b64d7be9af6e957847 Mon Sep 17 00:00:00 2001 From: tiagohm Date: Fri, 5 Apr 2024 14:19:29 -0300 Subject: [PATCH] [api]: Take account of DATAMIN and DATAMAX FITS keywords --- .../src/main/kotlin/nebulosa/fits/FitsFormat.kt | 5 ++++- .../kotlin/nebulosa/fits/SeekableSourceImageData.kt | 9 ++++++++- .../src/main/kotlin/nebulosa/image/format/ImageData.kt | 10 ++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt index 95e648f7a..9336676ff 100644 --- a/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt +++ b/nebulosa-fits/src/main/kotlin/nebulosa/fits/FitsFormat.kt @@ -66,8 +66,11 @@ data object FitsFormat : ImageFormat { val numberOfChannels = header.numberOfChannels val bitpix = header.bitpix val position = source.position + val rangeMin = header.getFloat(FitsKeyword.DATAMIN, 0f) + val rangeMax = header.getFloat(FitsKeyword.DATAMAX, 1f) + val range = rangeMin..rangeMax - val data = SeekableSourceImageData(source, position, width, height, numberOfChannels, bitpix) + val data = SeekableSourceImageData(source, position, width, height, numberOfChannels, bitpix, range) val skipBytes = computeRemainingBytesToSkip(data.totalSizeInBytes) if (skipBytes > 0L) source.seek(position + data.totalSizeInBytes + skipBytes) diff --git a/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt b/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt index 4a7fc10ae..bd79dd395 100644 --- a/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt +++ b/nebulosa-fits/src/main/kotlin/nebulosa/fits/SeekableSourceImageData.kt @@ -3,6 +3,7 @@ package nebulosa.fits import nebulosa.fits.FitsFormat.readPixel import nebulosa.image.format.ImageChannel import nebulosa.image.format.ImageData +import nebulosa.image.format.ImageData.Companion.representableRange import nebulosa.io.SeekableSource import okio.Buffer import okio.Sink @@ -16,8 +17,12 @@ internal data class SeekableSourceImageData( override val height: Int, override val numberOfChannels: Int, private val bitpix: Bitpix, + private val range: ClosedFloatingPointRange, ) : ImageData { + private val rangeDelta = range.endInclusive - range.start + private val rescale = range.start != 0f || range.endInclusive != 1f + @JvmField internal val channelSizeInBytes = (numberOfPixels * bitpix.byteLength).toLong() @JvmField internal val totalSizeInBytes = channelSizeInBytes * numberOfChannels @@ -84,7 +89,9 @@ internal data class SeekableSourceImageData( n = (size / bitpix.byteLength).toInt() repeat(n) { - output[pos++] = buffer.readPixel(bitpix) + val pixel = buffer.readPixel(bitpix) + output[pos++] = if (rescale) pixel.representableRange(range.start, range.endInclusive, rangeDelta) + else pixel } remainingPixels -= n diff --git a/nebulosa-image-format/src/main/kotlin/nebulosa/image/format/ImageData.kt b/nebulosa-image-format/src/main/kotlin/nebulosa/image/format/ImageData.kt index ab83c43ca..748701ee4 100644 --- a/nebulosa-image-format/src/main/kotlin/nebulosa/image/format/ImageData.kt +++ b/nebulosa-image-format/src/main/kotlin/nebulosa/image/format/ImageData.kt @@ -18,4 +18,14 @@ interface ImageData { val blue: FloatArray fun readChannelTo(channel: ImageChannel, output: FloatArray) + + companion object { + + @Suppress("NOTHING_TO_INLINE") + inline fun Float.representableRange(rangeMin: Float, rangeMax: Float, rangeDelta: Float = rangeMax - rangeMin): Float { + return if (this < rangeMin) 0f + else if (this > rangeMax) 1f + else (this - rangeMin) / rangeDelta + } + } }