You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2021/07/29 21:38:28 UTC
[sis] branch geoapi-4.0 updated: Minor optimization for the case
where the bands to read are consecutive.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 79d5221 Minor optimization for the case where the bands to read are consecutive.
79d5221 is described below
commit 79d5221c53a6fefd0f4eab7aab2f061007f7eb16
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Jul 29 23:10:42 2021 +0200
Minor optimization for the case where the bands to read are consecutive.
---
.../sis/storage/geotiff/CompressedSubset.java | 47 +++++++++++++++++-----
1 file changed, 38 insertions(+), 9 deletions(-)
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CompressedSubset.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CompressedSubset.java
index 1b36eb1..f49ed60 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CompressedSubset.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CompressedSubset.java
@@ -107,19 +107,36 @@ final class CompressedSubset extends DataSubset {
final int between = sourcePixelStride * (getSubsampling(0) - 1);
int afterLastBand = sourcePixelStride * (getTileSize(0) - 1);
if (selectedBands != null && sourcePixelStride > 1) {
- final int n = selectedBands.length;
- skipAfterElements = new int[n];
+ final int[] skips = new int[selectedBands.length];
+ final int m = skips.length - 1;
int b = sourcePixelStride;
- for (int i = n; --i >= 0;) {
+ for (int i=m; i >= 0; --i) {
// Number of sample values to skip after each band.
- skipAfterElements[i] = b - (b = selectedBands[i]) - 1;
+ skips[i] = b - (b = selectedBands[i]) - 1;
+ }
+ beforeFirstBand = b;
+ afterLastBand += skips[m]; // Add trailing bands that were left unread.
+ skips[m] += between + beforeFirstBand; // Add pixels skipped by subsampling and move to first band.
+ /*
+ * If there is more than one band and all of them are consecutive, then we can optimize a little bit
+ * by reading "chunks" of the size of those consecutive bands instead of reading each band separately.
+ *
+ * Example: if the image has 5 bands and users requested bands 1, 2 and 3 (no empty space between bands),
+ * then we can read those 3 bands as a "chunk" on 3 sample values instead of reading 3 chunks of 1 value.
+ */
+ if (m != 0 && startsWithZeros(skips, m)) {
+ samplesPerElement = selectedBands.length;
+ skipAfterElements = new int[] {skips[m]};
+ } else {
+ samplesPerElement = 1;
+ skipAfterElements = skips;
}
- beforeFirstBand = b;
- afterLastBand += skipAfterElements[n-1]; // Add trailing bands that were left unread.
- skipAfterElements[n-1] += between + beforeFirstBand; // Add pixels skipped by subsampling and move to first band.
- samplesPerElement = 1;
- // TODO: we could optimize if we find that all sample values to read are consecutive.
} else {
+ /*
+ * Case when all bands are read. If there is a subsampling, then `between` is the space (in number of
+ * sample values) between two pixels. If that space is zero, it will be possible to read the whole row
+ * in a single read operation, but that optimization is done in `Inflater` constructor.
+ */
skipAfterElements = (between != 0) ? new int[] {between} : null;
samplesPerElement = sourcePixelStride;
beforeFirstBand = 0;
@@ -133,6 +150,18 @@ final class CompressedSubset extends DataSubset {
}
/**
+ * Returns {@code true} if all array elements except the last one are zeros.
+ * A {@code true} value means that all sample values in a pixel are consecutive.
+ *
+ * @param m {@code skipAfterElements.length} - 1. Shall be greater than zero.
+ */
+ private static boolean startsWithZeros(final int[] skipAfterElements, int m) {
+ do if (skipAfterElements[--m] != 0) return false;
+ while (m != 0);
+ return true;
+ }
+
+ /**
* Computes the number of pixels to read in dimension <var>i</var>
* The arguments given to this method are the ones given to the {@code readSlice(…)} method.
*/