public static ByteBuffer flipDXT(ByteBuffer img, int w, int h, Format format) {
        if (format == Format.ETC1 || format == Format.ETC2 || format == Format.ETC2_ALPHA1) {
            logger.warning("This is not a DXT format, but ETC. Use flipETC instead.");
            return ETCFlipper.flipETC(img, w, h, format);
        }
        int originalLimit = img.limit();
        int blocksX = (int) FastMath.ceil(w / 4f);
        int blocksY = (int) FastMath.ceil(h / 4f);

        int type;
        switch (format){
            case DXT1:
            case DXT1A:
                type = 1;
                break;
            case DXT3:
                type = 2;
                break;
            case DXT5:
                type = 3;
                break;
            case RGTC2:
            case SIGNED_RGTC2:
                type = 4;
                break;                
            case RGTC1:
            case SIGNED_RGTC1:
                type = 5;
                break;
            default:
                throw new IllegalArgumentException("No flip support for texture format " + format);
        }

        // DXT1 uses 8 bytes per block,
        // DXT3, DXT5, LATC use 16 bytes per block
        int bpb = type == 1 || type == 5 ? 8 : 16;

        ByteBuffer retImg = BufferUtils.createByteBuffer(blocksX * blocksY * bpb);
        if (h == 1){
            retImg.put(img);
            retImg.rewind();
        }else if (h == 2){
            byte[] colorBlock = new byte[8];
            byte[] alphaBlock = type != 1 && type != 5 ? new byte[8] : null;
            for (int x = 0; x < blocksX; x++){
                // prepare for block reading
                int blockByteOffset = x * bpb;
                img.position(blockByteOffset);
                img.limit(blockByteOffset + bpb);

                if (alphaBlock != null){
                    img.get(alphaBlock);
                    switch (type){
                        case 2:
                            flipDXT3Block(alphaBlock, h); 
                            break;
                        case 3:
                        case 4: 
                            flipDXT5Block(alphaBlock, h);
                            break;
                    }
                    retImg.put(alphaBlock);
                }
                
                img.get(colorBlock);
                if (type == 4 || type == 5)
                    flipDXT5Block(colorBlock, h);
                else
                    flipDXT1orDXTA3Block(colorBlock, h);

                // write block (no need to flip block indexes, only pixels
                // inside block
                retImg.put(colorBlock);
            }
            retImg.rewind();
        }else if (h >= 4){
            byte[] colorBlock = new byte[8];
            byte[] alphaBlock = type != 1 && type != 5 ? new byte[8] : null;
            for (int y = 0; y < blocksY; y++){
                for (int x = 0; x < blocksX; x++){
                    // prepare for block reading
                    int blockIdx = y * blocksX + x;
                    int blockByteOffset = blockIdx * bpb;

                    img.position(blockByteOffset);
                    img.limit(blockByteOffset + bpb);

                    blockIdx = (blocksY - y - 1) * blocksX + x;
                    blockByteOffset = blockIdx * bpb;

                    retImg.position(blockByteOffset);
                    retImg.limit(blockByteOffset + bpb);

                    if (alphaBlock != null){
                        img.get(alphaBlock);
                        switch (type){
                            case 2:
                                flipDXT3Block(alphaBlock, h);
                                break;
                            case 3:
                            case 4:
                                flipDXT5Block(alphaBlock, h);
                                break;
                        }
                        retImg.put(alphaBlock);
                    }

                    img.get(colorBlock);
                    if (type == 4 || type == 5)
                        flipDXT5Block(colorBlock, h);
                    else
                        flipDXT1orDXTA3Block(colorBlock, h);
                    
                    retImg.put(colorBlock);
                }
            }
            retImg.limit(retImg.capacity());
            retImg.position(0);
        } else {
            return null;
        }
        img.limit(originalLimit); // make sure to restore original limit.
        return retImg;
    }
Flips a DXT color block or a DXT3 alpha block
@param block
@param h
jme3-core/src/plugins/java/com/jme3/texture/plugins/DXTFlipper.java