Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Test Code/TinselMipMap.c
/****************************************************************************** |
** ** |
** Module: TinselMipMap.c ** |
** ** |
** Purpose: Support file for mipmapping ** |
** ** |
** Author: Mike W. Kelley ** |
** ** |
** 2/3/95 Revised for 0.9 SDK release ** |
** ** |
** Copyright (C) 1994-95 Apple Computer, Inc. All rights reserved. ** |
** ** |
*****************************************************************************/ |
#include <stdlib.h> |
#include <math.h> |
#include <string.h> |
#include <stdio.h> |
/* Macintosh */ |
#include <Types.h> |
#include <Resources.h> |
#include <QuickDraw.h> |
#include <Fonts.h> |
#include <Events.h> |
#include <Windows.h> |
#include <Menus.h> |
#include <TextEdit.h> |
#include <Dialogs.h> |
#include <Desk.h> |
#include <ToolUtils.h> |
#include <Memory.h> |
#include <SegLoad.h> |
#include <Files.h> |
#include <OSUtils.h> |
#include <OSEvents.h> |
#include <DiskInit.h> |
#include <Packages.h> |
/* Project */ |
#include "RAVE.h" |
#include "TinselTest.h" |
/******************************************************************************************* |
* |
* Create the mipmap for 'pixmap', and load it into 'texture'. Returns NULL on error. |
* |
******************************************************************************************/ |
TQATexture *CreateMipMapTexture ( |
TQAEngine *engine, |
TexturePixel *pixmap, |
long rowBytes, |
long widthNBits, |
long heightNBits) |
{ |
long nImages; |
long width, height; |
long nPixels; |
TexturePixel *mipmap; |
TQAImage images [20]; /* Maximum conceivable number of TQAImages! */ |
long i; |
long x, y; |
long oneHalf; |
TQATexture *texture; |
TQAError status; |
/* |
* Allocate working space for the mip map images (starting with the |
* 2^(widthNBits-1) x 2^(heightNBits-1) map), and for the array of |
* TQAImages that describe the mip map and the parent map. |
*/ |
nImages = ((widthNBits > heightNBits) ? widthNBits : heightNBits) + 1; |
width = 1 << (widthNBits - 1); /* ??? Doesn't work for nBits == 0 */ |
height = 1 << (heightNBits - 1); /* ??? Doesn't work for nBits == 0 */ |
for (i = nImages - 1, nPixels = 0; i-- > 0; /* Nothing */) |
{ |
nPixels += width * height; |
width >>= 1; |
height >>= 1; |
if (width == 0) |
{ |
width = 1; |
} |
if (height == 0) |
{ |
height = 1; |
} |
} |
if ( ! (mipmap = malloc (sizeof (*pixmap) * nPixels))) |
{ |
return (NULL); |
} |
/* |
* Fill in the TQAImage info. |
*/ |
images[0].width = 1 << widthNBits; |
images[0].height = 1 << heightNBits; |
images[0].pixmap = pixmap; |
images[0].rowBytes = rowBytes; |
width = 1 << (widthNBits - 1); /* ??? Doesn't work for nBits == 0 */ |
height = 1 << (heightNBits - 1); /* ??? Doesn't work for nBits == 0 */ |
for (i = 1; i < nImages; ++i) |
{ |
images[i].width = width; |
images[i].height = height; |
images[i].pixmap = mipmap; |
images[i].rowBytes = width * sizeof (*mipmap); |
mipmap += width * height; |
width >>= 1; |
height >>= 1; |
if (width == 0) |
{ |
width = 1; |
} |
if (height == 0) |
{ |
height = 1; |
} |
} |
/* |
* oneHalf is used to round off the box filter of four pixels. |
*/ |
oneHalf = 4 / 2; |
/* |
* Create the mipmapped images. |
*/ |
for (i = 1; i < nImages; ++i) |
{ |
TQAImage *prevImage, *image; |
long sourceRowBytes, targetRowBytes; |
unsigned char *sourceLine0, *sourceLine1; |
unsigned char *targetLine; |
prevImage = &images [i - 1]; |
image = &images [i]; |
sourceLine0 = prevImage->pixmap; |
if (prevImage->height == 1) |
{ |
/* |
* Source image is height 1 (widthNBits must be greater than heightNBits). |
* Make sourceLine1 duplicate sourceLine0, and set sourceRowBytes to 0 so we |
* just keep re-reading the single source line. |
*/ |
sourceRowBytes = 0; |
sourceLine1 = sourceLine0; |
} |
else |
{ |
/* |
* Normal case. sourceLine1 points one scanline above sourceLine0. |
*/ |
sourceRowBytes = prevImage->rowBytes; |
sourceLine1 = sourceLine0 + sourceRowBytes; |
} |
targetRowBytes = image->rowBytes; |
targetLine = image->pixmap; |
for (y = image->height; y-- > 0; /* Nothing */) |
{ |
unsigned char *sourcePixel0, *sourcePixel1; |
unsigned char *targetPixel; |
sourcePixel0 = sourceLine0; |
sourcePixel1 = sourceLine1; |
targetPixel = targetLine; |
if (prevImage->width == 1) |
{ |
/* |
* Source image has width 1 (heightNBits must be greater than widthNBits). |
* Use a special inner loop that doesn't advance past the first pixel of |
* the source lines. |
*/ |
for (x = image->width; x-- > 0; /* Nothing */) |
{ |
long a, r, g, b; |
/* |
* Read and average two pixels from source into target. |
*/ |
a = sourcePixel0 [0] + (oneHalf >> 1); |
r = sourcePixel0 [1] + (oneHalf >> 1); |
g = sourcePixel0 [2] + (oneHalf >> 1); |
b = sourcePixel0 [3] + (oneHalf >> 1); |
a += sourcePixel1 [0]; |
r += sourcePixel1 [1]; |
g += sourcePixel1 [2]; |
b += sourcePixel1 [3]; |
*targetPixel++ = a >> 1; |
*targetPixel++ = r >> 1; |
*targetPixel++ = g >> 1; |
*targetPixel++ = b >> 1; |
} |
} |
else |
{ |
/* |
* Source image has at least width 2. This is the normal case. |
*/ |
for (x = image->width; x-- > 0; /* Nothing */) |
{ |
long a, r, g, b; |
/* |
* Read and average four pixels from source into target. |
*/ |
a = *sourcePixel0++ + oneHalf; |
r = *sourcePixel0++ + oneHalf; |
g = *sourcePixel0++ + oneHalf; |
b = *sourcePixel0++ + oneHalf; |
a += *sourcePixel1++; |
r += *sourcePixel1++; |
g += *sourcePixel1++; |
b += *sourcePixel1++; |
a += *sourcePixel0++; |
r += *sourcePixel0++; |
g += *sourcePixel0++; |
b += *sourcePixel0++; |
a += *sourcePixel1++; |
r += *sourcePixel1++; |
g += *sourcePixel1++; |
b += *sourcePixel1++; |
*targetPixel++ = a >> 2; |
*targetPixel++ = r >> 2; |
*targetPixel++ = g >> 2; |
*targetPixel++ = b >> 2; |
} |
} |
sourceLine0 += (sourceRowBytes << 1); |
sourceLine1 += (sourceRowBytes << 1); |
targetLine += targetRowBytes; |
} |
} |
status = QATextureNew (engine, kQATexture_Mipmap, kQAPixel_RGB32, images, &texture); |
if (status != kQANoErr) |
{ |
return (NULL); |
} |
return (texture); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14