CoverityFix-CID:1360865 Inner class could be made static
[scilab.git] / scilab / modules / scirenderer / src / org / scilab / forge / scirenderer / implementation / g2d / texture / G2DTextureManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  */
14
15 package org.scilab.forge.scirenderer.implementation.g2d.texture;
16
17 import org.scilab.forge.scirenderer.SciRendererException;
18 import org.scilab.forge.scirenderer.implementation.g2d.G2DCanvas;
19 import org.scilab.forge.scirenderer.implementation.g2d.G2DDrawingTools;
20 import org.scilab.forge.scirenderer.texture.AbstractTexture;
21 import org.scilab.forge.scirenderer.texture.Texture;
22 import org.scilab.forge.scirenderer.texture.TextureDrawer;
23 import org.scilab.forge.scirenderer.texture.TextureManager;
24 import org.scilab.forge.scirenderer.texture.TextureDataProvider.ImageType;
25
26 import java.awt.Dimension;
27 import java.awt.image.BufferedImage;
28 import java.nio.ByteBuffer;
29 import java.nio.ByteOrder;
30 import java.nio.FloatBuffer;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.HashMap;
34 import java.util.Map;
35
36 /**
37  * @author Calixte DENIZET
38  */
39 public class G2DTextureManager implements TextureManager {
40
41     private static Map<ImageBuffer, ImageBuffer> images = new HashMap<ImageBuffer, ImageBuffer>();
42
43     public G2DTextureManager(G2DCanvas canvas) { }
44
45     public static void clear() {
46         images.clear();
47     }
48
49     /**
50      * Draw the given texture.
51      * @param drawingTools used drawing tools.
52      * @param texture the texture too drawn.
53      * @throws org.scilab.forge.scirenderer.SciRendererException if the texture is invalid.
54      */
55     public void draw(G2DDrawingTools drawingTools, Texture texture) throws SciRendererException {
56         if (texture instanceof G2DTexture) {
57             ((G2DTexture) texture).draw(drawingTools);
58         }
59     }
60
61     @Override
62     public Texture createTexture() {
63         return new G2DTexture();
64     }
65
66     @Override
67     public void dispose(Collection<Texture> textures) {
68         for (Texture texture : textures) {
69             dispose(texture);
70         }
71     }
72
73     @Override
74     public void dispose(Texture texture) {
75         if (texture instanceof G2DTexture) {
76             ((G2DTexture) texture).dispose();
77         }
78     }
79
80     private static final int toColorComp(final float f) {
81         return (f < 0) ? 0 : ((f > 1) ? 0xFF : ((int) (f * 255.0f)));
82     }
83
84     /**
85      * Inner class for {@link Texture} implementation.
86      */
87     public static class G2DTexture extends AbstractTexture implements Texture {
88
89         private ImageBuffer image;
90         private TextureDrawer drawer;
91
92         /**
93          * Default constructor.
94          */
95         public G2DTexture() { }
96
97         public void dispose() {
98             images.remove(image);
99         }
100
101         @Override
102         public void setDrawer(TextureDrawer drawer) {
103             this.drawer = drawer;
104             super.setDrawer(drawer);
105         }
106
107         public TextureDrawer getDrawer() {
108             return drawer;
109         }
110
111         public void draw(G2DDrawingTools drawingTools) {
112             drawingTools.getMotor3D().drawTexture(drawingTools, getImage(), this);
113         }
114
115         public BufferedImage getImage() {
116             if (image == null) {
117                 Dimension textureSize = getDataProvider().getTextureSize();
118                 ByteBuffer buffer = getDataProvider().getData();
119                 ImageType type = getDataProvider().getImageType();
120                 int imageType = BufferedImage.TYPE_INT_RGB;
121                 int[] ibuffer = null;
122                 final ByteOrder order = ByteOrder.nativeOrder();
123
124                 switch (type) {
125                     case RGB: {
126                         imageType = BufferedImage.TYPE_INT_RGB;
127                         ibuffer = new int[buffer.capacity() / 3];
128                         int k = 0;
129                         for (int i = 0; i < buffer.capacity(); i += 3) {
130                             ibuffer[k++] = ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
131                         }
132                         break;
133                     }
134                     case RGB_RGBA: {
135                         imageType = BufferedImage.TYPE_INT_RGB;
136                         ibuffer = new int[buffer.capacity() / 4];
137                         int k = 0;
138                         if (order == ByteOrder.LITTLE_ENDIAN) {
139                             for (int i = 0; i < buffer.capacity(); i += 4) {
140                                 ibuffer[k++] = ((buffer.get(i + 3) & 0xFF) << 16) | ((buffer.get(i + 2) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF);
141                             }
142                         } else {
143                             for (int i = 0; i < buffer.capacity(); i += 4) {
144                                 ibuffer[k++] = ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
145                             }
146                         }
147                         break;
148                     }
149                     case BGR: {
150                         imageType = BufferedImage.TYPE_INT_BGR;
151                         ibuffer = new int[buffer.capacity() / 3];
152                         int k = 0;
153                         for (int i = 0; i < buffer.capacity(); i += 3) {
154                             ibuffer[k++] = ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
155                         }
156                         break;
157                     }
158                     case GRAY: {
159                         imageType = BufferedImage.TYPE_INT_RGB;
160                         ibuffer = new int[buffer.capacity()];
161                         for (int i = 0; i < buffer.capacity(); i++) {
162                             final int c = buffer.get(i) & 0xFF;
163                             ibuffer[i] = (c << 16) | (c << 8) | c;
164                         }
165                         break;
166                     }
167                     case GRAY_16: {
168                         imageType = BufferedImage.TYPE_INT_RGB;
169                         ibuffer = new int[buffer.capacity() / 2];
170                         int k = 0;
171                         if (order == ByteOrder.LITTLE_ENDIAN) {
172                             for (int i = 0; i < buffer.capacity(); i += 2) {
173                                 final int c = (((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i) & 0xFF)) / 257;
174                                 ibuffer[k++] = (c << 16) | (c << 8) | c;
175                             }
176                         } else {
177                             for (int i = 0; i < buffer.capacity(); i += 2) {
178                                 final int c = (((buffer.get(i) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF)) / 257;
179                                 ibuffer[k++] = (c << 16) | (c << 8) | c;
180                             }
181                         }
182                         break;
183                     }
184                     case RGBA: {
185                         imageType = BufferedImage.TYPE_INT_ARGB;
186                         ibuffer = new int[buffer.capacity() / 4];
187                         if (order == ByteOrder.LITTLE_ENDIAN) {
188                             int k = 0;
189                             for (int i = 0; i < buffer.capacity(); i += 4) {
190                                 ibuffer[k++] = ((buffer.get(i) & 0xFF) << 24) | ((buffer.get(i + 3) & 0xFF) << 16) | ((buffer.get(i + 2) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF);
191                             }
192                         } else {
193                             int k = 0;
194                             for (int i = 0; i < buffer.capacity(); i += 4) {
195                                 ibuffer[k++] = ((buffer.get(i + 3) & 0xFF) << 24) | ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
196                             }
197                         }
198                         break;
199                     }
200                     case RGBA_REV: {
201                         imageType = BufferedImage.TYPE_INT_ARGB;
202                         ibuffer = new int[buffer.capacity() / 4];
203                         if (order == ByteOrder.BIG_ENDIAN) {
204                             int k = 0;
205                             for (int i = 0; i < buffer.capacity(); i += 4) {
206                                 ibuffer[k++] = ((buffer.get(i) & 0xFF) << 24) | ((buffer.get(i + 3) & 0xFF) << 16) | ((buffer.get(i + 2) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF);
207                             }
208                         } else {
209                             int k = 0;
210                             for (int i = 0; i < buffer.capacity(); i += 4) {
211                                 ibuffer[k++] = ((buffer.get(i + 3) & 0xFF) << 24) | ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
212                             }
213                         }
214                         break;
215                     }
216                     case ABGR: {
217                         imageType = BufferedImage.TYPE_INT_ARGB;
218                         ibuffer = new int[buffer.capacity() / 4];
219                         int k = 0;
220                         for (int i = 0; i < buffer.capacity(); i += 4) {
221                             ibuffer[k++] = ((buffer.get(i) & 0xFF) << 24) | ((buffer.get(i + 3) & 0xFF) << 16) | ((buffer.get(i + 2) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF);
222                         }
223                         break;
224                     }
225                     case RGB_332: {
226                         imageType = BufferedImage.TYPE_INT_RGB;
227                         ibuffer = new int[buffer.capacity()];
228                         for (int i = 0; i < buffer.capacity(); i++) {
229                             final int c = buffer.get(i) & 0xFF;
230                             ibuffer[i] = ((((c >> 5) & 0x7) * 255 / 7) << 16) | ((((c >> 2) & 0x7) * 255 / 7) << 8) | ((c & 0x3) * 255 / 3);
231                         }
232                         break;
233                     }
234                     case RED: {
235                         imageType = BufferedImage.TYPE_INT_RGB;
236                         ibuffer = new int[buffer.capacity()];
237                         for (int i = 0; i < buffer.capacity(); i++) {
238                             ibuffer[i] = (buffer.get(i) & 0xFF) << 16;
239                         }
240                         break;
241                     }
242                     case GREEN: {
243                         imageType = BufferedImage.TYPE_INT_RGB;
244                         ibuffer = new int[buffer.capacity()];
245                         for (int i = 0; i < buffer.capacity(); i++) {
246                             ibuffer[i] = (buffer.get(i) & 0xFF) << 8;
247                         }
248                         break;
249                     }
250                     case BLUE: {
251                         imageType = BufferedImage.TYPE_INT_RGB;
252                         ibuffer = new int[buffer.capacity()];
253                         for (int i = 0; i < buffer.capacity(); i++) {
254                             ibuffer[i] = (buffer.get(i) & 0xFF);
255                         }
256                         break;
257                     }
258                     case INTENSITY: {
259                         imageType = BufferedImage.TYPE_INT_ARGB;
260                         ibuffer = new int[buffer.capacity()];
261                         for (int i = 0; i < buffer.capacity(); i++) {
262                             final int c = buffer.get(i) & 0xFF;
263                             ibuffer[i] = (c << 24) | (c << 16) | (c << 8) | c;
264                         }
265                         break;
266                     }
267                     case RGBA_4444: {
268                         imageType = BufferedImage.TYPE_INT_ARGB;
269                         ibuffer = new int[buffer.capacity() / 2];
270                         int k = 0;
271                         if (order == ByteOrder.LITTLE_ENDIAN) {
272                             for (int i = 0; i < buffer.capacity(); i += 2) {
273                                 int c = buffer.get(i) & 0xFF;
274                                 final int B = ((c >> 4) & 0xF) * 0x11;
275                                 final int A = (c & 0xF) * 0x11;
276                                 c = buffer.get(i + 1) & 0xFF;
277                                 final int R = ((c >> 4) & 0xF) * 0x11;
278                                 final int G = (c & 0xF) * 0x11;
279                                 ibuffer[k++] = (A << 24) | (R << 16) | (G << 8) | B;
280                             }
281                         } else {
282                             for (int i = 0; i < buffer.capacity(); i += 2) {
283                                 int c = buffer.get(i + 1) & 0xFF;
284                                 final int B = ((c >> 4) & 0xF) * 0x2F;
285                                 final int A = (c & 0xF) * 0x2F;
286                                 c = buffer.get(i) & 0xFF;
287                                 final int R = ((c >> 4) & 0xF) * 0x2F;
288                                 final int G = (c & 0xF) * 0x2F;
289                                 ibuffer[k++] = (A << 24) | (R << 16) | (G << 8) | B;
290                             }
291                         }
292                         break;
293                     }
294                     case RGBA_5551: {
295                         imageType = BufferedImage.TYPE_INT_ARGB;
296                         ibuffer = new int[buffer.capacity() / 2];
297                         int k = 0;
298                         if (order == ByteOrder.LITTLE_ENDIAN) {
299                             for (int i = 0; i < buffer.capacity(); i += 2) {
300                                 int c = buffer.get(i) & 0xFF;
301                                 final int B = (((c >> 1) & 0x1F) * 0xFF) / 0x1F;
302                                 final int A = (c & 0x1) * 0xFF;
303                                 int G = (c >> 6) & 0x3;
304                                 c = buffer.get(i + 1) & 0xFF;
305                                 final int R = (((c >> 3) & 0x1F) * 0xFF) / 0x1F;
306                                 G = (((c & 0x7) << 2 | G) * 0xFF) / 0x1F;
307                                 ibuffer[k++] = (A << 24) | (R << 16) | (G << 8) | B;
308                             }
309                         } else {
310                             for (int i = 0; i < buffer.capacity(); i += 2) {
311                                 int c = buffer.get(i + 1) & 0xFF;
312                                 final int B = (((c >> 1) & 0x1F) * 0xFF) / 0x1F;
313                                 final int A = (c & 0x1) * 0xFF;
314                                 int G = (c >> 6) & 0x3;
315                                 c = buffer.get(i) & 0xFF;
316                                 final int R = (((c >> 3) & 0x1F) * 0xFF) / 0x1F;
317                                 G = (((c & 0x7) << 2 | G) * 0xFF) / 0x1F;
318                                 ibuffer[k++] = (A << 24) | (R << 16) | (G << 8) | B;
319                             }
320                         }
321                         break;
322                     }
323                     case RGB_FLOAT: {
324                         imageType = BufferedImage.TYPE_INT_RGB;
325                         FloatBuffer fbuffer = buffer.asFloatBuffer();
326                         ibuffer = new int[fbuffer.capacity() / 3];
327                         int k = 0;
328                         for (int i = 0; i < fbuffer.capacity(); i += 3) {
329                             ibuffer[k++] = (toColorComp(fbuffer.get(i)) << 16) | (toColorComp(buffer.get(i + 1)) << 8) | toColorComp(buffer.get(i + 2));
330                         }
331                         break;
332                     }
333                     case RGBA_FLOAT: {
334                         imageType = BufferedImage.TYPE_INT_ARGB;
335                         buffer.order(order);
336                         FloatBuffer fbuffer = buffer.asFloatBuffer();
337                         ibuffer = new int[fbuffer.capacity() / 4];
338                         int k = 0;
339                         for (int i = 0; i < fbuffer.capacity(); i += 4) {
340                             ibuffer[k++] = (toColorComp(fbuffer.get(i + 3)) << 24) | (toColorComp(fbuffer.get(i)) << 16) | (toColorComp(fbuffer.get(i + 1)) << 8) | toColorComp(fbuffer.get(i + 2));
341                         }
342                         break;
343                     }
344                     case GRAY_FLOAT: {
345                         imageType = BufferedImage.TYPE_INT_RGB;
346                         buffer.order(order);
347                         FloatBuffer fbuffer = buffer.asFloatBuffer();
348                         ibuffer = new int[fbuffer.capacity()];
349                         for (int i = 0; i < fbuffer.capacity(); i++) {
350                             final int c = toColorComp(fbuffer.get(i));
351                             ibuffer[i] = (c << 16) | (c << 8) | c;
352                         }
353                         break;
354                     }
355                     case RED_16: {
356                         imageType = BufferedImage.TYPE_INT_RGB;
357                         ibuffer = new int[buffer.capacity() / 2];
358                         int k = 0;
359                         if (order == ByteOrder.LITTLE_ENDIAN) {
360                             for (int i = 0; i < buffer.capacity(); i += 2) {
361                                 final int c = (((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i) & 0xFF)) / 257;
362                                 ibuffer[k++] = c << 16;
363                             }
364                         } else {
365                             for (int i = 0; i < buffer.capacity(); i += 2) {
366                                 final int c = (((buffer.get(i) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF)) / 257;
367                                 ibuffer[k++] = c << 16;
368                             }
369                         }
370                         break;
371                     }
372                     case GREEN_16: {
373                         imageType = BufferedImage.TYPE_INT_RGB;
374                         ibuffer = new int[buffer.capacity() / 2];
375                         int k = 0;
376                         if (order == ByteOrder.LITTLE_ENDIAN) {
377                             for (int i = 0; i < buffer.capacity(); i += 2) {
378                                 final int c = (((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i) & 0xFF)) / 257;
379                                 ibuffer[k++] = c << 8;
380                             }
381                         } else {
382                             for (int i = 0; i < buffer.capacity(); i += 2) {
383                                 final int c = (((buffer.get(i) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF)) / 257;
384                                 ibuffer[k++] = c << 8;
385                             }
386                         }
387                         break;
388                     }
389                     case BLUE_16: {
390                         imageType = BufferedImage.TYPE_INT_RGB;
391                         ibuffer = new int[buffer.capacity() / 2];
392                         int k = 0;
393                         if (order == ByteOrder.LITTLE_ENDIAN) {
394                             for (int i = 0; i < buffer.capacity(); i += 2) {
395                                 final int c = (((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i) & 0xFF)) / 257;
396                                 ibuffer[k++] = c;
397                             }
398                         } else {
399                             for (int i = 0; i < buffer.capacity(); i += 2) {
400                                 final int c = (((buffer.get(i) & 0xFF) << 8) | (buffer.get(i + 1) & 0xFF)) / 257;
401                                 ibuffer[k++] = c;
402                             }
403                         }
404                         break;
405                     }
406                     case RED_FLOAT: {
407                         imageType = BufferedImage.TYPE_INT_RGB;
408                         buffer.order(order);
409                         FloatBuffer fbuffer = buffer.asFloatBuffer();
410                         ibuffer = new int[fbuffer.capacity()];
411                         for (int i = 0; i < fbuffer.capacity(); i++) {
412                             ibuffer[i] = toColorComp(fbuffer.get(i)) << 16;
413                         }
414                         break;
415                     }
416                     case GREEN_FLOAT: {
417                         imageType = BufferedImage.TYPE_INT_RGB;
418                         buffer.order(order);
419                         FloatBuffer fbuffer = buffer.asFloatBuffer();
420                         ibuffer = new int[fbuffer.capacity()];
421                         for (int i = 0; i < fbuffer.capacity(); i++) {
422                             ibuffer[i] = toColorComp(fbuffer.get(i)) << 8;
423                         }
424                         break;
425                     }
426                     case BLUE_FLOAT: {
427                         imageType = BufferedImage.TYPE_INT_RGB;
428                         buffer.order(order);
429                         FloatBuffer fbuffer = buffer.asFloatBuffer();
430                         ibuffer = new int[fbuffer.capacity()];
431                         for (int i = 0; i < fbuffer.capacity(); i++) {
432                             ibuffer[i] = toColorComp(fbuffer.get(i));
433                         }
434                         break;
435                     }
436                     case RGBA_BYTE: {
437                         imageType = BufferedImage.TYPE_INT_ARGB;
438                         ibuffer = new int[buffer.capacity() / 4];
439                         int k = 0;
440                         for (int i = 0; i < buffer.capacity(); i += 4) {
441                             ibuffer[k++] = ((buffer.get(i + 3) & 0xFF) << 24) | ((buffer.get(i) & 0xFF) << 16) | ((buffer.get(i + 1) & 0xFF) << 8) | (buffer.get(i + 2) & 0xFF);
442                         }
443                         break;
444                     }
445                 }
446
447                 ImageBuffer ib1;
448                 if (getDataProvider().isRowMajorOrder()) {
449                     ib1 = new ImageBuffer(imageType, ibuffer, (int) textureSize.getWidth(), (int) textureSize.getHeight());
450                 } else {
451                     int[] tibuffer = new int[ibuffer.length];
452                     final int w = (int) textureSize.getWidth();
453                     final int h = (int) textureSize.getHeight();
454                     int k = 0;
455                     for (int i = 0; i < h; i++) {
456                         for (int j = 0; j < w; j++) {
457                             tibuffer[k++] = ibuffer[i + j * h];
458                         }
459                     }
460                     ib1 = new ImageBuffer(imageType, tibuffer, w, h);
461                 }
462
463                 ImageBuffer ib2 = images.get(ib1);
464                 if (ib2 == null) {
465                     images.put(ib1, ib1);
466                     ib2 = ib1;
467                 }
468
469                 image = ib2;
470             }
471
472             return image.getImage();
473         }
474     }
475
476     private static class ImageBuffer {
477
478         private int[] buffer;
479         private int hash;
480         private int width;
481         private int height;
482         private BufferedImage image;
483         private int type;
484
485         ImageBuffer(int type, int[] buffer, int width, int height) {
486             this.type = type;
487             this.buffer = buffer;
488             this.hash = Arrays.hashCode(buffer) * 31 + type;
489             this.width = width;
490             this.height = height;
491         }
492
493         BufferedImage getImage() {
494             if (image == null) {
495                 image = new BufferedImage(width, height, type);
496                 image.setRGB(0, 0, width, height, buffer, 0, width);
497             }
498
499             return image;
500         }
501
502         @Override
503         public int hashCode() {
504             return hash;
505         }
506
507         @Override
508         public boolean equals(Object o) {
509             if (o instanceof ImageBuffer) {
510                 ImageBuffer mfb = (ImageBuffer) o;
511                 return type == mfb.type && Arrays.equals(buffer, mfb.buffer);
512             }
513             return false;
514         }
515     }
516 }