View Javadoc
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 }