This algorithm will produce a texture, given an image.
the result will both be in texImage, as well as in a textureCompatible buffer, which can be fed to glTexSubImage2D, glTexImage2D or gluBuild2DMipmaps
Basically, for any given image I, it will generate an ARGB image Y, which is a scaled ARGB version (to the nearest power of 2) of I. Testing shows it is about 16 times faster than a similar graphics.drawImage() scaling operation, even with all "dd" performance flags set on the VM. It uses fixed point arithmetics to achieve maximum speed.
I needed this because I was rendering video to a texture, and the java library algorithms were too slow.
in case you are wondering what the fastest way to update a texture in gl is, it is glTexSubImage2D, and you can use it as such, in combination with the algorithm:
1
| gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, textureCompatibleBuffer); |
anyway, I hope it is usefull to you, and if you find other optimizations I haven't thought of, share it with us here, please

you will need the "get2fold" algorithm, as mentioned in this post:
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=share;action=display;num=11171869071 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| private BufferedImage image; private WritableRaster raster; private BufferedImage texImage; private byte[] iBuffer; private byte[] tBuffer; private ByteBuffer textureCompatibleBuffer; private int[] bankOffsets; private int textureWidth = -1; private int textureHeight = -1; private int xScaleUnit; private int yScaleUnit; private ComponentSampleModel imageSampleModel; private int scanLineStride; private int pixelStride;
public static final ColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8,8,8,8}, true, false, ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
if(raster == null) { textureWidth = get2Fold(image.getWidth()); textureHeight = get2Fold(image.getHeight()); raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,this.textureWidth,this.textureHeight,4,null); texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable()); iBuffer = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); tBuffer= ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData(); ComponentSampleModel imageSampleModel = (ComponentSampleModel) image.getSampleModel(); scanLineStride = imageSampleModel.getScanlineStride(); pixelStride = imageSampleModel.getPixelStride(); bankOffsets = imageSampleModel.getBandOffsets(); xScaleUnit = (int) (((double) image.getWidth() / (double) textureWidth) * 65536); yScaleUnit = (int) (((double) image.getHeight() / (double) textureHeight) * 65536); textureCompatibleBuffer = ByteBuffer.allocateDirect(tBuffer.length); textureCompatibleBuffer.order(ByteOrder.nativeOrder()); }
int adr = 0; int xOffset = 0; int bufferOffset = 0; int yOffset = 0; int yBufferOffset = 0; if(bankOffsets.length > 3) { for(int y=0; y<textureHeight; y++) { xOffset = 0;
yBufferOffset = (yOffset >> 16) * scanLineStride; for(int x=0; x<textureWidth; x++) { bufferOffset = yBufferOffset + (xOffset >> 16) * pixelStride;
tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[0]]; tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[1]]; tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[2]]; tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[3]]; xOffset += xScaleUnit; } yOffset += yScaleUnit; } } else { for(int y=0; y<textureHeight; y++) { xOffset = 0;
yBufferOffset = (yOffset >> 16) * scanLineStride; for(int x=0; x<textureWidth; x++) { bufferOffset = yBufferOffset + (xOffset >> 16) * pixelStride;
tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[0]]; tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[1]]; tBuffer[adr++] = iBuffer[bufferOffset + bankOffsets[2]]; tBuffer[adr++] = -1; xOffset += xScaleUnit; } yOffset += yScaleUnit; } } textureCompatibleBuffer.rewind(); textureCompatibleBuffer.put(tBuffer, 0, tBuffer.length);
|