1 package nom.tam.image.tile.operation.buffer; 2 3 /* 4 * #%L 5 * nom.tam FITS library 6 * %% 7 * Copyright (C) 1996 - 2024 nom-tam-fits 8 * %% 9 * This is free and unencumbered software released into the public domain. 10 * 11 * Anyone is free to copy, modify, publish, use, compile, sell, or 12 * distribute this software, either in source code form or as a compiled 13 * binary, for any purpose, commercial or non-commercial, and by any 14 * means. 15 * 16 * In jurisdictions that recognize copyright laws, the author or authors 17 * of this software dedicate any and all copyright interest in the 18 * software to the public domain. We make this dedication for the benefit 19 * of the public at large and to the detriment of our heirs and 20 * successors. We intend this dedication to be an overt act of 21 * relinquishment in perpetuity of all present and future rights to this 22 * software under copyright law. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 * OTHER DEALINGS IN THE SOFTWARE. 31 * #L% 32 */ 33 34 import java.nio.Buffer; 35 36 import nom.tam.util.type.ElementType; 37 38 /** 39 * <p> 40 * (<i>for internal use</i>) Tiling implementation, for when the tile width is less than the width of the image. For 41 * example, for covering a 300 by 250 image with tiles of 40 by 40 pixels. 42 * </p> 43 * <p> 44 * This subclass of the row based view, will abstract the problems that occur when the tile does not spread over a whole 45 * row. in that case the buffer describing the image does not match the buffer describing the tile. That is why a 46 * temporary buffer is needed to make the buffer continuous. 47 * </p> 48 * 49 * @see TileBufferRowBased 50 */ 51 class TileBufferColumnBased extends TileBuffer { 52 53 /** 54 * the buffer representing the tile data gap less. this will exist only between the first getBuffer() and the 55 * finish(). This way the memory used for the data copy is allocates as early as needed and freed as soon as 56 * possible. 57 */ 58 private Buffer packed; 59 60 /** 61 * the width of the image in pixels, that differs from the width of the tile. 62 */ 63 private final int imageWidth; 64 65 TileBufferColumnBased(ElementType<Buffer> baseType, int dataOffset, int imageWidth, int width, int height) { 66 super(baseType, dataOffset, width, height); 67 this.imageWidth = imageWidth; 68 } 69 70 @Override 71 public void finish() { 72 desolveGapLessBuffer(); 73 } 74 75 @Override 76 public Buffer getBuffer() { 77 if (packed == null) { 78 createPackedBuffer(); 79 } 80 return packed; 81 } 82 83 /** 84 * create the temporary buffer that contains no data gaps. 85 */ 86 private void createPackedBuffer() { 87 final int gap = imageWidth - getWidth(); 88 89 Buffer raw = getImageBuffer(); 90 final int imLength = Math.min(raw.capacity(), getPixelSizeInData()); 91 92 raw.position(0); 93 94 ElementType<Buffer> type = elementType(); 95 packed = type.newBuffer(getPixelSize()); 96 97 for (int i = 0; i < getHeight(); i++) { 98 raw.limit(raw.position() + getWidth()); 99 type.appendBuffer(packed, raw); 100 raw.limit(Math.min(raw.position() + gap, imLength)); 101 raw.position(raw.limit()); 102 } 103 packed.rewind(); 104 raw.limit(imLength); 105 } 106 107 /** 108 * resolve the temporary buffer that contains no data gaps, and put the data back into the image buffer. 109 */ 110 private void desolveGapLessBuffer() { 111 final int gap = imageWidth - getWidth(); 112 Buffer raw = getImageBuffer(); 113 raw.position(0); 114 raw.limit(getPixelSizeInData()); 115 packed.rewind(); 116 117 ElementType<Buffer> type = elementType(); 118 119 for (int i = 0; i < getHeight(); i++) { 120 packed.limit(packed.position() + getWidth()); 121 type.appendBuffer(raw, packed); 122 raw.position(Math.min(raw.position() + gap, raw.limit())); 123 } 124 packed = null; 125 } 126 127 /** 128 * @return size of the tile data inside the image data. normally tile-height*image-width but then the data block of 129 * the last tile would go over the image data limit. 130 */ 131 private int getPixelSizeInData() { 132 return (getHeight() - 1) * imageWidth + getWidth(); 133 } 134 135 private ElementType<Buffer> elementType() { 136 return ElementType.forBuffer(getImageBuffer()); 137 } 138 139 }