home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / Mesa-1.2.1 / src-glu / mipmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-05  |  17.0 KB  |  725 lines

  1. /* mipmap.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: mipmap.c,v 1.9 1995/06/16 14:04:24 brianp Exp $
  26.  
  27. $Log: mipmap.c,v $
  28.  * Revision 1.9  1995/06/16  14:04:24  brianp
  29.  * gluBuild2DMipmaps: fixed wrong size malloc, better error checking
  30.  *
  31.  * Revision 1.8  1995/05/22  16:56:20  brianp
  32.  * Release 1.2
  33.  *
  34.  * Revision 1.7  1995/05/16  19:17:21  brianp
  35.  * minor changes to allow compilation with real OpenGL headers
  36.  *
  37.  * Revision 1.6  1995/03/17  20:14:02  brianp
  38.  * implemented gluScaleImage and gluBuild2DMipmaps
  39.  *
  40.  * Revision 1.5  1995/03/09  14:51:09  brianp
  41.  * changed log_2 to ilog2
  42.  *
  43.  * Revision 1.4  1995/03/07  19:39:16  brianp
  44.  * changed log2 to log_2
  45.  *
  46.  * Revision 1.3  1995/03/07  14:36:40  brianp
  47.  * first attempt at gluBuild1DMipmaps
  48.  *
  49.  * Revision 1.2  1995/03/04  19:39:18  brianp
  50.  * version 1.1 beta
  51.  *
  52.  * Revision 1.1  1995/02/24  15:45:01  brianp
  53.  * Initial revision
  54.  *
  55.  */
  56.  
  57. #include <assert.h>
  58.  
  59. #include <math.h>
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include "gluP.h"
  63.  
  64.  
  65.  
  66. /*
  67.  * Compute ceiling of integer quotient of A divided by B:
  68.  */
  69. #define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
  70.  
  71.  
  72.  
  73. #define EPSILON 0.001
  74.  
  75.  
  76.  
  77.  
  78. int gluScaleImage( GLenum format,
  79.            GLint widthin, GLint heightin,
  80.            GLenum typein, const void *datain,
  81.            GLint widthout, GLint heightout,
  82.            GLenum typeout, void *dataout )
  83. {
  84.    GLuint components, i, j, k, n;
  85.    GLfloat *tempin, *tempout, *in, *out;
  86.    GLfloat sx, sy;
  87.    GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
  88.    GLint packrowlength, packalignment, packskiprows, packskippixels;
  89.    GLint sizein, sizeout;
  90.    GLint rowstride, rowlen;
  91.  
  92.  
  93.    /* Determine number of components per pixel */
  94.    switch (format) {
  95.       case GL_COLOR_INDEX:
  96.       case GL_STENCIL_INDEX:
  97.       case GL_DEPTH_COMPONENT:
  98.       case GL_RED:
  99.       case GL_GREEN:
  100.       case GL_BLUE:
  101.       case GL_ALPHA:
  102.       case GL_LUMINANCE:
  103.          components = 1;
  104.      break;
  105.       case GL_LUMINANCE_ALPHA:
  106.      components = 2;
  107.      break;
  108.       case GL_RGB:
  109.      components = 3;
  110.      break;
  111.       case GL_RGBA:
  112.      components = 4;
  113.      break;
  114.       default:
  115.      return GLU_INVALID_ENUM;
  116.    }
  117.  
  118.    /* Determine bytes per input datum */
  119.    switch (typein) {
  120.       case GL_UNSIGNED_BYTE:    sizein = sizeof(GLubyte);    break;
  121.       case GL_BYTE:        sizein = sizeof(GLbyte);    break;
  122.       case GL_UNSIGNED_SHORT:    sizein = sizeof(GLushort);    break;
  123.       case GL_SHORT:        sizein = sizeof(GLshort);    break;
  124.       case GL_UNSIGNED_INT:    sizein = sizeof(GLuint);    break;
  125.       case GL_INT:        sizein = sizeof(GLint);        break;
  126.       case GL_FLOAT:        sizein = sizeof(GLfloat);    break;
  127.       case GL_BITMAP:
  128.      /* not implemented yet */
  129.       default:
  130.      return GL_INVALID_ENUM;
  131.    }
  132.  
  133.    /* Determine bytes per output datum */
  134.    switch (typeout) {
  135.       case GL_UNSIGNED_BYTE:    sizeout = sizeof(GLubyte);    break;
  136.       case GL_BYTE:        sizeout = sizeof(GLbyte);    break;
  137.       case GL_UNSIGNED_SHORT:    sizeout = sizeof(GLushort);    break;
  138.       case GL_SHORT:        sizeout = sizeof(GLshort);    break;
  139.       case GL_UNSIGNED_INT:    sizeout = sizeof(GLuint);    break;
  140.       case GL_INT:        sizeout = sizeof(GLint);    break;
  141.       case GL_FLOAT:        sizeout = sizeof(GLfloat);    break;
  142.       case GL_BITMAP:
  143.      /* not implemented yet */
  144.       default:
  145.      return GL_INVALID_ENUM;
  146.    }
  147.  
  148.    /* Get glPixelStore state */
  149.    glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength );
  150.    glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment );
  151.    glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows );
  152.    glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels );
  153.    glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength );
  154.    glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment );
  155.    glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows );
  156.    glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels );
  157.  
  158.    /* Allocate storage for intermediate images */
  159.    tempin = (GLfloat *) malloc( widthin * heightin
  160.                     * components * sizeof(GLfloat) );
  161.    if (!tempin) {
  162.       return GLU_OUT_OF_MEMORY;
  163.    }
  164.    tempout = (GLfloat *) malloc( widthout * heightout
  165.                       * components * sizeof(GLfloat) );
  166.    if (!tempout) {
  167.       free( tempin );
  168.       return GLU_OUT_OF_MEMORY;
  169.    }
  170.  
  171.  
  172.    /*
  173.     * Unpack the pixel data and convert to floating point
  174.     */
  175.  
  176.    if (unpackrowlength>0) {
  177.       rowlen = unpackrowlength;
  178.    }
  179.    else {
  180.       rowlen = widthin;
  181.    }
  182.    if (sizein >= unpackalignment) {
  183.       rowstride = components * rowlen;
  184.    }
  185.    else {
  186.       rowstride = unpackalignment/sizein
  187.             * CEILING( components * rowlen * sizein, unpackalignment );
  188.    }
  189.  
  190.    switch (typein) {
  191.       case GL_UNSIGNED_BYTE:
  192.      k = 0;
  193.      for (i=0;i<heightin;i++) {
  194.         GLubyte *ubptr = (GLubyte *) datain
  195.                        + i * rowstride
  196.                + unpackskiprows * rowstride
  197.                + unpackskippixels * components;
  198.         for (j=0;j<widthin*components;j++) {
  199.            tempin[k++] = (GLfloat) *ubptr++;
  200.         }
  201.      }
  202.      break;
  203.       case GL_BYTE:
  204.      k = 0;
  205.      for (i=0;i<heightin;i++) {
  206.         GLbyte *bptr = (GLbyte *) datain
  207.                      + i * rowstride
  208.              + unpackskiprows * rowstride
  209.              + unpackskippixels * components;
  210.         for (j=0;j<widthin*components;j++) {
  211.            tempin[k++] = (GLfloat) *bptr++;
  212.         }
  213.      }
  214.      break;
  215.       case GL_UNSIGNED_SHORT:
  216.      k = 0;
  217.      for (i=0;i<heightin;i++) {
  218.         GLushort *usptr = (GLushort *) datain
  219.                         + i * rowstride
  220.                 + unpackskiprows * rowstride
  221.                 + unpackskippixels * components;
  222.         for (j=0;j<widthin*components;j++) {
  223.            tempin[k++] = (GLfloat) *usptr++;
  224.         }
  225.      }
  226.      break;
  227.       case GL_SHORT:
  228.      k = 0;
  229.      for (i=0;i<heightin;i++) {
  230.         GLshort *sptr = (GLshort *) datain
  231.                       + i * rowstride
  232.               + unpackskiprows * rowstride
  233.               + unpackskippixels * components;
  234.         for (j=0;j<widthin*components;j++) {
  235.            tempin[k++] = (GLfloat) *sptr++;
  236.         }
  237.      }
  238.      break;
  239.       case GL_UNSIGNED_INT:
  240.      k = 0;
  241.      for (i=0;i<heightin;i++) {
  242.         GLuint *uiptr = (GLuint *) datain
  243.                       + i * rowstride
  244.               + unpackskiprows * rowstride
  245.               + unpackskippixels * components;
  246.         for (j=0;j<widthin*components;j++) {
  247.            tempin[k++] = (GLfloat) *uiptr++;
  248.         }
  249.      }
  250.      break;
  251.       case GL_INT:
  252.      k = 0;
  253.      for (i=0;i<heightin;i++) {
  254.         GLint *iptr = (GLint *) datain
  255.                     + i * rowstride
  256.             + unpackskiprows * rowstride
  257.             + unpackskippixels * components;
  258.         for (j=0;j<widthin*components;j++) {
  259.            tempin[k++] = (GLfloat) *iptr++;
  260.         }
  261.      }
  262.      break;
  263.       case GL_FLOAT:
  264.      k = 0;
  265.      for (i=0;i<heightin;i++) {
  266.         GLfloat *fptr = (GLfloat *) datain
  267.                       + i * rowstride
  268.               + unpackskiprows * rowstride
  269.               + unpackskippixels * components;
  270.         for (j=0;j<widthin*components;j++) {
  271.            tempin[k++] = *fptr++;
  272.         }
  273.      }
  274.      break;
  275.       default:
  276.      return GLU_INVALID_ENUM;
  277.    }
  278.  
  279.  
  280.    /*
  281.     * Scale the image!
  282.     */
  283.  
  284.    sx = (GLfloat) widthin / (GLfloat) widthout;
  285.    sy = (GLfloat) heightin / (GLfloat) heightout;
  286.  
  287. /*#define POINT_SAMPLE*/
  288. #ifdef POINT_SAMPLE
  289.    for (i=0;i<heightout;i++) {
  290.       GLint ii = i * sy;
  291.       for (j=0;j<widthout;j++) {
  292.      GLint jj = j * sx;
  293.  
  294.      GLfloat *src = tempin + (ii * widthin + jj) * components;
  295.      GLfloat *dst = tempout + (i * widthout + j) * components;
  296.  
  297.      for (k=0;k<components;k++) {
  298.         *dst++ = *src++;
  299.      }
  300.       }
  301.    }
  302. #else
  303.    if (sx<1.0 && sy<1.0) {
  304.       /* magnify both width and height:  use weighted sample of 4 pixels */
  305.       GLint i0, i1, j0, j1;
  306.       GLfloat alpha, beta;
  307.       GLfloat *src00, *src01, *src10, *src11;
  308.       GLfloat s1, s2;
  309.       GLfloat *dst;
  310.  
  311.       for (i=0;i<heightout;i++) {
  312.      i0 = i * sy;
  313.      i1 = (i+1) * sy - EPSILON;
  314.      alpha = i*sy - i0;
  315.      for (j=0;j<widthout;j++) {
  316.         j0 = j * sx;
  317.         j1 = (j+1) * sx - EPSILON;
  318.         beta = j*sx - j0;
  319.  
  320.         /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
  321.         src00 = tempin + (i0 * widthin + j0) * components;
  322.         src01 = tempin + (i0 * widthin + j1) * components;
  323.         src10 = tempin + (i1 * widthin + j0) * components;
  324.         src11 = tempin + (i1 * widthin + j1) * components;
  325.  
  326.         dst = tempout + (i * widthout + j) * components;
  327.  
  328.         for (k=0;k<components;k++) {
  329.            s1 = *src00++ * (1.0-beta) + *src01++ * beta;
  330.            s2 = *src10++ * (1.0-beta) + *src11++ * beta;
  331.            *dst++ = s1 * (1.0-alpha) + s2 * alpha;
  332.         }
  333.      }
  334.       }
  335.    }
  336.    else {
  337.       /* shrink width and/or height:  use an unweighted box filter */
  338.       GLint i0, i1;
  339.       GLint j0, j1;
  340.       GLint ii, jj;
  341.       GLfloat sum, *dst;
  342.  
  343.       for (i=0;i<heightout;i++) {
  344.      i0 = i * sy;
  345.      i1 = (i+1) * sy - EPSILON;
  346.      for (j=0;j<widthout;j++) {
  347.         j0 = j * sx;
  348.         j1 = (j+1) * sx - EPSILON;
  349.  
  350.         dst = tempout + (i * widthout + j) * components;
  351.  
  352.         /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
  353.         for (k=0;k<components;k++) {
  354.            sum = 0.0;
  355.            for (ii=i0;ii<=i1;ii++) {
  356.           for (jj=j0;jj<=j1;jj++) {
  357.              sum += *(tempin + (ii * widthin + jj) * components + k);
  358.           }
  359.            }
  360.            sum /= (j1-j0+1) * (i1-i0+1);
  361.            *dst++ = sum;
  362.         }
  363.      }
  364.       }
  365.    }
  366. #endif
  367.  
  368.  
  369.    /*
  370.     * Return output image
  371.     */
  372.  
  373.    if (packrowlength>0) {
  374.       rowlen = packrowlength;
  375.    }
  376.    else {
  377.       rowlen = widthout;
  378.    }
  379.    if (sizeout >= packalignment) {
  380.       rowstride = components * rowlen;
  381.    }
  382.    else {
  383.       rowstride = packalignment/sizeout
  384.             * CEILING( components * rowlen * sizeout, packalignment );
  385.    }
  386.  
  387.    switch (typeout) {
  388.       case GL_UNSIGNED_BYTE:
  389.      k = 0;
  390.      for (i=0;i<heightout;i++) {
  391.         GLubyte *ubptr = (GLubyte *) dataout
  392.                        + i * rowstride
  393.                + packskiprows * rowstride
  394.                + packskippixels * components;
  395.         for (j=0;j<widthout*components;j++) {
  396.            *ubptr++ = (GLubyte) tempout[k++];
  397.         }
  398.      }
  399.      break;
  400.       case GL_BYTE:
  401.      k = 0;
  402.      for (i=0;i<heightout;i++) {
  403.         GLbyte *bptr = (GLbyte *) dataout
  404.                      + i * rowstride
  405.              + packskiprows * rowstride
  406.              + packskippixels * components;
  407.         for (j=0;j<widthout*components;j++) {
  408.            *bptr++ = (GLbyte) tempout[k++];
  409.         }
  410.      }
  411.      break;
  412.       case GL_UNSIGNED_SHORT:
  413.      k = 0;
  414.      for (i=0;i<heightout;i++) {
  415.         GLushort *usptr = (GLushort *) dataout
  416.                         + i * rowstride
  417.                 + packskiprows * rowstride
  418.                 + packskippixels * components;
  419.         for (j=0;j<widthout*components;j++) {
  420.            *usptr++ = (GLushort) tempout[k++];
  421.         }
  422.      }
  423.      break;
  424.       case GL_SHORT:
  425.      k = 0;
  426.      for (i=0;i<heightout;i++) {
  427.         GLshort *sptr = (GLshort *) dataout
  428.                       + i * rowstride
  429.               + packskiprows * rowstride
  430.               + packskippixels * components;
  431.         for (j=0;j<widthout*components;j++) {
  432.            *sptr++ = (GLshort) tempout[k++];
  433.         }
  434.      }
  435.      break;
  436.       case GL_UNSIGNED_INT:
  437.      k = 0;
  438.      for (i=0;i<heightout;i++) {
  439.         GLuint *uiptr = (GLuint *) dataout
  440.                       + i * rowstride
  441.               + packskiprows * rowstride
  442.               + packskippixels * components;
  443.         for (j=0;j<widthout*components;j++) {
  444.            *uiptr++ = (GLuint) tempout[k++];
  445.         }
  446.      }
  447.      break;
  448.       case GL_INT:
  449.      k = 0;
  450.      for (i=0;i<heightout;i++) {
  451.         GLint *iptr = (GLint *) dataout
  452.                     + i * rowstride
  453.             + packskiprows * rowstride
  454.             + packskippixels * components;
  455.         for (j=0;j<widthout*components;j++) {
  456.            *iptr++ = (GLint) tempout[k++];
  457.         }
  458.      }
  459.      break;
  460.       case GL_FLOAT:
  461.      k = 0;
  462.      for (i=0;i<heightout;i++) {
  463.         GLfloat *fptr = (GLfloat *) dataout
  464.                       + i * rowstride
  465.               + packskiprows * rowstride
  466.               + packskippixels * components;
  467.         for (j=0;j<widthout*components;j++) {
  468.            *fptr++ = tempout[k++];
  469.         }
  470.      }
  471.      break;
  472.       default:
  473.      return GLU_INVALID_ENUM;
  474.    }
  475.  
  476.  
  477.    /* free temporary image storage */
  478.    free( tempin );
  479.    free( tempout );
  480.  
  481.    return 0;
  482. }
  483.  
  484.  
  485.  
  486. /*
  487.  * Return the largest k such that 2^k <= n.
  488.  */
  489. static GLint ilog2( GLint n )
  490. {
  491.    GLint k;
  492.  
  493.    if (n<=0) return 0;
  494.    for (k=0; n>>=1; k++) ;
  495.    return k;
  496. }
  497.  
  498.  
  499.  
  500. /*
  501.  * Find the value nearest to n which is also a power of two.
  502.  */
  503. static GLint round2( GLint n )
  504. {
  505.    GLint m;
  506.  
  507.    for (m=1; m<n; m*=2)
  508.      ;
  509.  
  510.    /* m>=n */
  511.    if (m-n <= n-m/2) {
  512.       return m;
  513.    }
  514.    else {
  515.       return m/2;
  516.    }
  517. }
  518.  
  519.  
  520. /*
  521.  * Given an pixel format and datatype, return the number of bytes to
  522.  * store one pixel.
  523.  */
  524. static GLint bytes_per_pixel( GLenum format, GLenum type )
  525. {
  526.    GLint n, m;
  527.  
  528.    switch (format) {
  529.       case GL_COLOR_INDEX:
  530.       case GL_STENCIL_INDEX:
  531.       case GL_DEPTH_COMPONENT:
  532.       case GL_RED:
  533.       case GL_GREEN:
  534.       case GL_BLUE:
  535.       case GL_ALPHA:
  536.       case GL_LUMINANCE:
  537.      n = 1;
  538.      break;
  539.       case GL_LUMINANCE_ALPHA:
  540.      n = 2;
  541.      break;
  542.       case GL_RGB:
  543.      n = 3;
  544.      break;
  545.       case GL_RGBA:
  546.      n = 4;
  547.      break;
  548.       default:
  549.      n = 0;
  550.    }
  551.  
  552.    switch (type) {
  553.       case GL_UNSIGNED_BYTE:    m = sizeof(GLubyte);    break;
  554.       case GL_BYTE:        m = sizeof(GLbyte);    break;
  555.       case GL_BITMAP:        m = 1;            break;
  556.       case GL_UNSIGNED_SHORT:    m = sizeof(GLushort);    break;
  557.       case GL_SHORT:        m = sizeof(GLshort);    break;
  558.       case GL_UNSIGNED_INT:    m = sizeof(GLuint);    break;
  559.       case GL_INT:        m = sizeof(GLint);    break;
  560.       case GL_FLOAT:        m = sizeof(GLfloat);    break;
  561.       default:            m = 0;
  562.    }
  563.  
  564.    return n * m;
  565. }
  566.  
  567.  
  568.  
  569. /*
  570.  * WARNING: This function isn't finished and has never been tested!!!!
  571.  */
  572. int gluBuild1DMipmaps( GLenum target, GLint components,
  573.                GLint width, GLenum format,
  574.                GLenum type, const void *data )
  575. {
  576.    GLubyte *texture;
  577.    GLint levels, max_levels;
  578.    GLint new_width, max_width;
  579.    GLint i, j, k, l;
  580.  
  581.    glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_width );
  582.    max_levels = ilog2( max_width ) + 1;
  583.  
  584.    /* Compute how many mipmap images to make */
  585.    levels = ilog2( width ) + 1;
  586.    if (levels>max_levels) {
  587.       levels = max_levels;
  588.    }
  589.  
  590.    new_width = 1 << (levels-1);
  591.  
  592.    texture = (GLubyte *) malloc( new_width * components );
  593.    if (!texture) {
  594.       return GLU_OUT_OF_MEMORY;
  595.    }
  596.  
  597.    if (width != new_width) {
  598.       /* initial rescaling */
  599.       switch (type) {
  600.      case GL_UNSIGNED_BYTE:
  601.         {
  602.            GLubyte *ub_data = (GLubyte *) data;
  603.            for (i=0;i<new_width;i++) {
  604.           j = i * width / new_width;
  605.           for (k=0;k<components;k++) {
  606.              texture[i*components+k] = ub_data[j*components+k];
  607.           }
  608.            }
  609.         }
  610.         break;
  611.      default:
  612.         /* Not implemented */
  613.         return GLU_ERROR;
  614.       }
  615.    }
  616.  
  617.    /* generate and load mipmap images */
  618.    for (l=0;l<levels;l++) {
  619.       glTexImage1D( GL_TEXTURE_1D, l, components, new_width, 0,
  620.             format, GL_UNSIGNED_BYTE, texture );
  621.  
  622.       /* Scale image down to 1/2 size */
  623.       new_width = new_width / 2;
  624.       for (i=0;i<new_width;i++) {
  625.      for (k=0;k<components;k++) {
  626.         GLint sample1, sample2;
  627.         sample1 = (GLint) texture[i*2*components+k];
  628.         sample2 = (GLint) texture[(i*2+1)*components+k];
  629.         texture[i*components+k] = (GLubyte) ((sample1 + sample2) / 2);
  630.      }
  631.       }
  632.    }
  633.  
  634.    free( texture );
  635.  
  636.    /* make sure remaining mipmap levels are removed */
  637.    for (l=levels;l<max_levels;l++) {
  638.       glTexImage1D( GL_TEXTURE_1D, l, components, 0, 0,
  639.             format, GL_UNSIGNED_BYTE, NULL );
  640.    }
  641.  
  642.    return 0;
  643. }
  644.  
  645.  
  646.  
  647. int gluBuild2DMipmaps( GLenum target, GLint components,
  648.                GLint width, GLint height, GLenum format,
  649.                GLenum type, const void *data )
  650. {
  651.    GLint w, h, maxsize;
  652.    void *image, *newimage;
  653.    GLint neww, newh, level, bpp;
  654.    int error;
  655.  
  656.    glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxsize );
  657.  
  658.    w = round2( width );
  659.    if (w>maxsize) {
  660.       w = maxsize;
  661.    }
  662.    h = round2( height );
  663.    if (h>maxsize) {
  664.       h = maxsize;
  665.    }
  666.  
  667.    bpp = bytes_per_pixel( format, type );
  668.    if (bpp==0) {
  669.       /* probably a bad format or type enum */
  670.       return GLU_INVALID_ENUM;
  671.    }
  672.  
  673.    if (w!=width || h!=height) {
  674.       /* must rescale image to get "top" mipmap texture image */
  675.       image = malloc( w * h * bpp );
  676.       if (!image) {
  677.      return GLU_OUT_OF_MEMORY;
  678.       }
  679.       error = gluScaleImage( format, width, height, type, data,
  680.                  w, h, type, image );
  681.       if (error) {
  682.      return error;
  683.       }
  684.    }
  685.    else {
  686.       image = (void *) data;
  687.    }
  688.  
  689.    level = 0;
  690.    while (1) {
  691.       glTexImage2D( target, level, components, w, h, 0, format, type, image );
  692.  
  693.       if (w==1 && h==1)  break;
  694.  
  695.       neww = (w<2) ? 1 : w/2;
  696.       newh = (h<2) ? 1 : h/2;
  697.       newimage = malloc( neww * newh * bpp );
  698.       if (!newimage) {
  699.      return GLU_OUT_OF_MEMORY;
  700.       }
  701.  
  702.       error =  gluScaleImage( format, w, h, type, image,
  703.                   neww, newh, type, newimage );
  704.       if (error) {
  705.      return error;
  706.       }
  707.  
  708.       if (image!=data) {
  709.      free( image );
  710.       }
  711.       image = newimage;
  712.  
  713.       w = neww;
  714.       h = newh;
  715.       level++;
  716.    }
  717.  
  718.    if (image!=data) {
  719.       free( image );
  720.    }
  721.  
  722.    return 0;
  723. }
  724.  
  725.