From 4cda4b70dbcd21cf57e1e253ddba32b88bcaec18 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Tue, 8 Feb 2011 06:20:35 +0100
Subject: Move implementation private files from com.jogamp.<module>.impl. to
 jogamp.<module> (1/2) - rename task

- com.jogamp.opengl.impl                     -> jogamp.opengl
- com.jogamp.opengl.util.glsl.fixedfunc.impl -> jogamp.opengl.util.glsl.fixedfunc
- com.jogamp.nativewindow.impl               -> jogamp.nativewindow
- com.jogamp.newt.impl                       -> jogamp.newt

This sorts implementation details from the top level, ie skipping the public 'com',
allowing a better seperation of public classes and implementation details
and also reduces strings.

This approach of public/private seperation is also used in the OpenJDK.
---
 .../jogamp/opengl/glu/mipmap/BuildMipmap.java      | 1597 +++++++++++++
 .../classes/jogamp/opengl/glu/mipmap/Extract.java  |   56 +
 .../jogamp/opengl/glu/mipmap/Extract1010102.java   |   97 +
 .../jogamp/opengl/glu/mipmap/Extract1555rev.java   |   97 +
 .../opengl/glu/mipmap/Extract2101010rev.java       |   97 +
 .../jogamp/opengl/glu/mipmap/Extract233rev.java    |   85 +
 .../jogamp/opengl/glu/mipmap/Extract332.java       |   84 +
 .../jogamp/opengl/glu/mipmap/Extract4444.java      |   96 +
 .../jogamp/opengl/glu/mipmap/Extract4444rev.java   |   97 +
 .../jogamp/opengl/glu/mipmap/Extract5551.java      |   97 +
 .../jogamp/opengl/glu/mipmap/Extract565.java       |   92 +
 .../jogamp/opengl/glu/mipmap/Extract565rev.java    |   92 +
 .../jogamp/opengl/glu/mipmap/Extract8888.java      |   97 +
 .../jogamp/opengl/glu/mipmap/Extract8888rev.java   |   97 +
 .../jogamp/opengl/glu/mipmap/ExtractFloat.java     |   74 +
 .../jogamp/opengl/glu/mipmap/ExtractPrimitive.java |   56 +
 .../jogamp/opengl/glu/mipmap/ExtractSByte.java     |   69 +
 .../jogamp/opengl/glu/mipmap/ExtractSInt.java      |   76 +
 .../jogamp/opengl/glu/mipmap/ExtractSShort.java    |   76 +
 .../jogamp/opengl/glu/mipmap/ExtractUByte.java     |   70 +
 .../jogamp/opengl/glu/mipmap/ExtractUInt.java      |   76 +
 .../jogamp/opengl/glu/mipmap/ExtractUShort.java    |   76 +
 .../jogamp/opengl/glu/mipmap/HalveImage.java       | 1533 ++++++++++++
 .../classes/jogamp/opengl/glu/mipmap/Image.java    | 1413 +++++++++++
 .../classes/jogamp/opengl/glu/mipmap/Mipmap.java   |  868 +++++++
 .../opengl/glu/mipmap/PixelStorageModes.java       |  426 ++++
 .../jogamp/opengl/glu/mipmap/ScaleInternal.java    | 2447 ++++++++++++++++++++
 .../jogamp/opengl/glu/mipmap/Type_Widget.java      |  226 ++
 28 files changed, 10267 insertions(+)
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
 create mode 100644 src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java

(limited to 'src/jogl/classes/jogamp/opengl/glu/mipmap')

diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
new file mode 100644
index 000000000..42f55f982
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
@@ -0,0 +1,1597 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.glu.GLU;
+import com.jogamp.opengl.impl.Debug;
+import com.jogamp.common.nio.Buffers;
+import java.nio.*;
+import java.io.*;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class BuildMipmap {
+
+  private static final boolean DEBUG = Debug.debug("BuildMipmap");
+  private static final boolean VERBOSE = Debug.verbose();
+
+  /** Creates a new instance of BuildMipmap */
+  public BuildMipmap() {
+  }
+  
+  public static int gluBuild1DMipmapLevelsCore( GL gl, int target, int internalFormat,
+                  int width, int widthPowerOf2, int format, int type, int userLevel,
+                  int baseLevel, int maxLevel, ByteBuffer data ) {
+    int newwidth;
+    int level, levels;
+    ShortBuffer newImage = null;
+    int newImage_width;
+    ShortBuffer otherImage = null;
+    ShortBuffer imageTemp = null;
+    int memReq;
+    int maxsize;
+    int cmpts;
+    PixelStorageModes psm = new PixelStorageModes();
+    
+    assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
+    assert( width >= 1 );
+    
+    newwidth = widthPowerOf2;
+    levels = Mipmap.computeLog( newwidth );
+    
+    levels += userLevel;
+    
+    Mipmap.retrieveStoreModes( gl, psm );
+    try {
+      newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, 1, format, 
+            GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+    } catch( OutOfMemoryError ome ) {
+      return( GLU.GLU_OUT_OF_MEMORY );
+    }
+    newImage_width = width;
+    
+    Image.fill_image( psm, width, 1, format, type, Mipmap.is_index( format ), data, newImage );
+    cmpts = Mipmap.elements_per_group( format, type );
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
+    
+    // if swap_bytes was set, swapping occurred in fill_image
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+    
+    for( level = userLevel; level <= levels; level++ ) {
+      if( newImage_width == newwidth ) {
+        // user newimage for this level
+        if( baseLevel <= level && level <= maxLevel ) {
+          gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, format,
+                        GL2.GL_UNSIGNED_SHORT, newImage );
+        }
+      } else {
+        if( otherImage == null ) {
+          memReq = Mipmap.image_size( newwidth, 1, format, GL2.GL_UNSIGNED_SHORT );
+          try {
+            otherImage = Buffers.newDirectByteBuffer( memReq ).asShortBuffer();
+          } catch( OutOfMemoryError ome ) {
+            gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+            gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+            return( GLU.GLU_OUT_OF_MEMORY );
+          }
+        }
+        ScaleInternal.scale_internal( cmpts, newImage_width, 1, newImage, newwidth, 1, otherImage );
+        // swap newImage and otherImage
+        imageTemp = otherImage;
+        otherImage = newImage;
+        newImage = imageTemp;
+        
+        newImage_width = newwidth;
+        if( baseLevel <= level && level <= maxLevel ) {
+          gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, 
+                            format, GL2.GL_UNSIGNED_SHORT, newImage );
+        }
+      }
+      if( newwidth > 1 ) {
+        newwidth /= 2;
+      }
+    }
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+    
+    return( 0 );
+  }
+  
+  public static int bitmapBuild2DMipmaps( GL gl, int target, int internalFormat,
+            int width, int height, int format, int type, ByteBuffer data ) {
+    int newwidth[] = new int[1];
+    int newheight[] = new int[1];
+    int level, levels;
+    ShortBuffer newImage = null;
+    int newImage_width;
+    int newImage_height;
+    ShortBuffer otherImage = null;
+    ShortBuffer tempImage = null;
+    int memReq;
+    int maxsize;
+    int cmpts;
+    PixelStorageModes psm = new PixelStorageModes();
+    
+    Mipmap.retrieveStoreModes( gl, psm );
+    
+    Mipmap.closestFit( gl, target, width, height, internalFormat, format, type, newwidth, newheight );
+    
+    levels = Mipmap.computeLog( newwidth[0] );
+    level = Mipmap.computeLog( newheight[0] );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    try {
+      newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, height, 
+            format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+    } catch( OutOfMemoryError ome ) {
+      return( GLU.GLU_OUT_OF_MEMORY );
+    }
+    newImage_width = width;
+    newImage_height = height;
+    
+    Image.fill_image( psm, width, height, format, type, Mipmap.is_index( format ), data, newImage );
+    
+    cmpts = Mipmap.elements_per_group( format, type );
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
+    
+    // if swap_bytes is set, swapping occurred in fill_image
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+    
+    for( level = 0; level < levels; level++ ) {
+      if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
+        newImage.rewind();
+        gl.glTexImage2D( target, level, internalFormat, newImage_width,
+            newImage_height, 0, format, GL2.GL_UNSIGNED_SHORT, newImage );
+      } else {
+        if( otherImage == null ) {
+          memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_SHORT );
+          try {
+            otherImage = Buffers.newDirectByteBuffer( memReq ).asShortBuffer();
+          } catch( OutOfMemoryError ome ) {
+            gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+            gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+            return( GLU.GLU_OUT_OF_MEMORY );
+          }
+        }
+        ScaleInternal.scale_internal( cmpts, newImage_width, newImage_height, 
+                              newImage, newwidth[0], newheight[0], otherImage );
+        // swap newImage and otherImage
+        tempImage = otherImage;
+        otherImage = newImage;
+        newImage = tempImage;
+        
+        newImage_width = newwidth[0];
+        newImage_height = newheight[0];
+        newImage.rewind();
+        gl.glTexImage2D( target, level, internalFormat, newImage_width, newImage_height,
+                                    0, format, GL2.GL_UNSIGNED_SHORT, newImage );
+      }
+      if( newheight[0] > 1 ) {
+        newwidth[0] /= 2;
+      }
+      if( newheight[0] > 1 ) {
+        newheight[0] /= 2;
+      }
+    }
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+    
+    return( 0 );
+  }
+  
+  public static int gluBuild2DMipmapLevelsCore( GL gl, int target, int internalFormat,
+                int width, int height, int widthPowerOf2, int heightPowerOf2,
+                int format, int type, int userLevel, int baseLevel, int maxLevel,
+                ByteBuffer data ) { // PointerWrapper data
+    int newwidth;
+    int newheight;
+    int level, levels;
+    int usersImage;
+    ByteBuffer srcImage = null;
+    ByteBuffer dstImage = null;
+    ByteBuffer tempImage = null;
+    int newImage_width;
+    int newImage_height;
+    short[] SWAP_IMAGE = null;
+    int memReq;
+    int maxsize;
+    int cmpts;
+    int mark=-1;
+    
+    boolean myswap_bytes;
+    int groups_per_line, element_size, group_size;
+    int rowsize, padding;
+    PixelStorageModes psm = new PixelStorageModes();
+    
+    assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
+    assert( width >= 1 && height >= 1 );
+    
+    if( type == GL2.GL_BITMAP ) {
+      return( bitmapBuild2DMipmaps( gl, target, internalFormat, width, height, format, type, data ) );
+    }
+    
+    newwidth = widthPowerOf2;
+    newheight = heightPowerOf2;
+    levels = Mipmap.computeLog( newwidth );
+    level = Mipmap.computeLog( newheight );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    levels += userLevel;
+    
+    Mipmap.retrieveStoreModes( gl, psm );
+    myswap_bytes = psm.getUnpackSwapBytes();
+    cmpts = Mipmap.elements_per_group( format, type );
+    if( psm.getUnpackRowLength() > 0 ) {
+      groups_per_line = psm.getUnpackRowLength();
+    } else {
+      groups_per_line = width;
+    }
+    
+    element_size = Mipmap.bytes_per_element( type );
+    group_size = element_size * cmpts;
+    if( element_size == 1 ) {
+      myswap_bytes = false;
+    }
+    
+    rowsize = groups_per_line * group_size;
+    padding = ( rowsize % psm.getUnpackAlignment() );
+    if( padding != 0 ) {
+      rowsize += psm.getUnpackAlignment() - padding;
+    }
+    
+    mark = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size;
+    data.position( mark );
+    
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
+    
+    level = userLevel;
+    
+    // already power of two square
+    if( width == newwidth && height == newheight ) {
+      // use usersImage for level userLevel
+      if( baseLevel <= level && level <= maxLevel ) {
+        data.rewind();
+        gl.glTexImage2D( target, level, internalFormat, width, height, 0, format, type, data );
+      }
+      if( levels == 0 ) { /* we're done. clean up and return */
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+        return( 0 );
+      }
+      int nextWidth = newwidth / 2;
+      int nextHeight = newheight / 2;
+      
+      // clamp to 1
+      if( nextWidth < 1 ) {
+        nextWidth = 1;
+      }
+      if( nextHeight < 1 ) {
+        nextHeight = 1;
+      }
+      memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
+      
+      try {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError ome ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      if( dstImage != null ) {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+            HalveImage.halveImage_ubyte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size );
+            break;
+          case( GL2.GL_BYTE ):
+            HalveImage.halveImage_byte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT ):
+            HalveImage.halveImage_ushort( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+            break;
+          case( GL2.GL_SHORT ):
+            HalveImage.halveImage_short( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT ):
+            HalveImage.halveImage_uint( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+            break;
+          case( GL2.GL_INT ):
+            HalveImage.halveImage_int( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+            break;
+          case( GL2.GL_FLOAT ):
+            HalveImage.halveImage_float( cmpts, width, height, data, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+            assert( format == GL2.GL_RGB );
+            HalveImage.halveImagePackedPixel( 3, new Extract332(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+            assert( format == GL2.GL_RGB );
+            HalveImage.halveImagePackedPixel( 3, new Extract233rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+            HalveImage.halveImagePackedPixel( 3, new Extract565(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+            HalveImage.halveImagePackedPixel( 3, new Extract565rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+            HalveImage.halveImagePackedPixel( 4, new Extract4444(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+            HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+            HalveImage.halveImagePackedPixel( 4, new Extract5551(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+            HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+            HalveImage.halveImagePackedPixel( 4, new Extract8888(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+            HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+            HalveImage.halveImagePackedPixel( 4, new Extract1010102(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+          default:
+            assert( false );
+            break;
+        }
+      }
+      newwidth = width / 2;
+      newheight = height / 2;
+      // clamp to 1
+      if( newwidth < 1 ) {
+        newwidth = 1;
+      }
+      if( newheight < 1 ) {
+        newheight = 1;
+      }
+      
+      myswap_bytes = false;
+      rowsize = newwidth * group_size;
+      memReq = Mipmap.image_size( newwidth, newheight, format, type );
+      // swap srcImage and dstImage
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      try {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError ome ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      // level userLevel+1 is in srcImage; level userLevel already saved
+      level = userLevel + 1;
+    } else { // user's image is not nice powerof2 size square
+      memReq = Mipmap.image_size( newwidth, newheight, format, type );
+      try { 
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError ome ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      data.position( mark );
+      switch( type ) {
+        case( GL2.GL_UNSIGNED_BYTE ):
+          ScaleInternal.scale_internal_ubyte( cmpts, width, height, data, 
+                newwidth, newheight, dstImage, element_size, rowsize, group_size );
+          break;
+        case( GL2.GL_BYTE ):
+          ScaleInternal.scale_internal_byte( cmpts, width, height, data, newwidth, 
+                  newheight, dstImage, element_size, rowsize, group_size );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT ):
+          ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth, 
+                  newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_SHORT ):
+          ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth,
+                  newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT ):
+          ScaleInternal.scale_internal_uint( cmpts, width, height, data, newwidth,
+                  newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_INT ):
+          ScaleInternal.scale_internal_int( cmpts, width, height, data, newwidth,
+                  newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_FLOAT ):
+          ScaleInternal.scale_internal_float( cmpts, width, height, data, newwidth,
+                  newheight, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          ScaleInternal.scaleInternalPackedPixel( 3, new Extract332(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 3, new Extract233rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          ScaleInternal.scaleInternalPackedPixel( 3, new Extract565(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 3, new Extract565rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract5551(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract1555rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract1010102(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+          ScaleInternal.scaleInternalPackedPixel( 4, new Extract2101010rev(), width, height, data, newwidth,
+              newheight, dstImage, element_size, rowsize, myswap_bytes );
+          break;
+        default:
+          assert( false );
+          break;
+      }
+      myswap_bytes = false;
+      rowsize = newwidth * group_size;
+      // swap dstImage and srcImage
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      
+      if( levels != 0 ) { // use as little memory as possible
+        int nextWidth = newwidth / 2;
+        int nextHeight = newheight / 2;
+        if( nextWidth < 1 ) {
+          nextWidth = 1;
+        }
+        if( nextHeight < 1 ) {
+          nextHeight = 1;
+        }
+        
+        memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
+        try {
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE ):
+            case( GL2.GL_BYTE ):
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_INT ):
+            case( GL2.GL_FLOAT ):
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              dstImage = Buffers.newDirectByteBuffer( memReq );
+              break;
+            default:
+              return( GLU.GLU_INVALID_ENUM );
+          }
+        } catch( OutOfMemoryError ome ) {
+          gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+          gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+          return( GLU.GLU_OUT_OF_MEMORY );
+        }
+      }
+      // level userLevel is in srcImage; nothing saved yet
+      level = userLevel;
+    }
+    
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+    if( baseLevel <= level && level <= maxLevel ) {
+      srcImage.rewind();
+      gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
+      if (DEBUG) {
+        System.err.println("GL Error(" + level + "): " + gl.glGetError() );
+        if (VERBOSE) {
+          srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+          writeTargaFile("glu2DMipmapJ" + level + ".tga",
+                         srcImage, newwidth, newheight);
+          srcImage.clear();
+        }
+      }
+    }
+    
+    level++;  // update current level for the loop
+    for( ; level <= levels; level++ ) {
+      srcImage.rewind();
+      dstImage.rewind();
+      switch( type ) {
+        case( GL2.GL_UNSIGNED_BYTE ):
+          HalveImage.halveImage_ubyte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size );
+          break;
+        case( GL2.GL_BYTE ):
+          HalveImage.halveImage_byte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT ):
+          HalveImage.halveImage_ushort( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_SHORT ):
+          HalveImage.halveImage_short( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT ):
+          HalveImage.halveImage_uint( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_INT ):
+          HalveImage.halveImage_int( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_FLOAT ):
+          HalveImage.halveImage_float( cmpts, newwidth, newheight, srcImage, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes );
+          break;
+        case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          assert( format == GL2.GL_RGB );
+          HalveImage.halveImagePackedPixel( 3, new Extract332(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          assert( format == GL2.GL_RGB );
+          HalveImage.halveImagePackedPixel( 3, new Extract233rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          HalveImage.halveImagePackedPixel( 3, new Extract565(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          HalveImage.halveImagePackedPixel( 3, new Extract565rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          HalveImage.halveImagePackedPixel( 4, new Extract4444(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          HalveImage.halveImagePackedPixel( 4, new Extract5551(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          HalveImage.halveImagePackedPixel( 4, new Extract8888(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          HalveImage.halveImagePackedPixel( 4, new Extract1010102(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+          HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes );
+            break;
+        default:
+          assert( false );
+          break;
+      }
+      
+      // swap dstImage and srcImage
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      
+      if( newwidth > 1 ) {
+        newwidth /= 2;
+        rowsize /= 2;
+      }
+      if( newheight > 1 ) {
+        newheight /= 2;
+      }
+      // compute amount to pad per row if any
+      int rowPad = rowsize % psm.getUnpackAlignment();
+      
+      // should row be padded
+      if( rowPad == 0 ) {
+        // call teximage with srcImage untouched since its not padded
+        if( baseLevel <= level && level <= maxLevel ) {
+          srcImage.rewind();
+          gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
+          if (DEBUG) {
+            System.err.println("GL Error(" + level + "): " + gl.glGetError() );
+            if (VERBOSE) {
+              srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+              writeTargaFile("glu2DMipmapJ" + level + ".tga",
+                             srcImage, newwidth, newheight);
+              srcImage.clear();
+            }
+          }
+        }
+      } else {
+        // compute length of new row in bytes, including padding
+        int newRowLength = rowsize + psm.getUnpackAlignment() - rowPad;
+        int ii, jj;
+        int dstTrav;
+        int srcTrav;
+        
+        // allocate new image for mipmap of size newRowLength x newheight
+        ByteBuffer newMipmapImage = null;
+        try {
+          newMipmapImage = ByteBuffer.allocateDirect( newRowLength * newheight );
+        } catch( OutOfMemoryError ome ) {
+          gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+          gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+          return( GLU.GLU_OUT_OF_MEMORY );
+        }
+        srcImage.rewind();
+        // copy image from srcImage into newMipmapImage by rows
+        for( ii = 0; ii < newheight; ii++ ) {
+          newMipmapImage.position(newRowLength * ii);
+          for( jj = 0; jj < rowsize; jj++ ) {
+            newMipmapImage.put( srcImage.get() );
+          }
+        }
+        
+        // and use this new image for mipmapping instead
+        if( baseLevel <= level && level <= maxLevel ) {
+          newMipmapImage.rewind();
+          gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, newMipmapImage );
+          if (DEBUG) {
+            System.err.println("GL Error(" + level + " padded): " + gl.glGetError() );
+            if (VERBOSE) {
+              writeTargaFile("glu2DMipmapJ" + level + ".tga",
+                             newMipmapImage, newwidth, newheight);
+            }
+          }
+        }
+      }
+    }
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) );
+    
+    return( 0 );
+  }
+  
+  public static int fastBuild2DMipmaps( GL gl, PixelStorageModes psm, int target,
+          int components, int width, int height, int format, int type, ByteBuffer data ) {
+    int[] newwidth = new int[1];
+    int[] newheight = new int[1];
+    int level, levels;
+    ByteBuffer newImage;
+    int newImage_width;
+    int newImage_height;
+    ByteBuffer otherImage;
+    ByteBuffer imageTemp;
+    int memReq;
+    int maxsize;
+    int cmpts;
+    
+    Mipmap.closestFit( gl, target, width, height, components, format, type, newwidth, 
+            newheight );
+    
+    levels = Mipmap.computeLog( newwidth[0] );
+    level = Mipmap.computeLog( newheight[0] );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    cmpts = Mipmap.elements_per_group( format, type );
+    
+    otherImage = null;
+    //  No need to copy the user data if its packed correctly.
+    //  Make sure that later routines don't change that data.
+    
+    if( psm.getUnpackSkipRows() == 0 && psm.getUnpackSkipPixels() == 0 ) {
+      newImage = data;
+      newImage_width = width;
+      newImage_height = height;
+    } else {
+      int rowsize;
+      int group_per_line;
+      int elements_per_line;
+      int start;
+      int iter;
+      int iter2;
+      int i, j;
+      
+      try {
+        newImage = Buffers.newDirectByteBuffer( Mipmap.image_size(width, height, format, GL2.GL_UNSIGNED_BYTE ) );
+      } catch( OutOfMemoryError err ) {
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      newImage_width = width;
+      newImage_height = height;
+
+      // Abbreviated version of fill_image for the restricted case.
+      if( psm.getUnpackRowLength() > 0 ) {
+        group_per_line = psm.getUnpackRowLength();
+      } else {
+        group_per_line = width;
+      }
+      rowsize = group_per_line * cmpts;
+      elements_per_line = width * cmpts;
+      start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * cmpts;
+      
+      for( i = 0; i < height; i++ ) {
+        iter = start;
+        data.position( iter );
+        for( j = 0; j < elements_per_line; j++ ) {
+          newImage.put( data.get() );
+        }
+        start += rowsize;
+      }
+    }
+    
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 1 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+    
+    for( level = 0; level <= levels; level++ ) {
+      if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
+        // use newImage for this level
+        newImage.rewind();
+        gl.glTexImage2D( target, level, components, newImage_width, newImage_height,
+                0, format, GL2.GL_UNSIGNED_BYTE, newImage );
+      } else {
+        if( otherImage == null ) {
+          memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_BYTE );
+          try {
+            otherImage = Buffers.newDirectByteBuffer( memReq );
+          } catch( OutOfMemoryError err ) {
+            gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+            gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+            gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
+            return( GLU.GLU_OUT_OF_MEMORY );
+          }
+        }
+        // swap newImage and otherImage
+        imageTemp = otherImage;
+        otherImage = newImage;
+        newImage = imageTemp;
+        
+        newImage_width = newwidth[0];
+        newImage_height = newheight[0];
+        newImage.rewind();
+        gl.glTexImage2D( target, level, components, newImage_width, newImage_height,
+                0, format, GL2.GL_UNSIGNED_BYTE, newImage );
+      }
+      if( newwidth[0] > 1 ) {
+        newwidth[0] /= 2;
+      }
+      if( newheight[0] > 1 ) {
+        newheight[0] /= 2;
+      }
+    }
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ;
+    
+    return( 0 );
+  }
+  
+  public static int gluBuild3DMipmapLevelsCore( GL gl, int target, int internalFormat,
+          int width, int height, int depth, int widthPowerOf2, int heightPowerOf2,
+          int depthPowerOf2, int format, int type, int userLevel, int baseLevel,
+          int maxLevel, ByteBuffer data ) {
+    int newWidth;
+    int newHeight;
+    int newDepth;
+    int level, levels;
+    ByteBuffer usersImage;
+    ByteBuffer srcImage, dstImage, tempImage;
+    int newImageWidth;
+    int newImageHeight;
+    int newImageDepth;
+    int memReq;
+    int maxSize;
+    int cmpts;
+    int mark=-1;
+    
+    boolean myswapBytes;
+    int groupsPerLine, elementSize, groupSize;
+    int rowsPerImage, imageSize;
+    int rowSize, padding;
+    PixelStorageModes psm = new PixelStorageModes();
+    
+    assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 );
+    assert( width >= 1 && height >= 1 && depth >= 1 );
+    assert( type != GL2.GL_BITMAP );
+    
+    srcImage = dstImage = null;
+    
+    newWidth = widthPowerOf2;
+    newHeight = heightPowerOf2;
+    newDepth = depthPowerOf2;
+    levels = Mipmap.computeLog( newWidth );
+    level = Mipmap.computeLog( newHeight );
+    if( level > levels ) {
+      levels = level;
+    }
+    level = Mipmap.computeLog( newDepth );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    levels += userLevel;
+    
+    Mipmap.retrieveStoreModes3D( gl, psm );
+    myswapBytes = psm.getUnpackSwapBytes();
+    cmpts = Mipmap.elements_per_group( format, type );
+    if( psm.getUnpackRowLength() > 0 ) {
+      groupsPerLine = psm.getUnpackRowLength();
+    } else {
+      groupsPerLine = width;
+    }
+    
+    elementSize = Mipmap.bytes_per_element( type );
+    groupSize = elementSize * cmpts;
+    if( elementSize == 1 ) {
+      myswapBytes = false;
+    }
+    
+    // 3dstuff
+    if( psm.getUnpackImageHeight() > 0 ) {
+      rowsPerImage = psm.getUnpackImageHeight();
+    } else {
+      rowsPerImage = height;
+    }
+    
+    rowSize = groupsPerLine * groupSize;
+    padding = ( rowSize % psm.getUnpackAlignment() );
+    if( padding != 0 ) {
+      rowSize += psm.getUnpackAlignment() - padding;
+    }
+    
+    imageSize = rowsPerImage * rowSize;
+    
+    usersImage = ByteBuffer.wrap(data.array());
+    mark = psm.getUnpackSkipRows() * rowSize +
+           psm.getUnpackSkipPixels() * groupSize +
+           psm.getUnpackSkipImages() * imageSize;
+    usersImage.position( mark );
+    
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, 0 );
+    
+    level = userLevel;
+    
+    if( width == newWidth && height == newHeight && depth == newDepth ) {
+      // use usersImage for level userlevel
+      if( baseLevel <= level && level <= maxLevel ) {
+        gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth,
+                0, format, type, usersImage );
+      }
+      if( levels == 0 ) { /* we're done. clean up and return */
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+        gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+        return( 0 );
+      }
+      int nextWidth = newWidth / 2;
+      int nextHeight = newHeight / 2;
+      int nextDepth = newDepth / 2;
+      
+      // clamp to one
+      if( nextWidth < 1 ) {
+        nextWidth = 1;
+      }
+      if( nextHeight < 1 ) {
+        nextHeight = 1;
+      }
+      if( nextDepth < 1 ) {
+        nextDepth = 1;
+      }
+      memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type );
+      try {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError err ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+        gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      
+      if( dstImage != null ) {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth,
+                      usersImage, dstImage, elementSize, 
+                      groupSize, rowSize, imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_ubyte( cmpts, width, height, usersImage,
+                      dstImage, elementSize, rowSize, groupSize );
+            }
+            break;
+          case( GL2.GL_BYTE ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_byte( cmpts, width, height, usersImage,
+                      dstImage, elementSize, rowSize, groupSize );
+            }
+            break;
+          case( GL2.GL_UNSIGNED_SHORT ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_ushort( cmpts, width, height, usersImage, 
+                      dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+            }
+            break;
+          case( GL2.GL_SHORT ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_short( cmpts, width, height, usersImage,
+                      dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+            }
+            break;
+          case( GL2.GL_UNSIGNED_INT ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_uint( cmpts, width, height, usersImage,
+                      dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+            }
+            break;
+          case( GL2.GL_INT ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_int( cmpts, width, height, usersImage,
+                      dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+            }
+            break;
+          case( GL2.GL_FLOAT ):
+            if( depth > 1 ) {
+              HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth,
+                      usersImage, dstImage, elementSize, groupSize, rowSize,
+                      imageSize, myswapBytes );
+            } else {
+              HalveImage.halveImage_float( cmpts, width, height, usersImage,
+                      dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+            }
+            break;
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+            assert( format == GL2.GL_RGB );
+            HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+            assert( format == GL2.GL_RGB );
+            HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+            HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+            HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage,
+                    dstImage, elementSize, rowSize, imageSize, myswapBytes );
+            break;
+          default:
+            assert( false );
+            break;
+        }
+      }
+      newWidth = width / 2;
+      newHeight = height / 2;
+      newDepth = depth / 2;
+      // clamp to 1
+      if( newWidth < 1 ) {
+        newWidth = 1;
+      }
+      if( newHeight < 1 ) {
+        newHeight = 1;
+      }
+      if( newDepth < 1 ) {
+        newDepth = 1;
+      }
+      
+      myswapBytes = false;
+      rowSize = newWidth * groupSize;
+      imageSize = rowSize * newHeight;
+      memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type );
+      // swap srcImage and dstImage
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      try {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError err ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+        gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      
+      // level userLevel + 1 is in srcImage; level userLevel already saved
+      level = userLevel + 1;
+    } else {
+      memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type );
+      try {
+        switch( type ) {
+          case( GL2.GL_UNSIGNED_BYTE ):
+          case( GL2.GL_BYTE ):
+          case( GL2.GL_UNSIGNED_SHORT ):
+          case( GL2.GL_SHORT ):
+          case( GL2.GL_UNSIGNED_INT ):
+          case( GL2.GL_INT ):
+          case( GL2.GL_FLOAT ):
+          case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+            dstImage = Buffers.newDirectByteBuffer( memReq );
+            break;
+          default:
+            return( GLU.GLU_INVALID_ENUM );
+        }
+      } catch( OutOfMemoryError err ) {
+        gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+        gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+        gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+        gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+        gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+      
+      ScaleInternal.gluScaleImage3D( gl, format, width, height, depth, type,
+              usersImage, newWidth, newHeight, newDepth, type, dstImage );
+      
+      myswapBytes = false;
+      rowSize = newWidth * groupSize;
+      imageSize = rowSize * newHeight;
+      // swap dstImage and srcImage
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      
+      if( levels != 0 ) {
+        int nextWidth = newWidth / 2;
+        int nextHeight = newHeight / 2;
+        int nextDepth = newDepth / 2;
+        if( nextWidth < 1 ) {
+          nextWidth = 1;
+        }
+        if( nextHeight < 1 ) {
+          nextHeight = 1;
+        }
+        if( nextDepth < 1 ) {
+          nextDepth = 1;
+        }
+        memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type );
+        try {
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE ):
+            case( GL2.GL_BYTE ):
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_INT ):
+            case( GL2.GL_FLOAT ):
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              dstImage = Buffers.newDirectByteBuffer( memReq );
+              break;
+            default:
+              return( GLU.GLU_INVALID_ENUM );
+          }
+        } catch( OutOfMemoryError err ) {
+          gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+          gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+          gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+          gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+          gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+          return( GLU.GLU_OUT_OF_MEMORY );
+        }
+      }
+      // level userLevel is in srcImage; nothing saved yet
+      level = userLevel;
+    }
+    
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
+    if( baseLevel <= level && level <= maxLevel ) {
+      usersImage.position( mark );
+      gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth,
+              0, format, type, usersImage );
+    }
+    level++;
+    for( ; level <= levels; level++ ) {
+      switch( type ) {
+        case( GL2.GL_UNSIGNED_BYTE ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_ubyte( cmpts, width, height, usersImage,
+                    dstImage, elementSize, rowSize, groupSize );
+          }
+          break;
+        case( GL2.GL_BYTE ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_byte( cmpts, width, height, usersImage,
+                    dstImage, elementSize, rowSize, groupSize );
+          }
+          break;
+        case( GL2.GL_UNSIGNED_SHORT ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_ushort( cmpts, width, height, usersImage,
+                    dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+          }
+          break;
+        case( GL2.GL_SHORT ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_short( cmpts, width, height, usersImage,
+                    dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+          }
+          break;
+        case( GL2.GL_UNSIGNED_INT ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_uint( cmpts, width, height, usersImage,
+                    dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+          }
+          break;
+        case( GL2.GL_INT ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_int( cmpts, width, height, usersImage,
+                    dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+          }
+          break;
+        case( GL2.GL_FLOAT ):
+          if( depth > 1 ) {
+            HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth,
+                    usersImage, dstImage, elementSize, groupSize, rowSize,
+                    imageSize, myswapBytes );
+          } else {
+            HalveImage.halveImage_float( cmpts, width, height, usersImage,
+                    dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes );
+          }
+          break;
+        case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+          HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+          HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+          HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+          HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+          HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage,
+                  dstImage, elementSize, rowSize, imageSize, myswapBytes );
+          break;
+        default:
+          assert( false );
+          break;
+      }
+      
+      tempImage = srcImage;
+      srcImage = dstImage;
+      dstImage = tempImage;
+      
+      if( newWidth > 1 ) {
+        newWidth /= 2;
+        rowSize /= 2;
+      }
+      if( newHeight > 1 ) {
+        newHeight /= 2;
+        imageSize = rowSize * newHeight;
+      }
+      if( newDepth > 1 ) {
+        newDepth /= 2;
+      }
+      if( baseLevel <= level && level <= maxLevel ) {
+        usersImage.position( mark );
+        gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth,
+                0, format, type, usersImage );
+      }
+    }
+    gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() );
+    gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() );
+    gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 );
+    gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() );
+    gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
+    return( 0 );
+  }
+
+  private static final int TARGA_HEADER_SIZE = 18;
+  private static void writeTargaFile(String filename, ByteBuffer data,
+                                     int width, int height) {
+    try {
+      FileOutputStream fos = new FileOutputStream(new File(filename));
+      ByteBuffer header = ByteBuffer.allocateDirect(TARGA_HEADER_SIZE);
+      header.put(0, (byte) 0).put(1, (byte) 0);
+      header.put(2, (byte) 2); // uncompressed type
+      header.put(12, (byte) (width & 0xFF)); // width
+      header.put(13, (byte) (width >> 8)); // width
+      header.put(14, (byte) (height & 0xFF)); // height
+      header.put(15, (byte) (height >> 8)); // height
+      header.put(16, (byte) 24); // pixel size
+      fos.write(header.array());
+      fos.write(data.array());
+      data.clear();
+      fos.close();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
new file mode 100644
index 000000000..be86585e7
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java
@@ -0,0 +1,56 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public interface Extract {
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents );
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel );
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
new file mode 100644
index 000000000..7e172b1ce
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract1010102 implements Extract {
+  
+  /** Creates a new instance of Extract1010102 */
+  public Extract1010102() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    long uint = 0;
+    
+    if( isSwap ) {
+      uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
+    } else {
+      uint = 0x00000000FFFFFFFF & packedPixel.getInt();
+    }
+    
+    // 11111111,11000000,00000000,00000000 == 0xFFC00000
+    // 00000000,00111111,11110000,00000000 == 0x003F0000
+    // 00000000,00000000,00001111,11111100 == 0x00000FFC
+    // 00000000,00000000,00000000,00000011 == 0x00000003
+    
+    extractComponents[0] = (float)( ( uint & 0xFFC00000 ) >> 22 ) / 1023.0f;
+    extractComponents[1] = (float)( ( uint & 0x003FF000 ) >> 12 ) / 1023.0f;
+    extractComponents[2] = (float)( ( uint & 0x00000FFC ) >>  2 ) / 1023.0f;
+    extractComponents[3] = (float)( ( uint & 0x00000003 )       ) / 3.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) << 22) & 0xFFC00000 );
+    uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) <<   12) & 0x003FF000 );
+    uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) <<    2) & 0x00000FFC );
+    uint |= (((int)((shoveComponents[3] *    3) + 0.5f)        ) & 0x00000003 );
+    packedPixel.asIntBuffer().put( index, (int)uint );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
new file mode 100644
index 000000000..37895096e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract1555rev implements Extract {
+  
+  /** Creates a new instance of Extract1555rev */
+  public Extract1555rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 00000000,00011111 == 0x001F
+    // 00000011,11100000 == 0x03E0
+    // 01111100,00000000 == 0x7C00
+    // 10000000,00000000 == 0x8000
+    
+    extractComponents[0] = (float)( ( ushort & 0x001F )       ) / 31.0f;
+    extractComponents[1] = (float)( ( ushort & 0x003E ) >>  5 ) / 31.0f;
+    extractComponents[2] = (float)( ( ushort & 0x7C00 ) >>  10) / 31.0f;
+    extractComponents[3] = (float)( ( ushort & 0x8000 ) >>  15);
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 00000000,00011111 == 0x001F
+    // 00000011,11100000 == 0x03E0
+    // 01111100,00000000 == 0x7C00
+    // 10000000,00000000 == 0x8000
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 31) + 0.5f)   ) & 0x0000001F );
+    ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) <<  5) & 0x000003E0 );
+    ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 10) & 0x00007C00 );
+    ushort |= (((int)((shoveComponents[3]) + 0.5f)      << 15) & 0x00008000 );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
new file mode 100644
index 000000000..077f3037b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract2101010rev implements Extract {
+  
+  /** Creates a new instance of Extract2101010 */
+  public Extract2101010rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    long uint = 0;
+    
+    if( isSwap ) {
+      uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
+    } else {
+      uint = 0x00000000FFFFFFFF & packedPixel.getInt();
+    }
+    
+    // 11111111,11000000,00000000,00000000 == 0xFFC00000
+    // 00000000,00111111,11110000,00000000 == 0x003F0000
+    // 00000000,00000000,00001111,11111100 == 0x00000FFC
+    // 00000000,00000000,00000000,00000011 == 0x00000003
+    
+    extractComponents[0] = (float)( ( uint & 0x000003FF )       ) / 1023.0f;
+    extractComponents[1] = (float)( ( uint & 0x000FFC00 ) >> 10 ) / 1023.0f;
+    extractComponents[2] = (float)( ( uint & 0x3FF00000 ) >> 20 ) / 1023.0f;
+    extractComponents[3] = (float)( ( uint & 0xC0000000 ) >> 30 ) / 3.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    long uint = (((int)((shoveComponents[0] * 1023) + 0.5f)    ) & 0x000003FF );
+    uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) <<   10) & 0x000FFC00 );
+    uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) <<   20) & 0x3FF00000 );
+    uint |= (((int)((shoveComponents[3] *    3) + 0.5f) <<   30) & 0xC0000000 );
+    packedPixel.asIntBuffer().put( index, (int)uint );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
new file mode 100644
index 000000000..fa35c6fbc
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java
@@ -0,0 +1,85 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract233rev implements Extract {
+  
+  /** Creates a new instance of Extract223rev */
+  public Extract233rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    // 11100000 == 0xe0
+    // 00011100 == 0x1c
+    // 00000011 == 0x03
+    byte ubyte = packedPixel.get();
+    extractComponents[0] = (float)((ubyte & 0x07) ) / 7.0f;
+    extractComponents[1] = (float)((ubyte & 0x38) >> 3) / 7.0f;
+    extractComponents[2] = (float)((ubyte & 0xC0) >> 6) / 3.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11100000 == 0xE0
+    // 00011100 == 0x1C
+    // 00000011 == 0x03
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) ) & 0x07 );
+    b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 3 ) & 0x38 );
+    b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) << 6 ) & 0xC0 );
+    packedPixel.position( index );
+    packedPixel.put( b );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
new file mode 100644
index 000000000..35936466c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java
@@ -0,0 +1,84 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract332 implements Extract {
+  
+  /** Creates a new instance of Extract332 */
+  public Extract332() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    // 11100000 == 0xe0
+    // 00011100 == 0x1c
+    // 00000011 == 0x03
+    byte ubyte = packedPixel.get();
+    extractComponents[0] = (float)((ubyte & 0xe0) >> 5) / 7.0f;
+    extractComponents[1] = (float)((ubyte & 0x1c) >> 2) / 7.0f;
+    extractComponents[2] = (float)((ubyte & 0x03)) / 3.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11100000 == 0xE0
+    // 00011100 == 0x1C
+    // 00000011 == 0x03
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) << 5 ) & 0xE0 );
+    b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 2 ) & 0x1C );
+    b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) ) & 0x03 );
+    packedPixel.put( index, b );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
new file mode 100644
index 000000000..bac4f57aa
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java
@@ -0,0 +1,96 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract4444 implements Extract {
+  
+  /** Creates a new instance of Extract4444 */
+  public Extract4444() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    extractComponents[0] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
+    extractComponents[1] = (float)( ( ushort & 0x0F00 ) >> 8  ) / 15.0f;
+    extractComponents[2] = (float)( ( ushort & 0x00F0 ) >> 4  ) / 15.0f;
+    extractComponents[3] = (float)( ( ushort & 0x000F )       ) / 15.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) << 12) & 0x0000F000 );
+    ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 8) & 0x00000F00 );
+    ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) << 4) & 0x000000F0 );
+    ushort |= (((int)((shoveComponents[3] * 15) + 0.5f)     ) & 0x0000000F );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
new file mode 100644
index 000000000..b1bea75e1
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract4444rev implements Extract {
+  
+  /** Creates a new instance of Extract4444rev */
+  public Extract4444rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 00000000,00001111 == 0x000F
+    // 00000000,11110000 == 0x00F0
+    // 00001111,00000000 == 0x0F00
+    // 11110000,00000000 == 0xF000
+    
+    extractComponents[0] = (float)( ( ushort & 0x000F )       ) / 15.0f;
+    extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 4  ) / 15.0f;
+    extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 8  ) / 15.0f;
+    extractComponents[3] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 15) + 0.5f)   ) & 0x0000000F );
+    ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) <<  4) & 0x000000F0 );
+    ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) <<  8) & 0x00000F00 );
+    ushort |= (((int)((shoveComponents[3] * 15) + 0.5f) << 12) & 0x0000F000 );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
new file mode 100644
index 000000000..a6247844f
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract5551 implements Extract {
+  
+  /** Creates a new instance of Extract5551 */
+  public Extract5551() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 11111000,00000000 == 0xF800
+    // 00000111,11000000 == 0x07C0
+    // 00000000,00111110 == 0x003E
+    // 00000000,00000001 == 0x0001
+    
+    extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+    extractComponents[1] = (float)( ( ushort & 0x00F0 ) >>  6 ) / 31.0f;
+    extractComponents[2] = (float)( ( ushort & 0x0F00 ) >>  1 ) / 31.0f;
+    extractComponents[3] = (float)( ( ushort & 0xF000 )       );
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 );
+    ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) <<  6) & 0x000007C0 );
+    ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) <<  1) & 0x0000003E );
+    ushort |= (((int)((shoveComponents[3]) + 0.5f)) & 0x00000001 );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
new file mode 100644
index 000000000..624a4f3f2
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java
@@ -0,0 +1,92 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract565 implements Extract {
+  
+  /** Creates a new instance of Extract565 */
+  public Extract565() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 11111000,00000000 == 0xF800
+    // 00000111,11100000 == 0x07E0
+    // 00000000,00111111 == 0x001F
+    
+    extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+    extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
+    extractComponents[2] = (float)( ( ushort & 0x001F ) ) / 31.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11111000,00000000 == 0xF800
+    // 00000111,11100000 == 0x07E0
+    // 00000000,00111111 == 0x001F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 );
+    ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 );
+    ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) ) & 0x0000001F );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
new file mode 100644
index 000000000..4ab6d7e98
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java
@@ -0,0 +1,92 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract565rev implements Extract {
+  
+  /** Creates a new instance of Extract565rev */
+  public Extract565rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    int ushort = 0;
+    
+    if( isSwap ) {
+      ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() );
+    } else {
+      ushort = 0x0000FFFF & packedPixel.getShort();
+    }
+    
+    // 00000000,00011111 == 0x001F
+    // 00000111,11100000 == 0x07E0
+    // 11111000,00000000 == 0xF800
+    
+    extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f;
+    extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f;
+    extractComponents[2] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 00000000,00111111 == 0x001F
+    // 00000111,11100000 == 0x07E0
+    // 11111000,00000000 == 0xF800
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F );
+    ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 );
+    ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 11) & 0x0000F800 );
+    packedPixel.asShortBuffer().put( index, (short)ushort );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
new file mode 100644
index 000000000..90d7e57c9
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract8888 implements Extract {
+  
+  /** Creates a new instance of Extract8888 */
+  public Extract8888() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    long uint = 0;
+    
+    if( isSwap ) {
+      uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
+    } else {
+      uint = 0x00000000FFFFFFFF & packedPixel.getInt();
+    }
+    
+    // 11111000,00000000 == 0xF800
+    // 00000111,11000000 == 0x07C0
+    // 00000000,00111110 == 0x003E
+    // 00000000,00000001 == 0x0001
+    
+    extractComponents[0] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
+    extractComponents[1] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
+    extractComponents[2] = (float)( ( uint & 0x0000FF00 ) >>  8 ) / 255.0f;
+    extractComponents[3] = (float)( ( uint & 0x000000FF )       ) / 255.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    long uint = (((int)((shoveComponents[0] * 255) + 0.5f) << 24) & 0xFF000000 );
+    uint |= (((int)((shoveComponents[1] * 255) + 0.5f) <<   16) & 0x00FF0000 );
+    uint |= (((int)((shoveComponents[2] * 255) + 0.5f) <<    8) & 0x0000FF00 );
+    uint |= (((int)((shoveComponents[3] * 255) + 0.5f)        ) & 0x000000FF );
+    packedPixel.asIntBuffer().put( index, (int)uint );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
new file mode 100644
index 000000000..10970573b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java
@@ -0,0 +1,97 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class Extract8888rev implements Extract {
+  
+  /** Creates a new instance of Extract8888rev */
+  public Extract8888rev() {
+  }
+  
+  public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
+    long uint = 0;
+    
+    if( isSwap ) {
+      uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() );
+    } else {
+      uint = 0x00000000FFFFFFFF & packedPixel.getInt();
+    }
+    
+    // 11111000,00000000 == 0xF800
+    // 00000111,11000000 == 0x07C0
+    // 00000000,00111110 == 0x003E
+    // 00000000,00000001 == 0x0001
+    
+    extractComponents[0] = (float)( ( uint & 0x000000FF )       ) / 255.0f;
+    extractComponents[1] = (float)( ( uint & 0x0000FF00 ) >>  8 ) / 255.0f;
+    extractComponents[2] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f;
+    extractComponents[3] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f;
+  }
+  
+  public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) {
+    // 11110000,00000000 == 0xF000
+    // 00001111,00000000 == 0x0F00
+    // 00000000,11110000 == 0x00F0
+    // 00000000,00001111 == 0x000F
+    
+    assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f );
+    assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f );
+    assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f );
+    assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f );
+    
+    // due to limited precision, need to round before shoving
+    long uint = (((int)((shoveComponents[0] * 255) + 0.5f)    ) & 0x000000FF );
+    uint |= (((int)((shoveComponents[1] * 255) + 0.5f) <<    8) & 0x0000FF00 );
+    uint |= (((int)((shoveComponents[2] * 255) + 0.5f) <<   16) & 0x00FF0000 );
+    uint |= (((int)((shoveComponents[3] * 255) + 0.5f) <<   24) & 0xFF000000 );
+    packedPixel.asIntBuffer().put( index, (int)uint );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
new file mode 100644
index 000000000..c42799470
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java
@@ -0,0 +1,74 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractFloat implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractFloat */
+  public ExtractFloat() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer data ) {
+    float f = 0;
+    if( isSwap ) {
+      f = Mipmap.GLU_SWAP_4_BYTES( data.getInt() );
+    } else {
+      f = data.getInt();
+    }
+    assert( f <= 1.0f );
+    return( f );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < 1.0);
+    data.asFloatBuffer().put( index, (float)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
new file mode 100644
index 000000000..8b986d6d0
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java
@@ -0,0 +1,56 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public interface ExtractPrimitive {
+  public double extract( boolean isSwap, ByteBuffer pointer );
+  public void shove( double value, int index, ByteBuffer pointer );
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
new file mode 100644
index 000000000..4f61015f4
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java
@@ -0,0 +1,69 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractSByte implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractUByte */
+  public ExtractSByte() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer sbyte ) {
+    byte b = sbyte.get();
+    assert( b <= 127 );
+    return( b );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    data.position( index );
+    data.put( (byte)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
new file mode 100644
index 000000000..2d5ac5329
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java
@@ -0,0 +1,76 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractSInt implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractSInt */
+  public ExtractSInt() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer uint ) {
+    int i = 0;
+    if( isSwap ) {
+      i = Mipmap.GLU_SWAP_4_BYTES( uint.getInt() );
+    } else {
+      i = uint.getInt();
+    }
+    assert( i <= 0x7FFFFFFF );
+    return( i );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < Integer.MAX_VALUE);
+    IntBuffer ib = data.asIntBuffer();
+    ib.position( index );
+    ib.put( (int)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
new file mode 100644
index 000000000..8b8d50cbf
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
@@ -0,0 +1,76 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractSShort implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractSShort */
+  public ExtractSShort() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer ushort ) {
+    short s = 0;
+    if( isSwap ) {
+      s = Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() );
+    } else {
+      s = ushort.getShort();
+    }
+    assert( s <= 32767 );
+    return( s );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < 32768.0);
+    ShortBuffer sb = data.asShortBuffer();
+    sb.position( index );
+    sb.put( (short)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
new file mode 100644
index 000000000..d33213f89
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
@@ -0,0 +1,70 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractUByte implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractUByte */
+  public ExtractUByte() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer ubyte ) {
+    int i = 0x000000FF & ubyte.get();
+    assert( i <= 255 );
+    return( i );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < 256.0);
+    data.position( index );
+    data.put( (byte)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
new file mode 100644
index 000000000..873668a43
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
@@ -0,0 +1,76 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractUInt implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtractUInt */
+  public ExtractUInt() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer uint ) {
+    long i = 0;
+    if( isSwap ) {
+      i = 0xFFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( uint.getInt() );
+    } else {
+      i = 0xFFFFFFFF & uint.getInt();
+    }
+    assert( i <= 0xFFFFFFFF );
+    return( i );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < 0xFFFFFFFF);
+    IntBuffer ib = data.asIntBuffer();
+    ib.position( index );
+    ib.put( (int)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
new file mode 100644
index 000000000..86bbb95f1
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
@@ -0,0 +1,76 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author Administrator
+ */
+public class ExtractUShort implements ExtractPrimitive {
+  
+  /** Creates a new instance of ExtracUShort */
+  public ExtractUShort() {
+  }
+  
+  public double extract( boolean isSwap, ByteBuffer ushort ) {
+    int i = 0;
+    if( isSwap ) {
+      i = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() );
+    } else {
+      i = 0x0000FFFF & ushort.getShort();
+    }
+    assert( i <= 65535 );
+    return( i );
+  }
+  
+  public void shove( double value, int index, ByteBuffer data ) {
+    assert(0.0 <= value && value < 65536.0);
+    ShortBuffer sb = data.asShortBuffer();
+    sb.position( index );
+    sb.put( (short)value );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
new file mode 100644
index 000000000..893d33c66
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
@@ -0,0 +1,1533 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import javax.media.opengl.GL;
+import java.nio.*;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class HalveImage {
+  
+  private static final int BOX2 = 2;
+  private static final int BOX4 = 4;
+  private static final int BOX8 = 8;
+  
+  public static void halveImage( int components, int width, int height,
+          ShortBuffer datain, ShortBuffer dataout ) {
+    int i, j, k;
+    int newwidth, newheight;
+    int delta;
+    int t = 0;
+    short temp = 0;
+    
+    newwidth = width / 2;
+    newheight = height /2;
+    delta = width * components;
+    
+    // Piece of cake
+    for( i = 0; i < newheight; i++ ) {
+      for( j = 0; j < newwidth; j++ ) {
+        for( k = 0; k < components; k++ ) {
+          datain.position( t );
+          temp = datain.get();
+          datain.position( t + components );
+          temp += datain.get();
+          datain.position( t + delta );
+          temp += datain.get();
+          datain.position( t + delta + components );
+          temp +=datain.get();
+          temp += 2;
+          temp /= 4;
+          dataout.put( temp );
+          t++;
+        }
+        t += components;
+      }
+      t += delta;
+    }
+  }
+  
+  public static void halveImage_ubyte( int components, int width, int height,
+                                      ByteBuffer datain, ByteBuffer dataout,
+                                      int element_size, int ysize, int group_size ) {
+    int i, j, k;
+    int newwidth, newheight;
+    int s;
+    int t;
+    
+    // Handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_ubyte( components, width, height, datain, dataout, element_size, ysize, group_size );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    s = 0;
+    t = 0;
+    
+    int temp = 0;
+    // piece of cake
+    for( i = 0; i < newheight; i++ ) {
+      for( j = 0; j < newwidth; j++ ) {
+        for( k = 0; k < components; k++ ) {
+          datain.position( t );
+          temp = ( 0x000000FF & datain.get() );
+          datain.position( t + group_size );
+          temp += ( 0x000000FF & datain.get() );
+          datain.position( t + ysize );
+          temp += ( 0x000000FF & datain.get() );
+          datain.position( t + ysize + group_size );
+          temp += ( 0x000000FF & datain.get() ) + 2;
+          dataout.put( (byte)(temp / 4) );
+          t += element_size;
+        }
+        t += group_size;
+      }
+      t += ysize;
+    }
+  }
+  
+  public static void halve1Dimage_ubyte( int components, int width, int height,
+                      ByteBuffer datain, ByteBuffer dataout, 
+                      int element_size, int ysize, int group_size ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    int temp = 0;
+    
+    assert( width == 1 || height == 1 ); // Must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // widthxheight can't be 1x1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          datain.position( src );
+          temp = ( 0x000000FF & datain.get() );
+          datain.position( src + group_size );
+          temp += ( 0x000000FF & datain.get() );
+          temp /= 2;
+          dataout.put( (byte)temp );
+          /*
+          dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + 
+                    (0x000000FF & datain.setIndexInBytes( src + group_size ).getByte())) / 2 ) );
+           */
+          src += element_size;
+          //dataout.plusPlus();
+          dest++;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) { // 1 column
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 );
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          datain.position( src );
+          temp = ( 0x000000FF & datain.get() );
+          datain.position( src + ysize );
+          temp += ( 0x000000FF & datain.get() );
+          temp /= 2;
+          dataout.put( (byte)temp );
+          /*
+          dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + 
+                    (0x000000FF & datain.setIndexInBytes(src + ysize).getByte()) ) / 2 ) );
+           */
+          src += element_size;
+          //dataout.plusPlus();
+          dest++;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+    }
+    assert( src == ysize * height );
+    assert( dest == components * element_size * halfWidth * halfHeight );
+  }
+  
+  public static void halveImage_byte( int components, int width, int height,
+                    ByteBuffer datain, ByteBuffer dataout, int element_size,
+                    int ysize, int group_size ) {
+    int i, j, k;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    byte temp = (byte)0;
+    
+    // handle case where there is only 1 column
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) );
+      halve1Dimage_byte( components, width, height, datain, dataout, element_size,
+                                                            ysize, group_size );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    for( i = 0; i < newheight; i++ ) {
+      for( j = 0; j < newwidth; j++ ) {
+        for( k = 0; k < components; k++ ) {
+          datain.position( t );
+          temp = datain.get();
+          datain.position( t + group_size );
+          temp += datain.get();
+          datain.position( t + ysize );
+          temp += datain.get();
+          datain.position( t + ysize + group_size );
+          temp += datain.get();
+          temp += 2;
+          temp /= 4;
+          dataout.put( temp );
+          t += element_size;
+        }
+        t += group_size;
+      }
+      t += ysize;
+    }
+  }
+  
+  public static void halve1Dimage_byte( int components, int width, int height,
+                      ByteBuffer datain, ByteBuffer dataout,
+                      int element_size, int ysize, int group_size ) {
+    int halfWidth = width / 2;
+    int halfHeight = width / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    byte temp = (byte)0;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // widthxheight can't be 1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          datain.position( src );
+          temp = datain.get();
+          datain.position( src + group_size );
+          temp += datain.get();
+          temp /= 2;
+          dataout.put( temp );
+          src += element_size;
+          dest++;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assert only
+    } else if( width == 1 ) { // 1 column
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 ); // widthxheight can't be 1
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          datain.position( src );
+          temp = datain.get();
+          datain.position( src + ysize );
+          temp += datain.get();
+          temp /= 2;
+          src += element_size;
+          dest++;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == components * element_size * halfWidth * halfHeight );
+  }
+  
+  public static void halveImage_ushort( int components, int width, int height,
+                          ByteBuffer datain, ShortBuffer dataout, int element_size,
+                          int ysize, int group_size, boolean myswap_bytes ) {
+    int i, j, k, l;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    int temp = 0;
+    // handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_ushort( components, width, height, datain, dataout, element_size,
+                                ysize, group_size, myswap_bytes );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    // Piece of cake
+    if( !myswap_bytes ) {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = ( 0x0000FFFF & datain.getShort() );
+            datain.position( t + group_size );
+            temp += ( 0x0000FFFF & datain.getShort() );
+            datain.position( t + ysize );
+            temp += ( 0x0000FFFF & datain.getShort() );
+            datain.position( t + ysize + group_size );
+            temp += ( 0x0000FFFF & datain.getShort() );
+            dataout.put( (short)( ( temp + 2 ) / 4 ) );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    } else {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            datain.position( t + group_size );
+            temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            datain.position( t + ysize );
+            temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            datain.position( t + ysize + group_size );
+            temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            dataout.put( (short)( ( temp + 2 ) / 4 ) );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    }
+  }
+  
+  public static void halve1Dimage_ushort( int components, int width, int height,
+                      ByteBuffer datain, ShortBuffer dataout, int element_size,
+                      int ysize, int group_size, boolean myswap_bytes ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // widthxheight can't be 1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < halfHeight; kk++ ) {
+          int[] ushort = new int[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            datain.position( src + group_size );
+            ushort[1] = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+          } else {
+            datain.position( src );
+            ushort[0] = (0x0000FFFF & datain.getShort() );
+            datain.position( src + group_size );
+            ushort[1] = (0x0000FFFF & datain.getShort() );
+          }
+          dataout.put( (short)( (ushort[0] + ushort[1]) / 2 ) );
+          src += element_size;
+          dest += 2;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) { // 1 column
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 ); // widthxheight can't be 1
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          int[] ushort = new int[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+            datain.position( src + ysize );
+            ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) );
+          } else {
+            datain.position( src );
+            ushort[0] = ( 0x0000FFFF & datain.getShort() );
+            datain.position( src + ysize );
+            ushort[1] = ( 0x0000FFFF & datain.getShort() );
+          }
+          dataout.put( (short)((ushort[0] + ushort[1]) / 2) );
+          src += element_size;
+          dest += 2;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == components * element_size * halfWidth * halfHeight );
+  }
+  
+  public static void halveImage_short( int components, int width, int height,
+                        ByteBuffer datain, ShortBuffer dataout, int element_size,
+                        int ysize, int group_size, boolean myswap_bytes ) {
+    int i, j, k, l;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    short temp = (short)0;
+    // handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_short( components, width, height, datain, dataout, element_size,
+                            ysize, group_size, myswap_bytes );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    // Piece of cake
+    if( !myswap_bytes ) {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = datain.getShort();
+            datain.position( t + group_size );
+            temp += datain.getShort();
+            datain.position( t + ysize );
+            temp += datain.getShort();
+            datain.position( t + ysize + group_size );
+            temp += datain.getShort();
+            temp += 2;
+            temp /= 4;
+            dataout.put( (short)temp );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    } else {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            short b;
+            int buf;
+            datain.position( t );
+            temp = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            datain.position( t + group_size );
+            temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            datain.position( t + ysize );
+            temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            datain.position( t + ysize + group_size );
+            temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            temp += 2;
+            temp /= 4;
+            dataout.put( temp );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    }
+  }
+  
+  public static void halve1Dimage_short( int components, int width, int height,
+              ByteBuffer datain, ShortBuffer dataout, int element_size, int ysize,
+              int group_size, boolean myswap_bytes ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // can't be 1x1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          short[] sshort = new short[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            datain.position( src + group_size );
+            sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+          } else {
+            datain.position( src );
+            sshort[0] = datain.getShort();
+            datain.position( src + group_size );
+            sshort[1] = datain.getShort();
+          }
+          dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) );
+          src += element_size;
+          dest += 2;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) {
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 );
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          short[] sshort = new short[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+            datain.position( src + ysize );
+            sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+          } else {
+            datain.position( src );
+            sshort[0] = datain.getShort();
+            datain.position( src + ysize );
+            sshort[1] = datain.getShort();
+          }
+          dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) );
+          src += element_size;
+          dest += 2;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == ( components * element_size * halfWidth * halfHeight ) );
+  }
+  
+  public static void halveImage_uint( int components, int width, int height,
+                          ByteBuffer datain, IntBuffer dataout, int element_size,
+                          int ysize, int group_size, boolean myswap_bytes ) {
+    int i, j, k, l;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    double temp = 0;
+    
+    // handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_uint( components, width, height, datain, dataout, element_size,
+                                ysize, group_size, myswap_bytes );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    // Piece of cake
+    if( !myswap_bytes ) {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = (0x000000007FFFFFFFL & datain.getInt() );
+            datain.position( t + group_size );
+            temp += (0x000000007FFFFFFFL & datain.getInt() );
+            datain.position( t + ysize );
+            temp += (0x000000007FFFFFFFL & datain.getInt() );
+            datain.position( t + ysize + group_size );
+            temp += (0x000000007FFFFFFFL & datain.getInt() );
+            dataout.put( (int)( ( temp / 4 ) + 0.5 ) );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    } else {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            // need to cast to double to hold large unsigned ints
+            double buf;
+            datain.position( t );
+            buf = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( t + group_size );
+            buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( t + ysize );
+            buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( t + ysize + group_size );
+            buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            temp /= 4;
+            temp += 0.5;
+            dataout.put( (int)temp );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    }
+  }
+  
+  public static void halve1Dimage_uint( int components, int width, int height,
+                      ByteBuffer datain, IntBuffer dataout, int element_size, int ysize,
+                      int group_size, boolean myswap_bytes ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // widthxheight can't be 1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < halfHeight; kk++ ) {
+          long[] uint = new long[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( src + group_size );
+            uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+          } else {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() );
+            datain.position( src + group_size );
+            uint[1] = (0x00000000FFFFFFFF & datain.getInt() );
+          }
+          dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) );
+          src += element_size;
+          dest += 4;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) { // 1 column
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 ); // widthxheight can't be 1
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          long[] uint = new long[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( src + group_size );
+            uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+          } else {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() );
+            datain.position( src + ysize );
+            uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() );
+          }
+          dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) );
+          src += element_size;
+          dest += 4;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == components * element_size * halfWidth * halfHeight );
+  }
+  
+  public static void halveImage_int( int components, int width, int height,
+                        ByteBuffer datain, IntBuffer dataout, int element_size,
+                        int ysize, int group_size, boolean myswap_bytes ) {
+    int i, j, k, l;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    int temp = 0;
+    
+    // handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_int( components, width, height, datain, dataout, element_size,
+                            ysize, group_size, myswap_bytes );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    // Piece of cake
+    if( !myswap_bytes ) {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = datain.getInt();
+            datain.position( t + group_size );
+            temp += datain.getInt();
+            datain.position( t + ysize );
+            temp += datain.getInt();
+            datain.position( t + ysize + group_size );
+            temp += datain.getInt();
+            temp = (int)( ( temp / 4.0f ) + 0.5f );
+            dataout.put( temp );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    } else {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            long b;
+            float buf;
+            datain.position( t );
+            b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            buf = b;
+            datain.position( t + group_size );
+            b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            buf += b;
+            datain.position( t + ysize );
+            b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            buf += b;
+            datain.position( t + ysize + group_size );
+            b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            buf += b;
+            dataout.put( (int)( ( buf / 4.0f ) + 0.5f ) );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    }
+  }
+  
+  public static void halve1Dimage_int( int components, int width, int height,
+              ByteBuffer datain, IntBuffer dataout, int element_size, int ysize,
+              int group_size, boolean myswap_bytes ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // can't be 1x1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          long[] uint = new long[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( src + group_size );
+            uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+          } else {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() );
+            datain.position( src + group_size );
+            uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() );
+          }
+          dataout.put( (int)( ( (float)uint[0] + (float)uint[1] ) / 2.0f) );
+          src += element_size;
+          dest += 4;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) {
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 );
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          long[] uint = new long[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+            datain.position( src + ysize );
+            uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) );
+          } else {
+            datain.position( src );
+            uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() );
+            datain.position( src + ysize );
+            uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() );
+          }
+          dataout.put( (int)(( (float)uint[0] + (float)uint[1] ) / 2.0f) );
+          src += element_size;
+          dest += 4;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == ( components * element_size * halfWidth * halfHeight ) );
+  }
+  
+  public static void halveImage_float( int components, int width, int height,
+                    ByteBuffer datain, FloatBuffer dataout, int element_size,
+                    int ysize, int group_size, boolean myswap_bytes ) {
+    int i, j, k, l;
+    int newwidth, newheight;
+    int s = 0;
+    int t = 0;
+    float temp = 0.0f;
+    // handle case where there is only 1 column/row
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) ); // can't be 1x1
+      halve1Dimage_float( components, width, height, datain, dataout, element_size,
+                                              ysize, group_size, myswap_bytes );
+      return;
+    }
+    
+    newwidth = width / 2;
+    newheight = height / 2;
+    
+    // Piece of cake
+    if( !myswap_bytes ) {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            datain.position( t );
+            temp = datain.getFloat();
+            datain.position( t + group_size );
+            temp += datain.getFloat();
+            datain.position( t + ysize );
+            temp += datain.getFloat();
+            datain.position( t + ysize + group_size );
+            temp /= 4.0f;
+            dataout.put( temp );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    } else {
+      for( i = 0; i < newheight; i++ ) {
+        for( j = 0; j < newwidth; j++ ) {
+          for( k = 0; k < components; k++ ) {
+            float buf;
+            datain.position( t );
+            buf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            datain.position( t + group_size );
+            buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            datain.position( t + ysize );
+            buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            datain.position( t + ysize + group_size );
+            buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            dataout.put( buf / 4.0f );
+            t += element_size;
+          }
+          t += group_size;
+        }
+        t += ysize;
+      }
+    }
+  }
+  
+  public static void halve1Dimage_float( int components, int width, int height,
+              ByteBuffer datain, FloatBuffer dataout, int element_size, int ysize,
+              int group_size, boolean myswap_bytes ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int dest = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 ); // must be 1D
+    assert( width != height ); // can't be square
+    
+    if( height == 1 ) { // 1 row
+      assert( width != 1 ); // can't be 1x1
+      halfHeight = 1;
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          float[] sfloat = new float[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            datain.position( src + group_size );
+            sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+          } else {
+            datain.position( src );
+            sfloat[0] = datain.getFloat();
+            datain.position( src + group_size );
+            sfloat[1] = datain.getFloat();
+          }
+          dataout.put( (sfloat[0] + sfloat[1]) / 2.0f );
+          src += element_size;
+          dest += 4;
+        }
+        src += group_size; // skip to next 2
+      }
+      int padBytes = ysize - ( width * group_size );
+      src += padBytes; // for assertion only
+    } else if( width == 1 ) {
+      int padBytes = ysize - ( width * group_size );
+      assert( height != 1 );
+      halfWidth = 1;
+      // one vertical column with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        int kk;
+        for( kk = 0; kk < components; kk++ ) {
+          float[] sfloat = new float[BOX2];
+          if( myswap_bytes ) {
+            datain.position( src );
+            sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+            datain.position( src + ysize );
+            sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+          } else {
+            datain.position( src );
+            sfloat[0] = datain.getFloat();
+            datain.position( src + ysize );
+            sfloat[1] = datain.getFloat();
+          }
+          dataout.put( ( sfloat[0] + sfloat[1] ) / 2.0f );
+          src += element_size;
+          dest += 4;
+        }
+        src += padBytes; // add pad bytes, if any, to get to end of row
+        src += ysize;
+      }
+      assert( src == ysize * height );
+    }
+    assert( dest == ( components * element_size * halfWidth * halfHeight ) );
+  }
+  
+  public static void halveImagePackedPixel( int components, Extract extract, int width, 
+          int height, ByteBuffer datain, ByteBuffer dataout, 
+          int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) {
+    if( width == 1 || height == 1 ) {
+      assert( !( width == 1 && height == 1 ) );
+      halve1DimagePackedPixel( components, extract, width, height, datain, dataout,
+                          pixelSizeInBytes, rowSizeInBytes, isSwap );
+      return;
+    }
+    int ii, jj;
+    
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+    int outIndex = 0;
+    
+    for( ii = 0; ii < halfHeight; ii++ ) {
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        float totals[] = new float[4];
+        float extractTotals[][] = new float[BOX4][4];
+        int cc;
+        
+        datain.position( src );
+        extract.extract( isSwap, datain, extractTotals[0] );
+        datain.position( src + pixelSizeInBytes );
+        extract.extract( isSwap, datain, extractTotals[1] );
+        datain.position( src + rowSizeInBytes );
+        extract.extract( isSwap, datain, extractTotals[2] );
+        datain.position( src + rowSizeInBytes + pixelSizeInBytes );
+        extract.extract( isSwap, datain, extractTotals[3] );
+        for( cc = 0; cc < components; cc++ ) {
+          int kk = 0;
+          // grab 4 pixels to average
+          totals[cc] = 0.0f;
+          for( kk = 0; kk < BOX4; kk++ ) {
+            totals[cc] += extractTotals[kk][cc];
+          }
+          totals[cc] /= BOX4;
+        }
+        extract.shove( totals, outIndex, dataout );
+        outIndex++;
+        src += pixelSizeInBytes + pixelSizeInBytes;
+      }
+      // skip past pad bytes, if any, to get to next row
+      src += padBytes;
+      src += rowSizeInBytes;
+    }
+    assert( src == rowSizeInBytes * height );
+    assert( outIndex == halfWidth * halfHeight );
+  }
+  
+  public static void halve1DimagePackedPixel( int components, Extract extract, int width,
+              int height, ByteBuffer datain, ByteBuffer dataout,
+              int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) {
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int src = 0;
+    int jj;
+    
+    assert( width == 1 || height == 1 );
+    assert( width != height );
+    
+    if( height == 1 ) {
+      int outIndex = 0;
+      
+      assert( width != 1 );
+      halfHeight = 1;
+      
+      // one horizontal row with possible pad bytes
+      
+      for( jj = 0; jj < halfWidth; jj++ ) {
+        float[] totals = new float[4];
+        float[][] extractTotals = new float[BOX2][4];
+        int cc;
+        
+        datain.position( src );
+        extract.extract( isSwap, datain, extractTotals[0] );
+        datain.position( src + pixelSizeInBytes );
+        extract.extract( isSwap, datain, extractTotals[1] );
+        for( cc = 0; cc < components; cc++ ) {
+          int kk = 0;
+          // grab 4 pixels to average
+          totals[cc] = 0.0f;
+          for( kk = 0; kk < BOX2; kk++ ) {
+            totals[cc] += extractTotals[kk][cc];
+          }
+          totals[cc] /= BOX2;
+        }
+        extract.shove( totals, outIndex, dataout );
+        outIndex++;
+        // skip over to next group of 2
+        src += pixelSizeInBytes + pixelSizeInBytes;
+      }
+      int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+      src += padBytes;
+      
+      assert( src == rowSizeInBytes );
+      assert( outIndex == halfWidth * halfHeight );
+    } else if( width == 1 ) {
+      int outIndex = 0;
+      
+      assert( height != 1 );
+      halfWidth = 1;
+      // one vertical volumn with possible pad bytes per row
+      // average two at a time
+      
+      for( jj = 0; jj < halfHeight; jj++ ) {
+        float[] totals = new float[4];
+        float[][] extractTotals = new float[BOX2][4];
+        int cc;
+        // average two at a time, instead of four
+        datain.position( src );
+        extract.extract( isSwap, datain, extractTotals[0] );
+        datain.position( src + rowSizeInBytes );
+        extract.extract( isSwap, datain, extractTotals[1] );
+        for( cc = 0; cc < components; cc++ ) {
+          int kk = 0;
+          // grab 4 pixels to average
+          totals[cc] = 0.0f;
+          for( kk = 0; kk < BOX2; kk++ ) {
+            totals[cc] += extractTotals[kk][cc];
+          }
+          totals[cc] /= BOX2;
+        }
+        extract.shove( totals, outIndex, dataout );
+        outIndex++;
+        // skip over to next group of 2
+        src += rowSizeInBytes + rowSizeInBytes;
+      }
+      assert( src == rowSizeInBytes );
+      assert( outIndex == halfWidth * halfHeight );
+    }
+  }
+  
+  public static void halveImagePackedPixelSlice( int components, Extract extract,
+          int width, int height, int depth, ByteBuffer dataIn,
+          ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes,
+          int imageSizeInBytes, boolean isSwap ) {
+    int ii, jj;
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int halfDepth = depth / 2;
+    int src = 0;
+    int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+    int outIndex = 0;
+    
+    assert( (width == 1 || height == 1) && depth >= 2 );
+    
+    if( width == height ) {
+      assert( width == 1 && height == 1 );
+      assert( depth >= 2 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        float totals[] = new float[4];
+        float extractTotals[][] = new float[BOX2][4];
+        int cc;
+        
+        dataIn.position( src );
+        extract.extract( isSwap, dataIn, extractTotals[0] );
+        dataIn.position( src + imageSizeInBytes );
+        extract.extract( isSwap, dataIn, extractTotals[1] );
+        
+        for( cc = 0; cc < components; cc++ ) {
+          int kk;
+          
+          // average only 2 pixels since a column
+          totals[cc]= 0.0f;
+          for( kk = 0; kk < BOX2; kk++ ) {
+            totals[cc] += extractTotals[kk][cc];
+          }
+          totals[cc] /= BOX2;
+        } // for cc
+        
+        extract.shove( totals, outIndex, dataOut );
+        outIndex++;
+        // skip over to next group of 2
+        src += imageSizeInBytes + imageSizeInBytes;
+      } // for ii
+    } else if( height == 1 ) {
+      assert( width != 1 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        for( jj = 0; jj < halfWidth; jj++ ) {
+          float totals[] = new float[4];
+          float extractTotals[][] = new float[BOX4][4];
+          int cc;
+          
+          dataIn.position( src );
+          extract.extract( isSwap, dataIn, extractTotals[0] );
+          dataIn.position( src + pixelSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[1] );
+          dataIn.position( src + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[2] );
+          dataIn.position( src + pixelSizeInBytes + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[3] );
+          
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            
+            // grab 4 pixels to average
+            totals[cc] = 0.0f;
+            for( kk = 0; kk < BOX4; kk++ ) {
+              totals[cc]+= extractTotals[kk][cc];
+            }
+            totals[cc]/= (float)BOX4;
+          }
+          extract.shove( totals, outIndex, dataOut );
+          outIndex++;
+          // skip over to next horizontal square of 4
+          src += imageSizeInBytes + imageSizeInBytes;
+        }
+      }
+    } else if( width == 1 ) {
+      assert( height != 1 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        for( jj = 0; jj < halfWidth; jj++ ) {
+          float totals[] = new float[4];
+          float extractTotals[][] = new float[BOX4][4];
+          int cc;
+          
+          dataIn.position( src );
+          extract.extract( isSwap, dataIn, extractTotals[0] );
+          dataIn.position( src + rowSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[1] );
+          dataIn.position( src + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[2] );
+          dataIn.position( src + rowSizeInBytes + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[3] );
+          
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            
+            // grab 4 pixels to average
+            totals[cc] = 0.0f;
+            for( kk = 0; kk < BOX4; kk++ ) {
+              totals[cc]+= extractTotals[kk][cc];
+            }
+            totals[cc]/= (float)BOX4;
+          }
+          extract.shove( totals, outIndex, dataOut );
+          outIndex++;
+          // skip over to next horizontal square of 4
+          src += imageSizeInBytes + imageSizeInBytes;
+        }
+      }
+    }
+  }
+  
+  public static void halveImageSlice( int components, ExtractPrimitive extract, int width,
+          int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut,
+          int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes,
+          int imageSizeInBytes, boolean isSwap ) {
+    int ii, jj;
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int halfDepth = depth / 2;
+    int src = 0;
+    int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
+    int outIndex = 0;
+    
+    assert( (width == 1 || height == 1) && depth >= 2 );
+    
+    if( width == height ) {
+      assert( width == 1 && height == 1 );
+      assert( depth >= 2 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        int cc;
+        for( cc = 0; cc < components; cc++ ) {
+          double[] totals = new double[4];
+          double[][] extractTotals = new double[BOX2][4];
+          int kk;
+          
+          dataIn.position( src );
+          extractTotals[0][cc] = extract.extract( isSwap, dataIn );
+          dataIn.position( src + imageSizeInBytes );
+          extractTotals[1][cc] = extract.extract( isSwap, dataIn );
+          
+          // average 2 pixels since only a column
+          totals[cc] = 0.0f;
+          // totals[red] = extractTotals[0][red] + extractTotals[1][red];
+          // totals[red] = red / 2;
+          for( kk = 0; kk < BOX2; kk++ ) {
+            totals[cc] += extractTotals[kk][cc];
+          }
+          totals[cc] /= (double)BOX2;
+          
+          extract.shove( totals[cc], outIndex, dataOut );
+          outIndex++;
+          src += elementSizeInBytes;
+        } // for cc
+        // skip over next group of 2
+        src += rowSizeInBytes;
+      } // for ii
+      
+      assert( src == rowSizeInBytes * height * depth );
+      assert( outIndex == halfDepth * components );
+    } else if( height == 1 ) {
+      assert( width != 1 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        for( jj = 0; jj < halfWidth; jj++ ) {
+          int cc;
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            double totals[] = new double[4];
+            double extractTotals[][] = new double[BOX4][4];
+            
+            dataIn.position( src );
+            extractTotals[0][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + groupSizeInBytes );
+            extractTotals[1][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + imageSizeInBytes );
+            extractTotals[2][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + imageSizeInBytes + groupSizeInBytes );
+            extractTotals[3][cc] = extract.extract( isSwap, dataIn );
+            
+            // grab 4 pixels to average
+            totals[cc] = 0.0f;
+            // totals[red] = extractTotals[0][red] + extractTotals[1][red] +
+            //               extractTotals[2][red] + extractTotals[3][red];
+            // totals[red] /= (double)BOX4;
+            for( kk = 0; kk < BOX4; kk++ ) {
+              totals[cc] += extractTotals[kk][cc];
+            }
+            totals[cc] /= (double)BOX4;
+            
+            extract.shove( totals[cc], outIndex, dataOut );
+            outIndex++;
+            src += elementSizeInBytes;
+          } // for cc
+          // skip over to next horizontal square of 4
+          src += elementSizeInBytes;
+        } // for jj
+        src += padBytes;
+        src += rowSizeInBytes;
+      } // for ii
+      assert( src == rowSizeInBytes * height * depth );
+      assert( outIndex == halfWidth * halfDepth * components );
+    } else if( width == 1 ) {
+      assert( height != 1 );
+      
+      for( ii = 0; ii < halfDepth; ii++ ) {
+        for( jj = 0; jj < halfHeight; jj++ ) {
+          int cc;
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            double totals[] = new double[4];
+            double extractTotals[][] = new double[BOX4][4];
+            
+            dataIn.position( src );
+            extractTotals[0][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + rowSizeInBytes );
+            extractTotals[1][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + imageSizeInBytes );
+            extractTotals[2][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + imageSizeInBytes + groupSizeInBytes );
+            extractTotals[3][cc] = extract.extract( isSwap, dataIn );
+            
+            
+            // grab 4 pixels to average
+            totals[cc] = 0.0f;
+            // totals[red] = extractTotals[0][red] + extractTotals[1][red] +
+            //               extractTotals[2][red] + extractTotals[3][red];
+            // totals[red] /= (double)BOX4;
+            for( kk = 0; kk < BOX4; kk++ ) {
+              totals[cc] += extractTotals[kk][cc];
+            }
+            totals[cc] /= (double)BOX4;
+            
+            extract.shove( totals[cc], outIndex, dataOut );
+            outIndex++;
+            src += elementSizeInBytes;
+          } // for cc
+          // skip over to next horizontal square of 4
+          src += padBytes;
+          src += rowSizeInBytes;
+        } // for jj
+        src += imageSizeInBytes;
+      } // for ii
+      assert( src == rowSizeInBytes * height * depth );
+      assert( outIndex == halfWidth * halfDepth * components );
+    }
+  }
+  
+  public static void halveImage3D( int components, ExtractPrimitive extract,
+          int width, int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut,
+          int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes,
+          int imageSizeInBytes, boolean isSwap ) {
+    assert( depth > 1 );
+    
+    // horizontal/vertical/onecolumn slice viewed from top
+    if( width == 1 || height == 1 ) {
+      assert( 1 <= depth );
+      
+      halveImageSlice( components, extract, width, height, depth, dataIn, dataOut,
+              elementSizeInBytes, groupSizeInBytes, rowSizeInBytes, imageSizeInBytes,
+              isSwap );
+      return;
+    }
+    
+    int ii, jj, dd;
+    
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int halfDepth = depth / 2;
+    int src = 0;
+    int padBytes = rowSizeInBytes - ( width * groupSizeInBytes );
+    int outIndex = 0;
+    
+    for( dd = 0; dd < halfDepth; dd++ ) {
+      for( ii = 0; ii < halfHeight; ii++ ) {
+        for( jj = 0; jj < halfWidth; jj++ ) {
+          int cc;
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            double totals[] = new double[4];
+            double extractTotals[][] = new double[BOX8][4];
+            
+            dataIn.position( src );
+            extractTotals[0][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + groupSizeInBytes );
+            extractTotals[1][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + rowSizeInBytes );
+            extractTotals[2][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + rowSizeInBytes + groupSizeInBytes );
+            extractTotals[3][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + imageSizeInBytes );
+            extractTotals[4][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + groupSizeInBytes + imageSizeInBytes );
+            extractTotals[5][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + rowSizeInBytes + imageSizeInBytes );
+            extractTotals[6][cc] = extract.extract( isSwap, dataIn );
+            dataIn.position( src + rowSizeInBytes + imageSizeInBytes + groupSizeInBytes );
+            extractTotals[7][cc] = extract.extract( isSwap, dataIn );
+            
+            totals[cc] = 0.0f;
+            
+            for( kk = 0; kk < BOX8; kk++ ) {
+              totals[cc] += extractTotals[kk][cc];
+            }
+            totals[cc] /= (double)BOX8;
+            
+            extract.shove( totals[cc], outIndex, dataOut );
+            outIndex++;
+            
+            src += elementSizeInBytes;
+          } // for cc
+          // skip over to next square of 4
+          src += groupSizeInBytes;
+        } // for jj
+        // skip past pad bytes, if any, to get to next row
+        src += padBytes;
+        src += rowSizeInBytes;
+      } // for ii
+      src += imageSizeInBytes;
+    } // for dd
+    assert( src == rowSizeInBytes * height * depth );
+    assert( outIndex == halfWidth * halfHeight * halfDepth * components );
+  }
+  
+  public static void halveImagePackedPixel3D( int components, Extract extract,
+          int width, int height, int depth, ByteBuffer dataIn, 
+          ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes,
+          int imageSizeInBytes, boolean isSwap ) {
+    if( depth == 1 ) {
+      assert( 1 <= width && 1 <= height );
+      
+      halveImagePackedPixel( components, extract, width, height, dataIn, dataOut,
+              pixelSizeInBytes, rowSizeInBytes, isSwap );
+      return;
+    } else if( width == 1 || height == 1 ) { // a horizontal or vertical slice viewed from top
+      assert( 1 <= depth );
+      
+      halveImagePackedPixelSlice( components, extract, width, height, depth, dataIn,
+              dataOut, pixelSizeInBytes, rowSizeInBytes, imageSizeInBytes, isSwap );
+      return;
+    }
+    int ii, jj, dd;
+    
+    int halfWidth = width / 2;
+    int halfHeight = height / 2;
+    int halfDepth = depth / 2;
+    int src = 0;
+    int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes );
+    int outIndex = 0;
+    
+    for( dd = 0; dd < halfDepth; dd++ ) {
+      for( ii = 0; ii < halfHeight; ii++ ) {
+        for( jj = 0; jj < halfWidth; jj++ ) {
+          float totals[] = new float[4]; // 4 is max components
+          float extractTotals[][] = new float[BOX8][4];
+          int cc;
+          
+          dataIn.position( src );
+          extract.extract( isSwap, dataIn, extractTotals[0] );
+          dataIn.position( src + pixelSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[1] );
+          dataIn.position( src + rowSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[2] );
+          dataIn.position( src + rowSizeInBytes + pixelSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[3] );
+          dataIn.position( src + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[4] );
+          dataIn.position( src + pixelSizeInBytes + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[5] );
+          dataIn.position( src + rowSizeInBytes + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[6] );
+          dataIn.position( src + rowSizeInBytes + pixelSizeInBytes + imageSizeInBytes );
+          extract.extract( isSwap, dataIn, extractTotals[7] );
+          
+          for( cc = 0; cc < components; cc++ ) {
+            int kk;
+            // grab 8 pixels to average
+            totals[cc] = 0.0f;
+            for( kk = 0; kk < BOX8; kk++ ) {
+              totals[cc] += extractTotals[kk][cc];
+            }
+            totals[cc] /= (float)BOX8;
+          }
+          extract.shove( totals, outIndex, dataOut );
+          outIndex++;
+          // skip over to next square of 4
+          src += pixelSizeInBytes + pixelSizeInBytes;
+        }
+        // skip past pad bytes, if any, to get to next row
+        src += padBytes;
+        src += rowSizeInBytes;
+      }
+      src += imageSizeInBytes;
+    }
+    assert( src == rowSizeInBytes * height * depth );
+    assert( outIndex == halfWidth * halfHeight * halfDepth );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
new file mode 100644
index 000000000..b2aaad2f7
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
@@ -0,0 +1,1413 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import java.nio.*;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class Image {
+  
+  /** Creates a new instance of Image */
+  public Image() {
+  }
+  
+  public static short getShortFromByteArray( byte[] array, int index ) {
+    short s;
+    s = (short)(array[index] << 8 );
+    s |= (short)(0x00FF & array[index+1]);
+    return( s );
+  }
+  
+  public static int getIntFromByteArray( byte[] array, int index ) {
+    int i;
+    i = ( array[index] << 24 ) & 0xFF000000;
+    i |= ( array[index+1] << 16 ) & 0x00FF0000;
+    i |= ( array[index+2] << 8 ) & 0x0000FF00;
+    i |= ( array[index+3] ) & 0x000000FF;
+    return( i );
+  }
+  
+  public static float getFloatFromByteArray( byte[] array, int index ) {
+    int i = getIntFromByteArray( array, index );
+    return( Float.intBitsToFloat(i) );
+  }
+  
+  /*
+   *  Extract array from user's data applying all pixel store modes.
+   *  The internal format used is an array of unsigned shorts.
+   */
+  public static void fill_image( PixelStorageModes psm, int width, int height,
+                  int format, int type, boolean index_format, ByteBuffer userdata,
+                  ShortBuffer newimage ) {
+    int components;
+    int element_size;
+    int rowsize;
+    int padding;
+    int groups_per_line;
+    int group_size;
+    int elements_per_line;
+    int start;
+    int iter = 0;
+    int iter2;
+    int i, j, k;
+    boolean myswap_bytes;
+    
+    // Create a Extract interface object
+    Extract extract = null;
+    switch( type ) {
+      case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+        extract = new Extract332();
+        break;
+      case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+        extract = new Extract233rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+        extract = new Extract565();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+        extract = new Extract565rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+        extract = new Extract4444();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+        extract = new Extract4444rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+        extract = new Extract5551();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+        extract = new Extract1555rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+        extract = new Extract8888();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+        extract = new Extract8888rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+        extract = new Extract1010102();
+        break;
+      case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+        extract = new Extract2101010rev();
+        break;
+    }
+    
+    myswap_bytes = psm.getUnpackSwapBytes();
+    components = Mipmap.elements_per_group( format, type );
+    if( psm.getUnpackRowLength() > 0 ) {
+      groups_per_line = psm.getUnpackRowLength();
+    } else {
+      groups_per_line = width;
+    }
+    
+    // All formats except GL_BITMAP fall out trivially
+    if( type == GL2.GL_BITMAP ) {
+      int bit_offset;
+      int current_bit;
+      
+      rowsize = ( groups_per_line * components + 7 ) / 8;
+      padding = ( rowsize % psm.getUnpackAlignment() );
+      if( padding != 0 ) {
+        rowsize += psm.getUnpackAlignment() - padding;
+      }
+      start = psm.getUnpackSkipRows() * rowsize + ( psm.getUnpackSkipPixels() * components / 8 );
+      elements_per_line = width * components;
+      iter2 = 0;
+      for( i = 0; i < height; i++ ) {
+        iter = start;
+        userdata.position( iter ); // ****************************************
+        bit_offset = (psm.getUnpackSkipPixels() * components) % 8;
+        for( j = 0; j < elements_per_line; j++ ) {
+          // retrieve bit
+          if( psm.getUnpackLsbFirst() ) {
+            userdata.position( iter );
+            current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << bit_offset );//userdata[iter] & ( 1 << bit_offset );
+          } else {
+            current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << ( 7 - bit_offset ) );
+          }
+          if( current_bit != 0 ) {
+            if( index_format ) {
+              newimage.position( iter2 );
+              newimage.put( (short)1 );
+            } else {
+              newimage.position( iter2 );
+              newimage.put( (short)65535 );
+            }
+          } else {
+            newimage.position( iter2 );
+            newimage.put( (short)0 );
+          }
+          bit_offset++;
+          if( bit_offset == 8 ) {
+            bit_offset = 0;
+            iter++;
+          }
+          iter2++;
+        }
+        start += rowsize;
+      }
+    } else {
+      element_size = Mipmap.bytes_per_element( type );
+      group_size = element_size * components;
+      if( element_size == 1 ) {
+        myswap_bytes = false;
+      }
+      
+      rowsize = groups_per_line * group_size;
+      padding = ( rowsize % psm.getUnpackAlignment() );
+      if( padding != 0 ) {
+        rowsize += psm.getUnpackAlignment() - padding;
+      }
+      start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size;
+      elements_per_line = width * components;
+      
+      iter2 = 0;
+      for( i = 0; i < height; i++ ) {
+        iter = start;
+        userdata.position( iter ); //***************************************
+        for( j = 0; j < elements_per_line; j++ ) {
+          Type_Widget widget = new Type_Widget();
+          float[] extractComponents = new float[4];
+          userdata.position( iter );
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+              extract.extract( false, userdata /*userdata[iter]*/, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+              extract.extract( false, userdata /*userdata[iter]*/, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_BYTE ):
+              if( index_format ) {
+                newimage.put( iter2++, (short)( 0x000000FF & userdata.get() ) );//userdata[iter];
+              } else {
+                newimage.put( iter2++, (short)( 0x000000FF & userdata.get()/*userdata[iter]*/ * 257 ) );
+              }
+              break;
+            case( GL2.GL_BYTE ):
+              if( index_format ) {
+                newimage.put( iter2++, userdata.get() ); //userdata[iter];
+              } else {
+                newimage.put( iter2++, (short)(userdata.get()/*userdata[iter]*/ * 516 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+              extract.extract( myswap_bytes, userdata/*userdata[iter]*/, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+              if( myswap_bytes ) {
+                widget.setUB1( userdata.get() );
+                widget.setUB0( userdata.get() );
+              } else {
+                widget.setUB0( userdata.get() );
+                widget.setUB1( userdata.get() );
+              }
+              if( type == GL2.GL_SHORT ) {
+                if( index_format ) {
+                  newimage.put( iter2++, widget.getS0() );
+                } else {
+                  newimage.put( iter2++, (short)(widget.getS0() * 2) );
+                }
+              } else {
+                newimage.put( iter2++, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              extract.extract( myswap_bytes, userdata, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_INT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_FLOAT ):
+              if( myswap_bytes ) {
+                widget.setUB3( userdata.get() );
+                widget.setUB2( userdata.get() );
+                widget.setUB1( userdata.get() );
+                widget.setUB0( userdata.get() );
+              } else {
+                widget.setUB0( userdata.get() );
+                widget.setUB1( userdata.get() );
+                widget.setUB2( userdata.get() );
+                widget.setUB3( userdata.get() );
+              }
+              if( type == GL2.GL_FLOAT ) {
+                if( index_format ) {
+                  newimage.put( iter2++, (short)widget.getF() );
+                } else {
+                  newimage.put( iter2++, (short)(widget.getF() * 65535 ) );
+                }
+              } else if( type == GL2.GL_UNSIGNED_INT ) {
+                if( index_format ) {
+                  newimage.put( iter2++, (short)( widget.getUI() ) );
+                } else {
+                  newimage.put( iter2++, (short)( widget.getUI() >> 16 ) );
+                }
+              } else {
+                if( index_format ) {
+                  newimage.put( iter2++, (short)( widget.getI() ) );
+                } else {
+                  newimage.put( iter2++, (short)( widget.getI() >> 15 ) );
+                }
+              }
+              break;
+          }
+          iter += element_size;
+        }  // for j
+        start += rowsize;
+        // want iter pointing at start, not within, row for assertion purposes
+        iter = start;
+      } // for i
+      
+      // iterators should be one byte past end
+      if( !Mipmap.isTypePackedPixel( type ) ) {
+        assert( iter2 == ( width * height * components ) );
+      } else {
+        assert( iter2 == ( width * height * Mipmap.elements_per_group( format, 0 ) ) );
+      }
+      assert( iter == ( rowsize * height + psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size ) );
+    }
+  }
+  
+  /*
+   *  Insert array into user's data applying all pixel store modes.
+   *  Theinternal format is an array of unsigned shorts.
+   *  empty_image() because it is the opposet of fill_image().
+   */
+  public static void empty_image( PixelStorageModes psm, int width, int height, 
+                                  int format, int type, boolean index_format, 
+                                  ShortBuffer oldimage, ByteBuffer userdata ) {
+    
+    int components;
+    int element_size;
+    int rowsize;
+    int padding;
+    int groups_per_line;
+    int group_size;
+    int elements_per_line;
+    int start;
+    int iter = 0;
+    int iter2;
+    int i, j, k;
+    boolean myswap_bytes;
+    
+    // Create a Extract interface object
+    Extract extract = null;
+    switch( type ) {
+      case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+        extract = new Extract332();
+        break;
+      case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+        extract = new Extract233rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+        extract = new Extract565();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+        extract = new Extract565rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+        extract = new Extract4444();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+        extract = new Extract4444rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+        extract = new Extract5551();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+        extract = new Extract1555rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+        extract = new Extract8888();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+        extract = new Extract8888rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+        extract = new Extract1010102();
+        break;
+      case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+        extract = new Extract2101010rev();
+        break;
+    }
+    
+    myswap_bytes = psm.getPackSwapBytes();
+    components = Mipmap.elements_per_group( format, type );
+    if( psm.getPackRowLength() > 0 ) {
+      groups_per_line = psm.getPackRowLength();
+    } else {
+      groups_per_line = width;
+    }
+    
+    // all formats except GL_BITMAP fall out trivially
+    if( type == GL2.GL_BITMAP ) {
+      int bit_offset;
+      int current_bit;
+      
+      rowsize = ( groups_per_line * components + 7 ) / 8;
+      padding = ( rowsize % psm.getPackAlignment() );
+      if( padding != 0 ) {
+        rowsize += psm.getPackAlignment() - padding;
+      }
+      start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * components / 8;
+      elements_per_line = width * components;
+      iter2 = 0;
+      for( i = 0; i < height; i++ ) {
+        iter = start;
+        bit_offset = ( psm.getPackSkipPixels() * components ) % 8;
+        for( j = 0; j < elements_per_line; j++ ) {
+          if( index_format ) {
+            current_bit = oldimage.get( iter2 ) & 1;
+          } else {
+            if( oldimage.get( iter2 ) < 0 ) { // must check for negative rather than 32767
+              current_bit = 1;
+            } else {
+              current_bit = 0;
+            }
+          }
+          
+          if( current_bit != 0 ) {
+            if( psm.getPackLsbFirst() ) {
+              userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 1 << bit_offset ) ) ) );
+            } else {
+              userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 7 - bit_offset ) ) ) );
+            }
+          } else {
+            if( psm.getPackLsbFirst() ) {
+              //userdata[iter] &= ~( 1 << bit_offset );
+              userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 1 << bit_offset ) ) ) );
+            } else {
+              //userdata[iter] &= ~( 1 << ( 7 - bit_offset ) );
+              userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 7 - bit_offset ) ) ) );
+            }
+          }
+          
+          bit_offset++;
+          if( bit_offset == 8 ) {
+            bit_offset = 0;
+            iter++;
+          }
+          iter2++;
+        }
+        start += rowsize;
+      }
+    } else {
+      float shoveComponents[] = new float[4];
+      
+      element_size = Mipmap.bytes_per_element( type );
+      group_size = element_size * components;
+      if( element_size == 1 ) {
+        myswap_bytes = false;
+      }
+      
+      rowsize = groups_per_line * group_size;
+      padding = ( rowsize % psm.getPackAlignment() );
+      if( padding != 0 ) {
+        rowsize += psm.getPackAlignment() - padding;
+      }
+      start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size;
+      elements_per_line = width * components;
+      
+      iter2 = 0;
+      for( i = 0; i < height; i++ ) {
+        iter = start;
+        for( j = 0; j < elements_per_line; j++ ) {
+          Type_Widget widget = new Type_Widget();
+          
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, userdata );
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, userdata );
+              break;
+            case( GL2.GL_UNSIGNED_BYTE ):
+              if( index_format ) {
+                //userdata[iter] = (byte)oldimage[iter2++];
+                userdata.put( iter, (byte)oldimage.get(iter2++) );
+              } else {
+                //userdata[iter] = (byte)( oldimage[iter2++] >> 8 );
+                userdata.put( iter, (byte)( oldimage.get(iter2++) ) );
+              }
+              break;
+            case( GL2.GL_BYTE ):
+              if( index_format ) {
+                //userdata[iter] = (byte)oldimage[iter2++];
+                userdata.put( iter, (byte)oldimage.get(iter2++) );
+              } else {
+                //userdata[iter] = (byte)( oldimage[iter2++] >> 9 );
+                userdata.put( iter, (byte)( oldimage.get(iter2++) ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1,widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get(iter2++) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter+1] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+              if( type == GL2.GL_SHORT ) {
+                if( index_format ) {
+                  widget.setS0( oldimage.get( iter2++ ) );
+                } else {
+                  widget.setS0( (short)(oldimage.get( iter2++ ) >> 1) );
+                }
+              } else {
+                widget.setUS0( oldimage.get( iter2++ ) );
+              }
+              if( myswap_bytes ) {
+                //userdata[iter] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB0();
+                userdata.put( iter, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB0() );
+              } else {
+                //userdata[iter] = widget.getUB0();
+                //userdata[iter] = widget.getUB1();
+                userdata.put( iter, widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter+3] = widget.getUB0();
+                //userdata[iter+2] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB2();
+                //userdata[iter  ] = widget.getUB3();
+                userdata.put( iter + 3, widget.getUB0() );
+                userdata.put( iter + 2, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB2() );
+                userdata.put( iter    , widget.getUB3() );
+              } else {
+                userdata.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter+3] = widget.getUB0();
+                //userdata[iter+2] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB2();
+                //userdata[iter  ] = widget.getUB3();
+                userdata.put( iter + 3, widget.getUB0() );
+                userdata.put( iter + 2, widget.getUB1() );
+                userdata.put( iter + 2, widget.getUB2() );
+                userdata.put( iter    , widget.getUB3() );
+              } else {
+                userdata.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter+3] = widget.getUB0();
+                //userdata[iter+2] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB2();
+                //userdata[iter  ] = widget.getUB3();
+                userdata.put( iter + 3, widget.getUB0() );
+                userdata.put( iter + 2, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB2() );
+                userdata.put( iter    , widget.getUB3() );
+              } else {
+                userdata.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswap_bytes ) {
+                //userdata[iter+3] = widget.getUB0();
+                //userdata[iter+2] = widget.getUB1();
+                //userdata[iter+1] = widget.getUB2();
+                //userdata[iter  ] = widget.getUB3();
+                userdata.put( iter + 3, widget.getUB0() );
+                userdata.put( iter + 2, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB2() );
+                userdata.put( iter    , widget.getUB3() );
+              } else {
+                userdata.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_INT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_FLOAT ):
+              if( type == GL2.GL_FLOAT ) {
+                if( index_format ) {
+                  widget.setF( oldimage.get( iter2++ ) );
+                } else {
+                  widget.setF( oldimage.get( iter2++ ) / 65535.0f );
+                }
+              } else if( type == GL2.GL_UNSIGNED_INT ) {
+                if( index_format ) {
+                  widget.setUI( oldimage.get( iter2++ ) );
+                } else {
+                  widget.setUI( oldimage.get( iter2++ ) * 65537 );
+                }
+              } else {
+                if( index_format ) {
+                  widget.setI( oldimage.get( iter2++ ) );
+                } else {
+                  widget.setI( (oldimage.get( iter2++ ) * 65537) / 2 );
+                }
+              }
+              if( myswap_bytes ) {
+                userdata.put( iter + 3, widget.getUB0() );
+                userdata.put( iter + 2, widget.getUB1() );
+                userdata.put( iter + 1, widget.getUB2() );
+                userdata.put( iter    , widget.getUB3() );
+              } else {
+                userdata.put( iter    , widget.getUB0() );
+                userdata.put( iter + 1, widget.getUB1() );
+                userdata.put( iter + 2, widget.getUB2() );
+                userdata.put( iter + 3, widget.getUB3() );
+              }
+              break;
+          }
+          iter += element_size;
+        } // for j
+        start += rowsize;
+        // want iter pointing at start, not within, row for assertion purposes
+        iter = start;
+      } // for i
+      // iterators should be one byte past end
+      if( !Mipmap.isTypePackedPixel( type ) ) {
+        assert( iter2 == width * height * components );
+      } else {
+        assert( iter2 == width * height * Mipmap.elements_per_group( format, 0 ) );
+      }
+      assert( iter == rowsize * height + psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size );
+    }
+  }
+  
+  public static void fillImage3D( PixelStorageModes psm, int width, int height,
+          int depth, int format, int type, boolean indexFormat, ByteBuffer userImage,
+          ShortBuffer newImage ) {
+    boolean myswapBytes;
+    int components;
+    int groupsPerLine;
+    int elementSize;
+    int groupSize;
+    int rowSize;
+    int padding;
+    int elementsPerLine;
+    int rowsPerImage;
+    int imageSize;
+    int start, rowStart;
+    int iter = 0;
+    int iter2 = 0;
+    int ww, hh, dd, k;
+    Type_Widget widget = new Type_Widget();
+    float extractComponents[] = new float[4];
+    
+    // Create a Extract interface object
+    Extract extract = null;
+    switch( type ) {
+      case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+        extract = new Extract332();
+        break;
+      case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+        extract = new Extract233rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+        extract = new Extract565();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+        extract = new Extract565rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+        extract = new Extract4444();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+        extract = new Extract4444rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+        extract = new Extract5551();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+        extract = new Extract1555rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+        extract = new Extract8888();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+        extract = new Extract8888rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+        extract = new Extract1010102();
+        break;
+      case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+        extract = new Extract2101010rev();
+        break;
+    }
+    
+    myswapBytes = psm.getUnpackSwapBytes();
+    components = Mipmap.elements_per_group( format, type );
+    if( psm.getUnpackRowLength() > 0 ) {
+      groupsPerLine = psm.getUnpackRowLength();
+    } else {
+      groupsPerLine = width;
+    }
+    elementSize = Mipmap.bytes_per_element( type );
+    groupSize = elementSize * components;
+    if( elementSize == 1 ) {
+      myswapBytes = false;
+    }
+    
+    // 3dstuff begin
+    if( psm.getUnpackImageHeight() > 0 ) {
+      rowsPerImage = psm.getUnpackImageHeight();
+    } else {
+      rowsPerImage = height;
+    }
+    // 3dstuff end
+    
+    rowSize = groupsPerLine * groupSize;
+    padding = rowSize % psm.getUnpackAlignment();
+    if( padding != 0 ) {
+      rowSize += psm.getUnpackAlignment() - padding;
+    }
+    
+    imageSize = rowsPerImage * rowSize; // 3dstuff
+    
+    start = psm.getUnpackSkipRows() * rowSize + 
+            psm.getUnpackSkipPixels() * groupSize + 
+            psm.getUnpackSkipImages() * imageSize;
+    elementsPerLine = width * components;
+    
+    iter2 = 0;
+    for( dd = 0; dd < depth; dd++ ) {
+      rowStart = start;
+      for( hh = 0; hh < height; hh++ ) {
+        iter = rowStart;
+        for( ww = 0; ww < elementsPerLine; ww++ ) {
+          
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE ):
+              if( indexFormat ) {
+                newImage.put( iter2++, (short)(0x000000FF & userImage.get( iter ) ) );
+              } else {
+                newImage.put( iter2++, (short)((0x000000FF & userImage.get( iter ) ) * 257 ) );
+              }
+              break;
+            case( GL2.GL_BYTE ):
+              if( indexFormat ) {
+                newImage.put( iter2++, userImage.get( iter ) );
+              } else {
+                newImage.put( iter2++, (short)(userImage.get( iter ) * 516 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+              userImage.position( iter );
+              extract.extract( false, userImage, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+              userImage.position( iter );
+              extract.extract( false, userImage, extractComponents );
+              for( k = 0; k < 3; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)(extractComponents[k] * 65535) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+              if( myswapBytes ) {
+                widget.setUB0( userImage.get( iter + 1 ) );
+                widget.setUB1( userImage.get( iter ) );
+              } else {
+                widget.setUB0( userImage.get( iter ) );
+                widget.setUB1( userImage.get( iter + 1 ) );
+              }
+              if( type == GL2.GL_SHORT ) {
+                if( indexFormat ) {
+                  newImage.put( iter2++, widget.getUS0() );
+                } else {
+                  newImage.put( iter2++, (short)(widget.getUS0() * 2) );
+                }
+              } else {
+                newImage.put( iter2++, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+              userImage.position( iter );
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              extract.extract( myswapBytes, userImage, extractComponents );
+              for( k = 0; k < 4; k++ ) {
+                newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) );
+              }
+              break;
+            case( GL2.GL_INT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_FLOAT ):
+              if( myswapBytes ) {
+                widget.setUB0( userImage.get( iter + 3 ) );
+                widget.setUB1( userImage.get( iter + 2 ) );
+                widget.setUB2( userImage.get( iter + 1 ) );
+                widget.setUB3( userImage.get( iter     ) );
+              } else {
+                widget.setUB0( userImage.get( iter     ) );
+                widget.setUB1( userImage.get( iter + 1 ) );
+                widget.setUB2( userImage.get( iter + 2 ) );
+                widget.setUB3( userImage.get( iter + 3 ) );
+              }
+              if( type == GL2.GL_FLOAT ) {
+                if( indexFormat ) {
+                  newImage.put( iter2++, (short)widget.getF() );
+                } else {
+                  newImage.put( iter2++, (short)( widget.getF() * 65535.0f ) );
+                }
+              } else if( type == GL2.GL_UNSIGNED_INT ) {
+                if( indexFormat ) {
+                  newImage.put( iter2++, (short)widget.getUI() );
+                } else {
+                  newImage.put( iter2++, (short)(widget.getUI() >> 16) );
+                }
+              } else {
+                if( indexFormat ) {
+                  newImage.put( iter2++, (short)widget.getI() );
+                } else {
+                  newImage.put( iter2++, (short)(widget.getI() >> 15) );
+                }
+              }
+              break;
+            default:
+              assert( false );
+          }
+          iter += elementSize;
+        } // for ww
+        rowStart += rowSize;
+        iter = rowStart; // for assert
+      } // for hh
+      start += imageSize;
+    }// for dd
+    
+    // iterators should be one byte past end
+    if( !Mipmap.isTypePackedPixel( type ) ) {
+      assert( iter2 == width * height * depth * components );
+    } else {
+      assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) );
+    }
+    assert( iter == rowSize * height * depth + psm.getUnpackSkipRows() * rowSize + 
+            psm.getUnpackSkipPixels() * groupSize +
+            psm.getUnpackSkipImages() * imageSize );
+  }
+  
+  public static void emptyImage3D( PixelStorageModes psm, int width, int height, int depth,
+          int format, int type, boolean indexFormat, ShortBuffer oldImage, ByteBuffer userImage ) {
+    boolean myswapBytes;
+    int components;
+    int groupsPerLine;
+    int elementSize;
+    int groupSize;
+    int rowSize;
+    int padding;
+    int start, rowStart, iter;
+    int elementsPerLine;
+    int iter2;
+    int ii, jj, dd, k;
+    int rowsPerImage;
+    int imageSize;
+    Type_Widget widget = new Type_Widget();
+    float[] shoveComponents = new float[4];
+    
+    // Create a Extract interface object
+    Extract extract = null;
+    switch( type ) {
+      case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+        extract = new Extract332();
+        break;
+      case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+        extract = new Extract233rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+        extract = new Extract565();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+        extract = new Extract565rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+        extract = new Extract4444();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+        extract = new Extract4444rev();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+        extract = new Extract5551();
+        break;
+      case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+        extract = new Extract1555rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+        extract = new Extract8888();
+        break;
+      case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+        extract = new Extract8888rev();
+        break;
+      case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+        extract = new Extract1010102();
+        break;
+      case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+        extract = new Extract2101010rev();
+        break;
+    }
+    
+    iter = 0;
+    
+    myswapBytes = psm.getPackSwapBytes();
+    components = Mipmap.elements_per_group( format, type );
+    if( psm.getPackRowLength() > 0 ) {
+      groupsPerLine = psm.getPackRowLength();
+    } else {
+      groupsPerLine = width;
+    }
+    
+    elementSize = Mipmap.bytes_per_element( type );
+    groupSize = elementSize * components;
+    if( elementSize == 1 ) {
+      myswapBytes = false;
+    }
+    
+    // 3dstuff begin
+    if( psm.getPackImageHeight() > 0 ) {
+      rowsPerImage = psm.getPackImageHeight();
+    } else {
+      rowsPerImage = height;
+    }
+    
+    // 3dstuff end
+    
+    rowSize = groupsPerLine * groupSize;
+    padding = rowSize % psm.getPackAlignment();
+    if( padding != 0 ) {
+      rowSize += psm.getPackAlignment() - padding;
+    }
+    
+    imageSize = rowsPerImage * rowSize;
+    
+    start = psm.getPackSkipRows() * rowSize +
+            psm.getPackSkipPixels() * groupSize +
+            psm.getPackSkipImages() * imageSize;
+    elementsPerLine = width * components;
+    
+    iter2 = 0;
+    for( dd = 0; dd < depth; dd++ ) {
+      rowStart = start;
+      
+      for( ii = 0; ii < height; ii++ ) {
+        iter = rowStart;
+        
+        for( jj = 0; jj < elementsPerLine; jj++ ) {
+          
+          switch( type ) {
+            case( GL2.GL_UNSIGNED_BYTE ):
+              if( indexFormat ) {
+                userImage.put( iter, (byte)(oldImage.get( iter2++ ) ) );
+              } else {
+                userImage.put( iter, (byte)(oldImage.get( iter2++ ) >> 8 ) );
+              }
+              break;
+            case( GL2.GL_BYTE ):
+              if( indexFormat ) {
+                userImage.put( iter, (byte)(oldImage.get(iter2++) ) );
+              } else {
+                userImage.put( iter, (byte)(oldImage.get(iter2++) >> 9) );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, userImage );
+              break;
+            case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ):
+              for( k = 0; k < 3; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, userImage );
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.putShort( iter, widget.getUB1() );
+                userImage.putShort( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.putShort( iter, widget.getUS0() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_SHORT ):
+            case( GL2.GL_SHORT ):
+              if( type == GL2.GL_SHORT ) {
+                if( indexFormat ) {
+                  widget.setS0( (short)oldImage.get( iter2++ ) );
+                } else {
+                  widget.setS0( (short)(oldImage.get( iter2++ ) >> 1) );
+                }
+              } else {
+                widget.setUS0( (short)oldImage.get( iter2++ ) );
+              }
+              if( myswapBytes ) {
+                userImage.put( iter, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB0() );
+              } else {
+                userImage.put( iter, widget.getUB0() );
+                userImage.put( iter + 1, widget.getUB1() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter + 3, widget.getUB0() );
+                userImage.put( iter + 2, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB2() );
+                userImage.put( iter    , widget.getUB3() );
+              } else {
+                userImage.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter + 3, widget.getUB0() );
+                userImage.put( iter + 2, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB2() );
+                userImage.put( iter    , widget.getUB3() );
+              } else {
+                userImage.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_10_10_10_2 ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter + 3, widget.getUB0() );
+                userImage.put( iter + 2, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB2() );
+                userImage.put( iter    ,widget.getUB3() );
+              } else {
+                userImage.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ):
+              for( k = 0; k < 4; k++ ) {
+                shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f;
+              }
+              extract.shove( shoveComponents, 0, widget.getBuffer() );
+              if( myswapBytes ) {
+                userImage.put( iter + 3, widget.getUB0() );
+                userImage.put( iter + 2, widget.getUB2() );
+                userImage.put( iter + 1, widget.getUB1() );
+                userImage.put( iter    , widget.getUB0() );
+              } else {
+                userImage.putInt( iter, widget.getUI() );
+              }
+              break;
+            case( GL2.GL_INT ):
+            case( GL2.GL_UNSIGNED_INT ):
+            case( GL2.GL_FLOAT ):
+              if( type == GL2.GL_FLOAT ) {
+                if( indexFormat ) {
+                  widget.setF( oldImage.get( iter2++ ) );
+                } else {
+                  widget.setF( oldImage.get( iter2++ ) / 65535.0f );
+                }
+              } else if( type == GL2.GL_UNSIGNED_INT ) {
+                if( indexFormat ) {
+                  widget.setUI( oldImage.get( iter2++ ) );
+                } else {
+                  widget.setUI( oldImage.get( iter2++ ) * 65537 );
+                }
+              } else {
+                if( indexFormat ) {
+                  widget.setI( oldImage.get( iter2++ ) );
+                } else {
+                  widget.setI( ( oldImage.get( iter2++ ) * 65535 ) / 2 );
+                }
+              }
+              if( myswapBytes ) {
+                userImage.put( iter + 3, widget.getUB0() );
+                userImage.put( iter + 2, widget.getUB1() );
+                userImage.put( iter + 1, widget.getUB2() );
+                userImage.put( iter    , widget.getUB3() );
+              } else {
+                userImage.put( iter    , widget.getUB0() );
+                userImage.put( iter + 1, widget.getUB1() );
+                userImage.put( iter + 2, widget.getUB2() );
+                userImage.put( iter + 3, widget.getUB3() );
+              }
+              break;
+            default:
+              assert( false );
+          }
+          
+          iter += elementSize;
+        } // for jj
+        rowStart += rowSize;
+      } // for ii
+      start += imageSize;
+    } // for dd
+    
+    if( !Mipmap.isTypePackedPixel( type ) ) {
+      assert( iter2 == width * height * depth * components );
+    } else {
+      assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) );
+    }
+    assert( iter == rowSize * height * depth + 
+                    psm.getUnpackSkipRows() * rowSize +
+                    psm.getUnpackSkipPixels() * groupSize +
+                    psm.getUnpackSkipImages() * imageSize );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
new file mode 100644
index 000000000..4e3f6c298
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java
@@ -0,0 +1,868 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.GLException;
+import java.nio.*;
+import com.jogamp.common.nio.Buffers;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class Mipmap {
+  
+  /** Creates a new instance of Mipmap */
+  public Mipmap() {
+  }
+  
+  public static int computeLog( int value ) {
+    int i = 0;
+    // Error
+    if( value == 0 ) {
+      return( -1 );
+    }
+    for( ;; ) {
+      if( (value & 1) >= 1 ) {
+        if( value != 1 ) {
+          return( -1 );
+        }
+        return( i );
+      }
+      value = value >> 1;
+      i++;
+    }
+  }
+  
+  /* Compute the nearest power of 2 number.  This algorithm is a little strange
+   * but it works quite well.
+   */
+  public static int nearestPower( int value ) {
+    int i = 1;
+    // Error!
+    if( value == 0 ) {
+      return( -1 );
+    }
+    for( ;; ) {
+      if( value == 1 ) {
+        return( i );
+      } else if( value == 3 ) {
+        return( i * 4 );
+      }
+      value = value >> 1;
+      i *= 2;
+    }
+  }
+  
+  public static short GLU_SWAP_2_BYTES( short s ) {
+    byte b = 0;
+    b = (byte)( s >>> 8 );
+    s = (short)( s << 8 );
+    s = (short)( s | (0x00FF & b) );
+    return( s );
+  }
+  
+  public static int GLU_SWAP_4_BYTES( int i ) {
+    int t = i << 24;
+    t |= 0x00FF0000 & ( i << 8 );
+    t |= 0x0000FF00 & ( i >>> 8 );
+    t |= 0x000000FF & ( i >>> 24 );
+    return( t );
+  }
+  
+  public static float GLU_SWAP_4_BYTES( float f ) {
+    int i = Float.floatToRawIntBits( f );
+    float temp = Float.intBitsToFloat( i );
+    return( temp );
+  }
+  
+  public static int checkMipmapArgs( int internalFormat, int format, int type ) {
+    if( !legalFormat( format ) || !legalType( type ) ) {
+      return( GLU.GLU_INVALID_ENUM );
+    }
+    if( format == GL2GL3.GL_STENCIL_INDEX ) {
+      return( GLU.GLU_INVALID_ENUM );
+    }
+    if( !isLegalFormatForPackedPixelType( format, type ) ) {
+      return( GLU.GLU_INVALID_OPERATION );
+    }
+    return( 0 );
+  }
+  
+  public static boolean legalFormat( int format ) {
+    switch( format ) {
+      case( GL2.GL_COLOR_INDEX ):
+      case( GL2GL3.GL_STENCIL_INDEX ):
+      case( GL2GL3.GL_DEPTH_COMPONENT ):
+      case( GL2GL3.GL_RED ):
+      case( GL2GL3.GL_GREEN ):
+      case( GL2GL3.GL_BLUE ):
+      case( GL2GL3.GL_ALPHA ):
+      case( GL2GL3.GL_RGB ):
+      case( GL2GL3.GL_RGBA ):
+      case( GL2GL3.GL_LUMINANCE ):
+      case( GL2GL3.GL_LUMINANCE_ALPHA ):
+      case( GL2GL3.GL_BGR ):
+      case( GL2GL3.GL_BGRA ):
+        return( true );
+      default:
+        return( false );
+    }
+  }
+  
+  public static boolean legalType( int type ) {
+    switch( type ) {
+      case( GL2.GL_BITMAP ):
+      case( GL2GL3.GL_BYTE ):
+      case( GL2GL3.GL_UNSIGNED_BYTE ):
+      case( GL2GL3.GL_SHORT ):
+      case( GL2GL3.GL_UNSIGNED_SHORT ):
+      case( GL2GL3.GL_INT ):
+      case( GL2GL3.GL_UNSIGNED_INT ):
+      case( GL2GL3.GL_FLOAT ):
+      case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+      case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+      case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+      case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+      case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ):
+      case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ):
+        return( true );
+      default:
+        return( false );
+    }
+  }
+  
+  public static boolean isTypePackedPixel( int type ) {
+    assert( legalType( type ) );
+    
+    if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
+        type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+        type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
+        type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
+        type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
+        type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) {
+          return( true );
+    }
+    return( false );
+  }
+  
+  public static boolean isLegalFormatForPackedPixelType( int format, int type ) {
+    // if not a packed pixel type then return true
+    if( isTypePackedPixel( type ) ) {
+      return( true );
+    }
+    
+    // 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB
+    if( (type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV )
+        & format != GL2GL3.GL_RGB ) {
+          return( false );
+    }
+    
+    // 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
+    // 10_10_10_2/2_10_10_10_REV are only campatible with RGBA, BGRA & ARGB_EXT
+    if( ( type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+          type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+          type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+          type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+          type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
+          type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
+          type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
+          type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) &&
+          (format != GL2GL3.GL_RGBA && format != GL2GL3.GL_BGRA) ) {
+            return( false );
+    }
+    return( true );
+  }
+  
+  public static boolean isLegalLevels( int userLevel, int baseLevel, int maxLevel,
+                                            int totalLevels ) {
+    if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) ||
+                                                  (totalLevels < maxLevel) ) {
+      return( false );
+    }
+    return( true );
+  }
+  
+  /* Given user requested textures size, determine if it fits. If it doesn't then
+   * halve both sides and make the determination again until it does fit ( for
+   * IR only ).
+   * Note that proxy textures are not implemented in RE* even though they
+   * advertise the texture extension.
+   * Note that proxy textures are implemented but not according to spec in IMPACT*
+   */
+  public static void closestFit( GL gl, int target, int width, int height, int internalFormat,
+                                int format, int type, int[] newWidth, int[] newHeight ) {
+    // Use proxy textures if OpenGL version >= 1.1
+    if( Double.parseDouble( gl.glGetString( GL.GL_VERSION ).trim().substring( 0, 3 ) ) >= 1.1 ) {
+      int widthPowerOf2 = nearestPower( width );
+      int heightPowerOf2 = nearestPower( height );
+      int[] proxyWidth = new int[1];
+      boolean noProxyTextures = false;
+      
+      // Some drivers (in particular, ATI's) seem to set a GL error
+      // when proxy textures are used even though this is in violation
+      // of the spec. Guard against this and interactions with the
+      // DebugGL by watching for GLException.
+      try {
+        do {
+          // compute level 1 width & height, clamping each at 1
+          int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 );
+          int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 );
+          int proxyTarget;
+        
+          assert( widthAtLevelOne > 0 );
+          assert( heightAtLevelOne > 0 );
+        
+          // does width x height at level 1 & all their mipmaps fit?
+          if( target == GL2GL3.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) {
+            proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D;
+            gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
+                             heightAtLevelOne, 0, format, type, null );
+          } else if( (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X) || 
+                     (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || 
+                     (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || 
+                     (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || 
+                     (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || 
+                     (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) {
+            proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP;
+            gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
+                             heightAtLevelOne, 0, format, type, null );
+          } else {
+            assert( target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D );
+            proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D;
+            gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne, 
+                             0, format, type, null );
+          }
+          if(gl.isGL2GL3()) {
+            gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 );
+          } else {
+            proxyWidth[0] = 0;
+          }
+          // does it fit?
+          if( proxyWidth[0] == 0 ) { // nope, so try again with theses sizes
+            if( widthPowerOf2 == 1 && heightPowerOf2 == 1 ) {
+              /* A 1x1 texture couldn't fit for some reason so break out.  This
+               * should never happen.  But things happen.  The disadvantage with
+               * this if-statement is that we will never be aware of when this
+               * happens since it will silently branch out.
+               */
+              noProxyTextures = true;
+              break;
+            }
+            widthPowerOf2 = widthAtLevelOne;
+            heightPowerOf2 = heightAtLevelOne;
+          }
+          // else it does fit
+        } while( proxyWidth[0] == 0 );
+      } catch (GLException e) {
+        noProxyTextures = true;
+      }
+      // loop must terminate
+      // return the width & height at level 0 that fits
+      if( !noProxyTextures ) {
+        newWidth[0] = widthPowerOf2;
+        newHeight[0] = heightPowerOf2;
+        return;
+      }
+    }
+    int[] maxsize = new int[1];
+    gl.glGetIntegerv( GL2GL3.GL_MAX_TEXTURE_SIZE, maxsize , 0);
+    // clamp user's texture sizes to maximum sizes, if necessary
+    newWidth[0] = nearestPower( width );
+    if( newWidth[0] > maxsize[0] ) {
+      newWidth[0] = maxsize[0];
+    }
+    newHeight[0] = nearestPower( height );
+    if( newHeight[0] > maxsize[0] ) {
+      newHeight[0] = maxsize[0];
+    }
+  }
+  
+  public static void closestFit3D( GL gl, int target, int width, int height, int depth, 
+          int internalFormat, int format, int type, int[] newWidth, int[] newHeight,
+          int[] newDepth ) {
+    int widthPowerOf2 = nearestPower( width );
+    int heightPowerOf2 = nearestPower( height );
+    int depthPowerOf2 = nearestPower( depth );
+    int[] proxyWidth = new int[1];
+    
+    do {
+      // compute level 1 width & height & depth, clamping each at 1
+      int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2;
+      int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2;
+      int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2;
+      int proxyTarget = 0;
+      assert( widthAtLevelOne > 0 );
+      assert( heightAtLevelOne > 0 );
+      assert( depthAtLevelOne > 0 );
+      
+      // does width x height x depth at level 1 & all their mipmaps fit?
+      if( target == GL2GL3.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) {
+        proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D;
+        gl.getGL2GL3().glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne,
+                heightAtLevelOne, depthAtLevelOne, 0, format, type, null );
+      }
+      if(gl.isGL2GL3()) {
+        gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 );
+      } else {
+        proxyWidth[0] = 0;
+      }
+      // does it fit
+      if( proxyWidth[0] == 0 ) {
+        if( widthPowerOf2 == 1 && heightPowerOf2 == 1 && depthPowerOf2 == 1 ) {
+          newWidth[0] = newHeight[0] = newDepth[0] = 1;
+          return;
+        }
+        widthPowerOf2 = widthAtLevelOne;
+        heightPowerOf2 = heightAtLevelOne;
+        depthPowerOf2 = depthAtLevelOne;
+      }
+    } while( proxyWidth[0] == 0 );
+    // loop must terminate
+    
+    // return the width & height at level 0 that fits
+    newWidth[0] = widthPowerOf2;
+    newHeight[0] = heightPowerOf2;
+    newDepth[0] = depthPowerOf2;
+  }
+  
+  public static int elements_per_group( int format, int type ) {
+    // Return the number of elements per grtoup of a specified gromat
+    
+    // If the type is packedpixels then answer is 1
+    if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ||
+        type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ||
+        type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ||
+        type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ||
+        type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ||
+        type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ||
+        type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) {
+          return( 1 );
+    }
+    
+    // Types are not packed pixels so get elements per group
+    switch( format ) {
+      case( GL2GL3.GL_RGB ):
+      case( GL2GL3.GL_BGR ):
+        return( 3 );
+      case( GL2GL3.GL_LUMINANCE_ALPHA ):
+        return( 2 );
+      case( GL2GL3.GL_RGBA ):
+      case( GL2GL3.GL_BGRA ):
+        return( 4 );
+      default:
+        return( 1 );
+    }
+  }
+  
+  public static int bytes_per_element( int type ) {
+    // return the number of bytes per element, based on the element type
+    
+    switch( type ) {
+      case( GL2.GL_BITMAP ):
+      case( GL2GL3.GL_BYTE ):
+      case( GL2GL3.GL_UNSIGNED_BYTE ):
+      case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ):
+      case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ):
+        return( 1 );
+      case( GL2GL3.GL_SHORT ):
+      case( GL2GL3.GL_UNSIGNED_SHORT ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ):
+      case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ):
+        return( 2 );
+      case( GL2GL3.GL_INT ):
+      case( GL2GL3.GL_UNSIGNED_INT ):
+      case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ):
+      case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ):
+      case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ):
+      case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ):
+      case( GL2GL3.GL_FLOAT ):
+        return( 4 );
+      default:
+        return( 4 );
+    }
+  }
+  
+  public static boolean is_index( int format ) {
+    return( format == GL2.GL_COLOR_INDEX || format == GL2GL3.GL_STENCIL_INDEX );
+  }
+  
+  /* Compute memory required for internal packed array of data of given type and format. */
+  
+  public static int image_size( int width, int height, int format, int type ) {
+    int bytes_per_row;
+    int components;
+    
+    assert( width > 0 );
+    assert( height > 0 );
+    components = elements_per_group( format, type );
+    if( type == GL2.GL_BITMAP ) {
+      bytes_per_row = (width + 7) / 8;
+    } else {
+      bytes_per_row = bytes_per_element( type ) * width;
+    }
+    return( bytes_per_row * height * components );
+  }
+  
+  public static int imageSize3D( int width, int height, int depth, int format, int type ) {
+    int components = elements_per_group( format, type );
+    int bytes_per_row = bytes_per_element( type ) * width;
+    
+    assert( width > 0 && height > 0 && depth > 0 );
+    assert( type != GL2.GL_BITMAP );
+    
+    return( bytes_per_row * height * depth * components );
+  }
+  
+  public static void retrieveStoreModes( GL gl, PixelStorageModes psm ) {
+    int[] a = new int[1];
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0);
+    psm.setUnpackAlignment( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0);
+    psm.setUnpackRowLength( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0);
+    psm.setUnpackSkipRows( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0);
+    psm.setUnpackSkipPixels( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
+    psm.setUnpackLsbFirst( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
+    psm.setUnpackSwapBytes( ( a[0] == 1 ) );
+    
+    gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0);
+    psm.setPackAlignment( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
+    psm.setPackRowLength( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0);
+    psm.setPackSkipRows( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0);
+    psm.setPackSkipPixels( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0);
+    psm.setPackLsbFirst( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0);
+    psm.setPackSwapBytes( ( a[0] == 1 ) );
+  }
+  
+  public static void retrieveStoreModes3D( GL gl, PixelStorageModes psm ) {
+    int[] a = new int[1];
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0);
+    psm.setUnpackAlignment( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0);
+    psm.setUnpackRowLength( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0);
+    psm.setUnpackSkipRows( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0);
+    psm.setUnpackSkipPixels( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0);
+    psm.setUnpackLsbFirst( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0);
+    psm.setUnpackSwapBytes( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_IMAGES, a, 0);
+    psm.setUnpackSkipImages( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_UNPACK_IMAGE_HEIGHT, a, 0);
+    psm.setUnpackImageHeight( a[0] );
+    
+    gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0);
+    psm.setPackAlignment( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
+    psm.setPackRowLength( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0);
+    psm.setPackSkipRows( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0 );
+    psm.setPackSkipPixels( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0 );
+    psm.setPackLsbFirst( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0 );
+    psm.setPackSwapBytes( ( a[0] == 1 ) );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_IMAGES, a, 0 );
+    psm.setPackSkipImages( a[0] );
+    gl.glGetIntegerv( GL2GL3.GL_PACK_IMAGE_HEIGHT, a, 0 );
+    psm.setPackImageHeight( a[0] );
+  }
+  
+  public static int gluScaleImage( GL gl, int format, int widthin, int heightin, 
+          int typein, ByteBuffer datain, int widthout, int heightout, 
+          int typeout, ByteBuffer dataout ) {
+    int datainPos = datain.position();
+    int dataoutPos = dataout.position();
+    try {
+
+      int components;
+      ByteBuffer beforeimage;
+      ByteBuffer afterimage;
+      PixelStorageModes psm = new PixelStorageModes();
+    
+      if( (widthin == 0)  || (heightin == 0) || (widthout == 0) || (heightout == 0) ) {
+        return( 0 );
+      }
+      if( (widthin < 0) || (heightin < 0) || (widthout < 0) || (heightout < 0) ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+      if( !legalFormat( format ) || !legalType( typein ) || !legalType( typeout ) ) {
+        return( GLU.GLU_INVALID_ENUM );
+      }
+      if( !isLegalFormatForPackedPixelType( format, typein ) ) {
+        return( GLU.GLU_INVALID_OPERATION );
+      }
+      if( !isLegalFormatForPackedPixelType( format, typeout ) ) {
+        return( GLU.GLU_INVALID_OPERATION );
+      }
+      beforeimage = Buffers.newDirectByteBuffer( image_size( widthin, heightin, format, GL2GL3.GL_UNSIGNED_SHORT ) );
+      afterimage = Buffers.newDirectByteBuffer( image_size( widthout, heightout, format, GL2GL3.GL_UNSIGNED_SHORT ) );
+      if( beforeimage == null || afterimage == null ) {
+        return( GLU.GLU_OUT_OF_MEMORY );
+      }
+    
+      retrieveStoreModes( gl, psm );
+      Image.fill_image( psm, widthin, heightin, format, typein, is_index( format ), datain, beforeimage.asShortBuffer() );
+      components = elements_per_group( format, 0 );
+      ScaleInternal.scale_internal( components, widthin, heightin, beforeimage.asShortBuffer(), widthout, heightout, afterimage.asShortBuffer() );
+      Image.empty_image( psm, widthout, heightout, format, typeout, is_index( format ), afterimage.asShortBuffer(), dataout );
+    
+      return( 0 );
+    } finally {
+      datain.position(datainPos);
+      dataout.position(dataoutPos);
+    }
+  }
+  
+  public static int gluBuild1DMipmapLevels( GL gl, int target, int internalFormat,
+                          int width, int format, int type, int userLevel, int baseLevel,
+                          int maxLevel, ByteBuffer data ) {
+    int dataPos = data.position();
+    try {
+
+      int levels;
+    
+      int rc = checkMipmapArgs( internalFormat, format, type );
+      if( rc != 0 ) {
+        return( rc );
+      }
+    
+      if( width < 1 ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      levels = computeLog( width );
+    
+      levels += userLevel;
+      if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, width,
+              width, format, type, userLevel, baseLevel, maxLevel, data ) );
+    } finally {
+      data.position(dataPos);
+    }
+  }
+  
+  public static int gluBuild1DMipmaps( GL gl, int target, int internalFormat, int width,
+              int format, int type, ByteBuffer data ) {
+    int dataPos = data.position();
+
+    try {
+      int[] widthPowerOf2 = new int[1];
+      int levels;
+      int[] dummy = new int[1];
+    
+      int rc = checkMipmapArgs( internalFormat, format, type );
+      if( rc != 0 ) {
+        return( rc );
+      }
+    
+      if( width < 1 ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      closestFit( gl, target, width, 1, internalFormat, format, type, widthPowerOf2, dummy );
+      levels = computeLog( widthPowerOf2[0] );
+    
+      return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, 
+                    width, widthPowerOf2[0], format, type, 0, 0, levels, data ) );
+    } finally {
+      data.position(dataPos);
+    }
+  }
+
+ 
+  public static int gluBuild2DMipmapLevels( GL gl, int target, int internalFormat,
+          int width, int height, int format, int type, int userLevel,
+          int baseLevel, int maxLevel, Object data ) {
+    int dataPos = 0;
+
+    int level, levels;
+    
+    int rc = checkMipmapArgs( internalFormat, format, type );
+    if( rc != 0 ) {
+      return( rc );
+    }
+    
+    if( width < 1 || height < 1 ) {
+      return( GLU.GLU_INVALID_VALUE );
+    }
+    
+    levels = computeLog( width );
+    level = computeLog( height );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    levels += userLevel;
+    if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
+      return( GLU.GLU_INVALID_VALUE );
+    }
+    
+    //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
+    ByteBuffer buffer = null;
+    if( data instanceof ByteBuffer ) {
+        buffer = (ByteBuffer)data;
+        dataPos = buffer.position();
+    } else if( data instanceof byte[] ) {
+      byte[] array = (byte[])data;
+      buffer = ByteBuffer.allocateDirect(array.length);
+      buffer.put(array);
+    } else if( data instanceof short[] ) {
+        short[] array = (short[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 2 );
+        ShortBuffer sb = buffer.asShortBuffer();
+        sb.put( array );
+    } else if( data instanceof int[] ) {
+        int[] array = (int[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 4 );
+        IntBuffer ib = buffer.asIntBuffer();
+        ib.put( array );
+    } else if( data instanceof float[] ) {
+        float[] array = (float[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 4 );
+        FloatBuffer fb = buffer.asFloatBuffer();
+        fb.put( array );
+    }
+    
+    try {
+      return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
+              width, height, width, height, format, type, userLevel, baseLevel,
+              maxLevel, buffer ) );
+    } finally {
+      buffer.position(dataPos);
+    }
+  }
+
+ 
+  public static int gluBuild2DMipmaps( GL gl, int target, int internalFormat,
+          int width, int height, int format, int type, Object data ) {
+    int dataPos = 0;
+
+    int[] widthPowerOf2 = new int[1];
+    int[] heightPowerOf2 = new int[1];
+    int level, levels;
+    
+    int rc = checkMipmapArgs( internalFormat, format, type );
+    if( rc != 0 ) {
+      return( rc );
+    }
+    
+    if( width < 1 || height < 1 ) {
+      return( GLU.GLU_INVALID_VALUE );
+    }
+    
+    closestFit( gl, target, width, height, internalFormat, format, type, 
+            widthPowerOf2, heightPowerOf2 );
+    
+    levels = computeLog( widthPowerOf2[0] );
+    level = computeLog( heightPowerOf2[0] );
+    if( level > levels ) {
+      levels = level;
+    }
+    
+    //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data );
+    ByteBuffer buffer = null;
+    if( data instanceof ByteBuffer ) {
+        buffer = (ByteBuffer)data;
+        dataPos = buffer.position();
+    } else if( data instanceof byte[] ) {
+      byte[] array = (byte[])data;
+      buffer = ByteBuffer.allocateDirect(array.length);
+      buffer.put(array);
+    } else if( data instanceof short[] ) {
+        short[] array = (short[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 2 );
+        ShortBuffer sb = buffer.asShortBuffer();
+        sb.put( array );
+    } else if( data instanceof int[] ) {
+        int[] array = (int[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 4 );
+        IntBuffer ib = buffer.asIntBuffer();
+        ib.put( array );
+    } else if( data instanceof float[] ) {
+        float[] array = (float[])data;
+        buffer = ByteBuffer.allocateDirect( array.length * 4 );
+        FloatBuffer fb = buffer.asFloatBuffer();
+        fb.put( array );
+    }
+    
+    try {
+      return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat, 
+              width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0, 
+              0, levels, buffer ) );
+    } finally {
+      buffer.position(dataPos);
+    }
+  }
+ 
+ 
+  public static int gluBuild3DMipmaps( GL gl, int target, int internalFormat,
+          int width, int height, int depth, int format, int type, ByteBuffer data ) {
+    int dataPos = data.position();
+    try {
+
+      int[] widthPowerOf2 = new int[1];
+      int[] heightPowerOf2 = new int[1];
+      int[] depthPowerOf2 = new int[1];
+      int level, levels;
+    
+      int rc = checkMipmapArgs( internalFormat, format, type );
+      if( rc != 0 ) {
+        return( rc );
+      }
+    
+      if( width < 1 || height < 1 || depth < 1 ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      if( type == GL2.GL_BITMAP ) {
+        return( GLU.GLU_INVALID_ENUM );
+      }
+    
+      closestFit3D( gl, target, width, height, depth, internalFormat, format,
+                    type, widthPowerOf2, heightPowerOf2, depthPowerOf2 );
+    
+      levels = computeLog( widthPowerOf2[0] );
+      level = computeLog( heightPowerOf2[0] );
+      if( level > levels ) {
+        levels = level;
+      }
+      level = computeLog( depthPowerOf2[0] );
+      if( level > levels ) {
+        levels = level;
+      }
+    
+      return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
+              height, depth, widthPowerOf2[0], heightPowerOf2[0], depthPowerOf2[0],
+              format, type, 0, 0, levels, data ) );
+    } finally {
+      data.position(dataPos);
+    }
+  }
+  
+  public static int gluBuild3DMipmapLevels( GL gl, int target, int internalFormat,
+          int width, int height, int depth, int format, int type, int userLevel,
+          int baseLevel, int maxLevel, ByteBuffer data ) {
+    int dataPos = data.position();
+    try {
+      int level, levels;
+    
+      int rc = checkMipmapArgs( internalFormat, format, type );
+      if( rc != 0 ) {
+        return( rc );
+      }
+    
+      if( width < 1 || height < 1 || depth < 1 ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      if( type == GL2.GL_BITMAP ) {
+        return( GLU.GLU_INVALID_ENUM );
+      }
+    
+      levels = computeLog( width );
+      level = computeLog( height );
+      if( level > levels ) {
+        levels = level;
+      }
+      level = computeLog( depth );
+      if( level > levels ) {
+        levels = level;
+      }
+    
+      levels += userLevel;
+      if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) {
+        return( GLU.GLU_INVALID_VALUE );
+      }
+    
+      return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width,
+              height, depth, width, height, depth, format, type, userLevel,
+              baseLevel, maxLevel, data ) );
+    } finally {
+      data.position(dataPos);
+    }
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
new file mode 100644
index 000000000..43b5c5691
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java
@@ -0,0 +1,426 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class PixelStorageModes {
+
+  /**
+   * Holds value of property packAlignment.
+   */
+  private int packAlignment;
+
+  /**
+   * Holds value of property packRowLength.
+   */
+  private int packRowLength;
+
+  /**
+   * Holds value of property packSkipRows.
+   */
+  private int packSkipRows;
+
+  /**
+   * Holds value of property packSkipPixels.
+   */
+  private int packSkipPixels;
+
+  /**
+   * Holds value of property packLsbFirst.
+   */
+  private boolean packLsbFirst;
+
+  /**
+   * Holds value of property packSwapBytes.
+   */
+  private boolean packSwapBytes;
+
+  /**
+   * Holds value of property packSkipImages.
+   */
+  private int packSkipImages;
+
+  /**
+   * Holds value of property packImageHeight.
+   */
+  private int packImageHeight;
+
+  /**
+   * Holds value of property unpackAlignment.
+   */
+  private int unpackAlignment;
+
+  /**
+   * Holds value of property unpackRowLength.
+   */
+  private int unpackRowLength;
+
+  /**
+   * Holds value of property unpackSkipRows.
+   */
+  private int unpackSkipRows;
+
+  /**
+   * Holds value of property unpackSkipPixels.
+   */
+  private int unpackSkipPixels;
+
+  /**
+   * Holds value of property unpackLsbFirst.
+   */
+  private boolean unpackLsbFirst;
+
+  /**
+   * Holds value of property unpackSwapBytes.
+   */
+  private boolean unpackSwapBytes;
+
+  /**
+   * Holds value of property unpackSkipImages.
+   */
+  private int unpackSkipImages;
+
+  /**
+   * Holds value of property unpackImageHeight.
+   */
+  private int unpackImageHeight;
+  
+  /** Creates a new instance of PixelStorageModes */
+  public PixelStorageModes() {
+  }
+
+  /**
+   * Getter for property packAlignment.
+   * @return Value of property packAlignment.
+   */
+  public int getPackAlignment() {
+
+    return this.packAlignment;
+  }
+
+  /**
+   * Setter for property packAlignment.
+   * @param packAlignment New value of property packAlignment.
+   */
+  public void setPackAlignment(int packAlignment) {
+
+    this.packAlignment = packAlignment;
+  }
+
+  /**
+   * Getter for property packRowLength.
+   * @return Value of property packRowLength.
+   */
+  public int getPackRowLength() {
+
+    return this.packRowLength;
+  }
+
+  /**
+   * Setter for property packRowLength.
+   * @param packRowLength New value of property packRowLength.
+   */
+  public void setPackRowLength(int packRowLength) {
+
+    this.packRowLength = packRowLength;
+  }
+
+  /**
+   * Getter for property packSkipRows.
+   * @return Value of property packSkipRows.
+   */
+  public int getPackSkipRows() {
+
+    return this.packSkipRows;
+  }
+
+  /**
+   * Setter for property packSkipRows.
+   * @param packSkipRows New value of property packSkipRows.
+   */
+  public void setPackSkipRows(int packSkipRows) {
+
+    this.packSkipRows = packSkipRows;
+  }
+
+  /**
+   * Getter for property packSkipPixels.
+   * @return Value of property packSkipPixels.
+   */
+  public int getPackSkipPixels() {
+
+    return this.packSkipPixels;
+  }
+
+  /**
+   * Setter for property packSkipPixels.
+   * @param packSkipPixels New value of property packSkipPixels.
+   */
+  public void setPackSkipPixels(int packSkipPixels) {
+
+    this.packSkipPixels = packSkipPixels;
+  }
+
+  /**
+   * Getter for property packLsbFirst.
+   * @return Value of property packLsbFirst.
+   */
+  public boolean getPackLsbFirst() {
+
+    return this.packLsbFirst;
+  }
+
+  /**
+   * Setter for property packLsbFirst.
+   * @param packLsbFirst New value of property packLsbFirst.
+   */
+  public void setPackLsbFirst(boolean packLsbFirst) {
+
+    this.packLsbFirst = packLsbFirst;
+  }
+
+  /**
+   * Getter for property packSwapBytes.
+   * @return Value of property packSwapBytes.
+   */
+  public boolean getPackSwapBytes() {
+
+    return this.packSwapBytes;
+  }
+
+  /**
+   * Setter for property packSwapBytes.
+   * @param packSwapBytes New value of property packSwapBytes.
+   */
+  public void setPackSwapBytes(boolean packSwapBytes) {
+
+    this.packSwapBytes = packSwapBytes;
+  }
+
+  /**
+   * Getter for property packSkipImages.
+   * @return Value of property packSkipImages.
+   */
+  public int getPackSkipImages() {
+
+    return this.packSkipImages;
+  }
+
+  /**
+   * Setter for property packSkipImages.
+   * @param packSkipImages New value of property packSkipImages.
+   */
+  public void setPackSkipImages(int packSkipImages) {
+
+    this.packSkipImages = packSkipImages;
+  }
+
+  /**
+   * Getter for property packImageHeight.
+   * @return Value of property packImageHeight.
+   */
+  public int getPackImageHeight() {
+
+    return this.packImageHeight;
+  }
+
+  /**
+   * Setter for property packImageHeight.
+   * @param packImageHeight New value of property packImageHeight.
+   */
+  public void setPackImageHeight(int packImageHeight) {
+
+    this.packImageHeight = packImageHeight;
+  }
+
+  /**
+   * Getter for property unpackAlignment.
+   * @return Value of property unpackAlignment.
+   */
+  public int getUnpackAlignment() {
+
+    return this.unpackAlignment;
+  }
+
+  /**
+   * Setter for property unpackAlignment.
+   * @param unpackAlignment New value of property unpackAlignment.
+   */
+  public void setUnpackAlignment(int unpackAlignment) {
+
+    this.unpackAlignment = unpackAlignment;
+  }
+
+  /**
+   * Getter for property unpackRowLength.
+   * @return Value of property unpackRowLength.
+   */
+  public int getUnpackRowLength() {
+
+    return this.unpackRowLength;
+  }
+
+  /**
+   * Setter for property unpackRowLength.
+   * @param unpackRowLength New value of property unpackRowLength.
+   */
+  public void setUnpackRowLength(int unpackRowLength) {
+
+    this.unpackRowLength = unpackRowLength;
+  }
+
+  /**
+   * Getter for property unpackSkipRows.
+   * @return Value of property unpackSkipRows.
+   */
+  public int getUnpackSkipRows() {
+
+    return this.unpackSkipRows;
+  }
+
+  /**
+   * Setter for property unpackSkipRows.
+   * @param unpackSkipRows New value of property unpackSkipRows.
+   */
+  public void setUnpackSkipRows(int unpackSkipRows) {
+
+    this.unpackSkipRows = unpackSkipRows;
+  }
+
+  /**
+   * Getter for property unpackSkipPixels.
+   * @return Value of property unpackSkipPixels.
+   */
+  public int getUnpackSkipPixels() {
+
+    return this.unpackSkipPixels;
+  }
+
+  /**
+   * Setter for property unpackSkipPixels.
+   * @param unpackSkipPixels New value of property unpackSkipPixels.
+   */
+  public void setUnpackSkipPixels(int unpackSkipPixels) {
+
+    this.unpackSkipPixels = unpackSkipPixels;
+  }
+
+  /**
+   * Getter for property unpackLsbFirst.
+   * @return Value of property unpackLsbFirst.
+   */
+  public boolean getUnpackLsbFirst() {
+
+    return this.unpackLsbFirst;
+  }
+
+  /**
+   * Setter for property unpackLsbFirst.
+   * @param unpackLsbFirst New value of property unpackLsbFirst.
+   */
+  public void setUnpackLsbFirst(boolean unpackLsbFirst) {
+
+    this.unpackLsbFirst = unpackLsbFirst;
+  }
+
+  /**
+   * Getter for property unpackSwapBytes.
+   * @return Value of property unpackSwapBytes.
+   */
+  public boolean getUnpackSwapBytes() {
+
+    return this.unpackSwapBytes;
+  }
+
+  /**
+   * Setter for property unpackSwapBytes.
+   * @param unpackSwapBytes New value of property unpackSwapBytes.
+   */
+  public void setUnpackSwapBytes(boolean unpackSwapBytes) {
+
+    this.unpackSwapBytes = unpackSwapBytes;
+  }
+
+  /**
+   * Getter for property unpackSkipImages.
+   * @return Value of property unpackSkipImages.
+   */
+  public int getUnpackSkipImages() {
+
+    return this.unpackSkipImages;
+  }
+
+  /**
+   * Setter for property unpackSkipImages.
+   * @param unpackSkipImages New value of property unpackSkipImages.
+   */
+  public void setUnpackSkipImages(int unpackSkipImages) {
+
+    this.unpackSkipImages = unpackSkipImages;
+  }
+
+  /**
+   * Getter for property unpackImageHeight.
+   * @return Value of property unpackImageHeight.
+   */
+  public int getUnpackImageHeight() {
+
+    return this.unpackImageHeight;
+  }
+
+  /**
+   * Setter for property unpackImageHeight.
+   * @param unpackImageHeight New value of property unpackImageHeight.
+   */
+  public void setUnpackImageHeight(int unpackImageHeight) {
+
+    this.unpackImageHeight = unpackImageHeight;
+  }
+  
+  
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
new file mode 100644
index 000000000..804845fe2
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java
@@ -0,0 +1,2447 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.glu.GLU;
+import java.nio.*;
+import com.jogamp.common.nio.Buffers;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class ScaleInternal {
+  
+  public static final float UINT_MAX = (float)(0x00000000FFFFFFFF);
+  
+  public static void scale_internal( int components, int widthin, int heightin,
+          ShortBuffer datain, int widthout, int heightout, ShortBuffer dataout ) {
+    float x, lowx, highx, convx, halfconvx;
+    float y, lowy, highy, convy, halfconvy;
+    float xpercent, ypercent;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, yint, xint, xindex, yindex;
+    int temp;
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage( components, widthin, heightin, datain, dataout );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    halfconvx = convx / 2;
+    halfconvy = convy / 2;
+    for( i = 0; i < heightout; i++ ) {
+      y = convy * ( i + 0.5f );
+      if( heightin > heightout ) {
+        highy = y + halfconvy;
+        lowy = y - halfconvy;
+      } else {
+        highy = y + 0.5f;
+        lowy = y - 0.5f;
+      }
+      for( j = 0; j < widthout; j++ ) {
+        x = convx * ( j + 0.5f );
+        if( widthin > widthout ) {
+          highx = x + halfconvx;
+          lowx = x - halfconvx;
+        } else {
+          highx = x + 0.5f;
+          lowx = x - 0.5f;
+        }
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        area = 0.0f;
+        
+        y = lowy;
+        yint = (int)Math.floor( y );
+        while( y < highy ) {
+          yindex = ( yint + heightin ) % heightin;
+          if( highy < yint + 1 ) {
+            ypercent = highy - y;
+          } else {
+            ypercent = yint + 1 - y;
+          }
+          
+          x = lowx;
+          xint = (int)Math.floor( x );
+          
+          while( x < highx ) {
+            xindex = ( xint + widthin ) % widthin;
+            if( highx < xint + 1 ) {
+              xpercent = highx -x;
+            } else {
+              xpercent = xint + 1 - x;
+            }
+            
+            percent = xpercent * ypercent;
+            area += percent;
+            temp = ( xindex + ( yindex * widthin) ) * components;
+            for( k = 0; k < components; k++ ) {
+              totals[k] += datain.get( temp + k ) * percent; 
+            }
+            
+            xint++;
+            x = xint;
+          }
+          yint++;
+          y = yint;
+        }
+        
+        temp = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          // totals[] should be rounded in the case of enlarging an RGB
+          // ramp when the type is 332 or 4444
+          dataout.put(  temp + k, (short)((totals[k] + 0.5f) / area) );
+        }
+      }
+    }
+  }
+  
+  public static void scale_internal_ubyte( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              ByteBuffer dataout, int element_size, int ysize, int group_size ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_ubyte( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += ( 0x000000FF & datain.get() ) * y_percent;
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += ( 0x000000FF & datain.get() ) * y_percent;
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              float f = 0.0f;
+              datain.position( left );
+              f = ( 0x000000FF & datain.get() ) * ( 1.0f - lowx_float );
+              datain.position( right );
+              f += ( 0x000000FF & datain.get() ) * highx_float;
+              totals[k] += f;
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += ( 0x000000FF & datain.get() ) * x_percent;
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += ( 0x000000FF & datain.get() ) * y_percent;
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += ( 0x000000FF & datain.get() ) * percent;
+          }
+        }
+
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += ( 0x000000FF & datain.get() );
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (byte)(totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_byte( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              ByteBuffer dataout, int element_size, int ysize,
+                              int group_size ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_byte( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += datain.get() * y_percent;
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += datain.get() * y_percent;
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              float f = 0.0f;
+              datain.position( left );
+              f = datain.get() * ( 1 - lowx_float );
+              datain.position( right );
+              f += datain.get() * highx_float;
+              totals[k] += f;
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += datain.get() * x_percent;
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += datain.get() * y_percent;
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            totals[k] += datain.get() * percent;
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              totals[k] += datain.get();
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (byte)(totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_ushort( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              ShortBuffer dataout, int element_size, int ysize, 
+                              int group_size, boolean myswap_bytes ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_ushort( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size, myswap_bytes );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent;
+            } else {
+              totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent;
+            }
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * y_percent;
+              } else {
+                totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += ( 0x0000FFFF & (Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent;
+            } else {
+              totals[k] += ( 0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent;
+            } else {
+              totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent;
+              } else {
+                totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent;
+            } else {
+              totals[k] += ( 0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              if( myswap_bytes ) {
+                datain.position( left );
+                float f = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * ( 1 - lowx_float );
+                datain.position( right );
+                f += ((0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * highx_float);
+                totals[k] += f;
+              } else {
+                datain.position( left );
+                float f = ((0x0000FFFF & datain.getShort()) * ( 1 - lowx_float ));
+                datain.position( right );
+                f += ((0x0000FFFF & datain.getShort()) * highx_float);
+                totals[k] += f;
+              }
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent;
+            } else {
+              totals[k] += (0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * x_percent;
+              } else {
+                totals[k] += (0x0000FFFF & datain.getShort()) * x_percent;
+              }
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent;
+            } else {
+              totals[k] += (0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent;
+            } else {
+              totals[k] += (0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent;
+              } else {
+                totals[k] += (0x0000FFFF & datain.getShort()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent;
+            } else {
+              totals[k] += (0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent;
+            } else {
+              totals[k] += (0x0000FFFF & datain.getShort()) * percent;
+            }
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()));
+              } else {
+                totals[k] += (0x0000FFFF & datain.getShort());
+              }
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (short)(totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_short( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout,
+                              ShortBuffer dataout, int element_size, int ysize, 
+                              int group_size, boolean myswap_bytes ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    int swapbuf; // unsigned buffer
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_short( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size, myswap_bytes );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getShort() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getShort() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              if( myswap_bytes ) {
+                datain.position( left );
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf * ( 1 - lowx_float );
+                datain.position( right );
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf * highx_float;
+              } else {
+                datain.position( left );
+                totals[k] += datain.getShort() * ( 1 - lowx_float );
+                datain.position( right );
+                totals[k] += datain.getShort() * highx_float;
+              }
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort());
+                totals[k] += swapbuf * x_percent;
+              } else {
+                totals[k] += datain.getShort() * x_percent;
+              }
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getShort() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getShort() * percent;
+            }
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() );
+                totals[k] += swapbuf;
+              } else {
+                totals[k] += datain.getShort();
+              }
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (short)(totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_uint( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              IntBuffer dataout, int element_size, int ysize, 
+                              int group_size, boolean myswap_bytes ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_uint( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size, myswap_bytes );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent;
+              } else {
+                totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent;
+              } else {
+                totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              if( myswap_bytes ) {
+                datain.position( left );
+                totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * ( 1 - lowx_float ));
+                datain.position( right );
+                totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * highx_float);
+              } else {
+                datain.position( left );
+                totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * ( 1 - lowx_float ));
+                datain.position( right );
+                totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * highx_float);
+              }
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * x_percent;
+              } else {
+                totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * x_percent;
+              }
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * y_percent;
+              } else {
+                totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            long tempInt0 = ( 0xFFFFFFFFL & datain.getInt( temp_index ) );
+            datain.position( temp_index );
+            long tempInt1 = ( 0xFFFFFFFFL & datain.getInt() );
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent;
+            } else {
+              totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent;
+            }
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()));
+              } else {
+                totals[k] += (0x00000000FFFFFFFF & datain.getInt());
+              }
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        float value = 0.0f;
+        for( k = 0; k < components; k++ ) {
+          value = totals[k] / area;
+          dataout.position( outindex + k );
+          if( value >= UINT_MAX ) {
+            dataout.put( (int)value );
+          } else {
+            dataout.put( (int)(totals[k] / area) );
+          }
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_int( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              IntBuffer dataout, int element_size, int ysize, 
+                              int group_size, boolean myswap_bytes ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    long swapbuf; // unsigned buffer
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_int( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size, myswap_bytes );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getInt() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getInt() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              if( myswap_bytes ) {
+                datain.position( left );
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * ( 1 - lowx_float );
+                datain.position( right );
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * highx_float;
+              } else {
+                datain.position( left );
+                totals[k] += (datain.getInt() * ( 1 - lowx_float ));
+                datain.position( right );
+                totals[k] += (datain.getInt() * highx_float);
+              }
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * x_percent;
+              } else {
+                totals[k] += datain.getInt() * x_percent;
+              }
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getInt() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getInt() * percent;
+            }
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() );
+                totals[k] += swapbuf;
+              } else {
+                totals[k] += datain.getInt();
+              }
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (int)(totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scale_internal_float( int components, int widthin, int heightin,
+                              ByteBuffer datain, int widthout, int heightout, 
+                              FloatBuffer dataout, int element_size, int ysize, 
+                              int group_size, boolean myswap_bytes ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    // Max components in a format is 4, so...
+    float[] totals = new float[4];
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outindex;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    float swapbuf; // unsigned buffer
+    
+    if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) {
+      HalveImage.halveImage_float( components, widthin, heightin, datain, dataout, 
+                        element_size, ysize, group_size, myswap_bytes );
+      return;
+    }
+    convy = (float)heightin / heightout;
+    convx = (float)widthin / widthout;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convy_float;
+    
+    for( i = 0; i < heightout; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightin)
+        highy_int = heightin - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthout; j++ ) {
+        
+        // Ok, now apply box filter to box that goes from (lowx, lowy)
+        // to (highx, highy) on input data into this pixel on output
+        // data.
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // caulate the value for pixels in the 1st row
+        xindex = lowx_int * group_size;
+        if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * ysize;
+          percent = y_percent * ( 1 - lowx_float );
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getFloat() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          right = temp;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          
+          // calculate the value for pixels in the last row
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getFloat() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          
+          // calculate the value for the pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += ysize;
+            right += ysize;
+            for( k = 0; k < components; k++, left += element_size, right += element_size ) {
+              if( myswap_bytes ) {
+                datain.position( left );
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * ( 1 - lowx_float );
+                datain.position( right );
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * highx_float;
+              } else {
+                datain.position( left );
+                totals[k] += (datain.getFloat() * ( 1 - lowx_float ));
+                datain.position( right );
+                totals[k] += (datain.getFloat() * highx_float);
+              }
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float) * x_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += ysize;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * x_percent;
+              } else {
+                totals[k] += datain.getFloat() * x_percent;
+              }
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += ysize;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += group_size;
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf * y_percent;
+              } else {
+                totals[k] += datain.getFloat() * y_percent;
+              }
+            }
+          }
+          temp += group_size;
+          percent = y_percent * highx_float;
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + (lowy_int * ysize);
+          for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+            datain.position( temp_index );
+            if( myswap_bytes ) {
+              swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+              totals[k] += swapbuf * percent;
+            } else {
+              totals[k] += datain.getFloat() * percent;
+            }
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) {
+              datain.position( temp_index );
+              if( myswap_bytes ) {
+                swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() );
+                totals[k] += swapbuf;
+              } else {
+                totals[k] += datain.getFloat();
+              }
+            }
+            temp += group_size;
+          }
+          temp0 += ysize;
+        }
+        
+        outindex = ( j + ( i * widthout ) ) * components;
+        for( k = 0; k < components; k++ ) {
+          dataout.position( outindex + k );
+          dataout.put( (totals[k] / area) );
+        }
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthin - 1) {
+          int delta = (highx_int - widthin + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+  }
+  
+  public static void scaleInternalPackedPixel( int components, Extract extract, 
+              int widthIn, int heightIn, ByteBuffer dataIn, int widthOut,
+              int heightOut, ByteBuffer dataOut, int pixelSizeInBytes,
+              int rowSizeInBytes, boolean isSwap ) {
+    float x, convx;
+    float y, convy;
+    float percent;
+    
+    // max components in a format is 4, so
+    float[] totals = new float[4];
+    float[] extractTotals = new float[4];
+    float[] extractMoreTotals = new float[4];
+    float[] shoveTotals = new float[4];
+    
+    float area;
+    int i, j, k, xindex;
+    
+    int temp, temp0;
+    int temp_index;
+    int outIndex = 0;
+    
+    int lowx_int, highx_int, lowy_int, highy_int;
+    float x_percent, y_percent;
+    float lowx_float, highx_float, lowy_float, highy_float;
+    float convy_float, convx_float;
+    int convy_int, convx_int;
+    int l, m;
+    int left, right;
+    
+    if( widthIn == widthOut * 2 && heightIn == heightOut * 2 ) {
+      HalveImage.halveImagePackedPixel( components, extract, widthIn, heightIn, dataIn, dataOut,
+                              pixelSizeInBytes, rowSizeInBytes, isSwap );
+      return;
+    }
+    convy = (float)heightIn / (float)heightOut;
+    convx = (float)widthIn / (float)widthOut;
+    convy_int = (int)Math.floor( convy );
+    convy_float = convy - convy_int;
+    convx_int = (int)Math.floor( convx );
+    convx_float = convx - convx_int;
+    
+    area = convx * convy;
+    
+    lowy_int = 0;
+    lowy_float = 0.0f;
+    highy_int = convy_int;
+    highy_float = convx_float;
+    
+    for( i = 0; i < heightOut; i++ ) {
+      // Clamp here to be sure we don't read beyond input buffer.
+      if (highy_int >= heightIn)
+        highy_int = heightIn - 1;
+      lowx_int = 0;
+      lowx_float = 0.0f;
+      highx_int = convx_int;
+      highx_float = convx_float;
+      
+      for( j = 0; j < widthOut; j++ ) {
+        // ok now apply box filter to box that goes from( lowx, lowy )
+        // to ( highx, highy ) on input data into this pixel on output data
+        totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+        
+        // calculate that value for pixels in the 1st row
+        xindex = lowx_int * pixelSizeInBytes;
+        if( (highy_int > lowy_int) && (highx_int > lowx_int) ) {
+          
+          y_percent = 1 - lowy_float;
+          temp = xindex + lowy_int * rowSizeInBytes;
+          percent = y_percent * ( 1 - lowx_float );
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          left = temp;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += pixelSizeInBytes;
+            dataIn.position( temp );
+            extract.extract( isSwap, dataIn, extractTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += extractTotals[k] * y_percent;
+            }
+          }
+          temp += pixelSizeInBytes;
+          right = temp;
+          percent = y_percent * highx_float;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          // calculate the value for pixels in the last row
+          
+          y_percent = highy_float;
+          percent = y_percent * ( 1 - lowx_float );
+          temp = xindex + highy_int * rowSizeInBytes;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += pixelSizeInBytes;
+            dataIn.position( temp );
+            extract.extract( isSwap, dataIn, extractTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += extractTotals[k] * y_percent;
+            }
+          }
+          temp += pixelSizeInBytes;
+          percent = y_percent * highx_float;
+          dataIn.position( temp );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          
+          // calculate the value for pixels in the 1st and last column
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            left += rowSizeInBytes;
+            right += rowSizeInBytes;
+            dataIn.position( left );
+            extract.extract( isSwap, dataIn, extractTotals );
+            dataIn.position( right );
+            extract.extract( isSwap, dataIn, extractMoreTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += ( extractTotals[k] * ( 1 - lowx_float ) + extractMoreTotals[k] * highx_float );
+            }
+          }
+        } else if( highy_int > lowy_int ) {
+          x_percent = highx_float - lowx_float;
+          percent = ( 1 - lowy_float ) * x_percent;
+          temp = xindex + lowy_int * rowSizeInBytes;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          for( m = lowy_int + 1; m < highy_int; m++ ) {
+            temp += rowSizeInBytes;
+            dataIn.position( temp );
+            extract.extract( isSwap, dataIn, extractTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += extractTotals[k] * x_percent;
+            }
+          }
+          percent = x_percent * highy_float;
+          temp += rowSizeInBytes;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+        } else if( highx_int > lowx_int ) {
+          y_percent = highy_float - lowy_float;
+          percent = ( 1 - lowx_float ) * y_percent;
+          temp = xindex + lowy_int * rowSizeInBytes;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            temp += pixelSizeInBytes;
+            dataIn.position( temp );
+            extract.extract( isSwap, dataIn, extractTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += extractTotals[k] * y_percent;
+            }
+          }
+          temp += pixelSizeInBytes;
+          percent = y_percent * highx_float;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+        } else {
+          percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float );
+          temp = xindex + lowy_int * rowSizeInBytes;
+          dataIn.position( temp );
+          extract.extract( isSwap, dataIn, extractTotals );
+          for( k = 0; k < components; k++ ) {
+            totals[k] += extractTotals[k] * percent;
+          }
+        }
+        
+        // this is for the pixels in the body
+        temp0 = xindex + pixelSizeInBytes + ( lowy_int + 1 ) * rowSizeInBytes;
+        for( m = lowy_int + 1; m < highy_int; m++ ) {
+          temp = temp0;
+          for( l = lowx_int + 1; l < highx_int; l++ ) {
+            dataIn.position( temp );
+            extract.extract( isSwap, dataIn, extractTotals );
+            for( k = 0; k < components; k++ ) {
+              totals[k] += extractTotals[k] * percent;
+            }
+            temp += pixelSizeInBytes;
+          }
+          temp0 += rowSizeInBytes;
+        }
+        
+        outIndex = ( j + ( i * widthOut ) );
+        for( k = 0; k < components; k++ ) {
+          shoveTotals[k] = totals[k] / area;
+        }
+        extract.shove( shoveTotals, outIndex, dataOut );
+        lowx_int = highx_int;
+        lowx_float = highx_float;
+        highx_int += convx_int;
+        highx_float += convx_float;
+        if( highx_float > 1.0f ) {
+          highx_float -= 1.0f;
+          highx_int++;
+        }
+
+        // Clamp to make sure we don't run off the right edge
+        if (highx_int > widthIn - 1) {
+          int delta = (highx_int - widthIn + 1);
+          lowx_int -= delta;
+          highx_int -= delta;
+        }
+      }
+      lowy_int = highy_int;
+      lowy_float = highy_float;
+      highy_int += convy_int;
+      highy_float += convy_float;
+      if( highy_float > 1.0f ) {
+        highy_float -= 1.0f;
+        highy_int++;
+      }
+    }
+    assert( outIndex == ( widthOut * heightOut - 1) );
+  }
+  
+  public static void scaleInternal3D( int components, int widthIn, int heightIn,
+          int depthIn, ShortBuffer dataIn, int widthOut, int heightOut,
+          int depthOut, ShortBuffer dataOut ) {
+    float x, lowx, highx, convx, halfconvx;
+    float y, lowy, highy, convy, halfconvy;
+    float z, lowz, highz, convz, halfconvz;
+    float xpercent, ypercent, zpercent;
+    float percent;
+    // max compnents in a format is 4
+    float[] totals = new float[4];
+    float volume;
+    int i, j, d, k, zint, yint, xint, xindex, yindex, zindex;
+    int temp;
+    
+    lowy = highy = lowx = highx = 0.0f;
+    
+    convz = (float)depthIn / depthOut;
+    convy = (float)heightIn / heightOut;
+    convx = (float)widthIn / widthOut;
+    halfconvz = convz / 2.0f;
+    halfconvy = convy / 2.0f;
+    halfconvx = convx / 2.0f;
+    for( d = 0; d < depthOut; d++ ) {
+      z = convz * ( d + 0.5f );
+      if( depthIn > depthOut ) {
+        highz = z + halfconvz;
+        lowz = z - halfconvz;
+      } else {
+        highz = z + 0.5f;
+        lowz = z - 0.5f;
+      }
+      for( i = 0; i < heightOut; i++ ) {
+        y = convy * ( i + 0.5f );
+        if( heightIn > heightOut ) {
+          highz = y + halfconvy;
+          lowz = y - halfconvy;
+        } else {
+          highz = y + 0.5f;
+          lowz = y - 0.5f;
+        }
+        for( j = 0; j < widthOut; j++ ) {
+          x = convx * ( j + 0.5f );
+          if( depthIn > depthOut ) {
+            highz = x + halfconvx;
+            lowz = x - halfconvx;
+          } else {
+            highz = x + 0.5f;
+            lowz = x - 0.5f;
+          }
+          
+          // Ok, now apply box filter to box that goes from ( lowx, lowy, lowz )
+          // to ( highx, highy, highz ) on input data into this pixel on output data
+          
+          totals[0] = totals[1] = totals[2] = totals[3] = 0.0f;
+          volume = 0.0f;
+          
+          z = lowz;
+          zint = (int)(Math.floor( z ) );
+          while( z < highz ) {
+            zindex = ( zint + depthIn ) % depthIn;
+            if( highz < zint + 1 ) {
+              zpercent = highz - z;
+            } else {
+              zpercent = zint + 1 - z;
+            }
+            
+            y = lowy;
+            yint = (int)(Math.floor( y ) );
+            while( y < highy ) {
+              yindex = ( yint + heightIn ) % heightIn;
+              if( highy < yint + 1 ) {
+                ypercent = highy - y;
+              } else {
+                ypercent = yint + 1 - y;
+              }
+              
+              x = lowx;
+              xint = (int)(Math.floor( x ) );
+              
+              while( x < highx ) {
+                xindex = (xint + widthIn ) % widthIn;
+                if( highx < xint + 1 ) {
+                  xpercent = highx - x;
+                } else {
+                  xpercent = xint + 1 - x;
+                }
+                
+                percent = xpercent * ypercent * zpercent;
+                volume += percent;
+                
+                temp = (xindex + ( yindex *widthIn) + (zindex * widthIn *heightIn)) * components;
+                for( k = 0; k < components; k++ ) {
+                  assert( 0 <= (temp+k) && (temp+k) < (widthIn * heightIn * depthIn * components) );
+                  totals[k] += dataIn.get( temp + k ) * percent;
+                }
+                xint++;
+                x = xint;
+              } // while x
+              yint++;
+              y = yint;
+            } // while y
+            zint++;
+            z = zint;
+          } // while z
+          
+          temp = ( j + ( i * widthOut ) + (d * widthOut * heightOut ) ) * components;
+          for( k = 0; k < components; k++ ) {
+            // totals should be rounded in the case of enlarging an rgb ramp when the type is 332 or 4444
+            assert( 0 <= ( temp + k ) && ( temp + k ) < (widthOut * heightOut* depthOut * components) );
+            dataOut.put( temp + k, (short)((totals[k] + 0.5f) / volume ) );
+          }
+        }
+      }
+    }
+  }
+  
+  public static int gluScaleImage3D( GL gl, int format, int widthIn, int heightIn, 
+          int depthIn, int typeIn, ByteBuffer dataIn, int widthOut, int heightOut, 
+          int depthOut, int typeOut, ByteBuffer dataOut ) {
+    int components;
+    ShortBuffer beforeImage, afterImage;
+    PixelStorageModes psm = new PixelStorageModes();
+    
+    if( widthIn == 0 || heightIn == 0 || depthIn == 0 ||
+            widthOut == 0 || heightOut == 0 || depthOut == 0 ) {
+      return( 0 );
+    }
+    
+    if( widthIn < 0 || heightIn < 0 || depthIn < 0 ||
+            widthOut < 0 || heightOut < 0 || depthOut < 0 ) {
+      return( GLU.GLU_INVALID_VALUE );
+    }
+    
+    if( !Mipmap.legalFormat(format) || !Mipmap.legalType(typeIn) || 
+            !Mipmap.legalType(typeOut) || typeIn == GL2.GL_BITMAP ||
+            typeOut == GL2.GL_BITMAP ) {
+      return( GLU.GLU_INVALID_ENUM );
+    }
+    
+    if( !Mipmap.isLegalFormatForPackedPixelType( format, typeIn ) ) {
+      return( GLU.GLU_INVALID_OPERATION );
+    }
+    
+    if( !Mipmap.isLegalFormatForPackedPixelType( format, typeOut ) ) {
+      return( GLU.GLU_INVALID_OPERATION );
+    }
+    
+    try {
+        beforeImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn, 
+                heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+        afterImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn, 
+                heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
+    } catch( OutOfMemoryError err ) {
+      return( GLU.GLU_OUT_OF_MEMORY );
+    }
+    Mipmap.retrieveStoreModes3D( gl, psm );
+    
+    Image.fillImage3D( psm, widthIn, heightIn, depthIn, format, typeIn,
+            Mipmap.is_index( format ), dataIn, beforeImage );
+    components = Mipmap.elements_per_group( format, 0 );
+    ScaleInternal.scaleInternal3D( components, widthIn, heightIn, depthIn,
+            beforeImage, widthOut, heightOut, depthOut, afterImage );
+    Image.emptyImage3D( psm, widthOut, heightOut, depthOut, format, typeOut,
+            Mipmap.is_index( format ), afterImage, dataOut );
+    
+    return( 0 );
+  }
+}
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java
new file mode 100644
index 000000000..0aeca8f1c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java
@@ -0,0 +1,226 @@
+/*
+ * License Applicability. Except to the extent portions of this file are
+ * made subject to an alternative license as permitted in the SGI Free
+ * Software License B, Version 2.0 (the "License"), the contents of this
+ * file are subject only to the provisions of the License. You may not use
+ * this file except in compliance with the License. You may obtain a copy
+ * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
+ * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
+ * 
+ * http://oss.sgi.com/projects/FreeB
+ * 
+ * Note that, as provided in the License, the Software is distributed on an
+ * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
+ * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
+ * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
+ * 
+ * NOTE:  The Original Code (as defined below) has been licensed to Sun
+ * Microsystems, Inc. ("Sun") under the SGI Free Software License B
+ * (Version 1.1), shown above ("SGI License").   Pursuant to Section
+ * 3.2(3) of the SGI License, Sun is distributing the Covered Code to
+ * you under an alternative license ("Alternative License").  This
+ * Alternative License includes all of the provisions of the SGI License
+ * except that Section 2.2 and 11 are omitted.  Any differences between
+ * the Alternative License and the SGI License are offered solely by Sun
+ * and not by SGI.
+ *
+ * Original Code. The Original Code is: OpenGL Sample Implementation,
+ * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
+ * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
+ * Copyright in any portions created by third parties is as indicated
+ * elsewhere herein. All Rights Reserved.
+ * 
+ * Additional Notice Provisions: The application programming interfaces
+ * established by SGI in conjunction with the Original Code are The
+ * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
+ * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
+ * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
+ * Window System(R) (Version 1.3), released October 19, 1998. This software
+ * was created using the OpenGL(R) version 1.2.1 Sample Implementation
+ * published by SGI, but has not been independently verified as being
+ * compliant with the OpenGL(R) version 1.2.1 Specification.
+ */
+
+package com.jogamp.opengl.impl.glu.mipmap;
+
+import java.nio.*;
+
+/**
+ *
+ * @author  Administrator
+ */
+public class Type_Widget {
+  
+  ByteBuffer buffer;
+  
+  /** Creates a new instance of Type_Widget */
+  public Type_Widget() {
+    // can't make this direct, because JVM doesn't allocate small direct buffers efficiently
+    // see https://jogamp.org/bugzilla/show_bug.cgi?id=463 for details
+    buffer = ByteBuffer.allocate( 4 );
+  }
+  
+  public void setUB0( byte b ) {
+    buffer.position( 0 );
+    buffer.put( b );
+  }
+  
+  public byte getUB0() {
+    buffer.position( 0 );
+    return( buffer.get() );
+  }
+  
+  public void setUB1( byte b ) {
+    buffer.position( 1 );
+    buffer.put( b );
+  }
+  
+  public byte getUB1() {
+    buffer.position( 1 );
+    return( buffer.get() );
+  }
+  
+  public void setUB2( byte b ) {
+    buffer.position( 2 );
+    buffer.put( b );
+  }
+  
+  public byte getUB2() {
+    buffer.position( 2 );
+    return( buffer.get() );
+  }
+  
+  public void setUB3( byte b ) {
+    buffer.position( 3 );
+    buffer.put( b );
+  }
+  
+  public byte getUB3() {
+    buffer.position( 3 );
+    return( buffer.get() );
+  }
+  
+  public void setUS0( short s ) {
+    buffer.position( 0 );
+    buffer.putShort( s );
+  }
+  
+  public short getUS0() {
+    buffer.position( 0 );
+    return( buffer.getShort() );
+  }
+  
+  public void setUS1( short s ) {
+    buffer.position( 2 );
+    buffer.putShort( s );
+  }
+  
+  public short getUS1() {
+   buffer.position( 2 );
+   return( buffer.getShort() );
+  }
+  
+  public void setUI( int i ) {
+    buffer.position( 0 );
+    buffer.putInt( i );
+  }
+  
+  public int getUI() {
+    buffer.position( 0 );
+    return( buffer.getInt() );
+  }
+  
+  public void setB0( byte b ) {
+    buffer.position( 0 );
+    buffer.put( b );
+  }
+  
+  public byte getB0() {
+    buffer.position( 0 );
+    return( buffer.get() );
+  }
+  
+  public void setB1( byte b ) {
+    buffer.position( 1 );
+    buffer.put( b );
+  }
+  
+  public byte getB1() {
+    buffer.position( 1 );
+    return( buffer.get() );
+  }
+  
+  public void setB2( byte b ) {
+    buffer.position( 2 );
+    buffer.put( b );
+  }
+  
+  public byte getB2() {
+    buffer.position( 2 );
+    return( buffer.get() );
+  }
+  
+  public void setB3( byte b ) {
+    buffer.position( 3 );
+    buffer.put( b );
+  }
+  
+  public byte getB3() {
+    buffer.position( 3 );
+    return( buffer.get() );
+  }
+  
+  public void setS0( short s ) {
+    buffer.position( 0 );
+    buffer.putShort( s );
+  }
+  
+  public short getS0() {
+    buffer.position( 0 );
+    return( buffer.getShort() );
+  }
+  
+  public void setS1( short s ) {
+    buffer.position( 2 );
+    buffer.putShort( s );
+  }
+  
+  public short getS1() {
+    buffer.position( 2 );
+    return( buffer.getShort() );
+  }
+  
+  public void setI( int i ) {
+    buffer.position( 0 );
+    buffer.putInt( i );
+  }
+  
+  public int getI() {
+    buffer.position( 0 );
+    return( buffer.getInt() );
+  }
+  
+  public void setF( float f ) {
+    buffer.position( 0 );
+    buffer.putFloat( f );
+  }
+  
+  public float getF() {
+    buffer.position( 0 );
+    return( buffer.getFloat() );
+  }
+  
+  public ByteBuffer getBuffer() {
+    buffer.rewind();
+    return( buffer );
+  }
+  
+  public static void main( String args[] ) {
+    Type_Widget t = new Type_Widget();
+    t.setI( 1000000 );
+    
+    System.out.println("int: " + Integer.toHexString( t.getI() ) );
+    
+  }
+}
-- 
cgit v1.2.3