This is Scale.m in view mode; [Download] [Up]
/* Copyright (c) 1992 Linus Upson & The Geometry Center University of Minnesota 1300 South Second Street Minneapolis, MN 55454, USA lupson@geom.umn.edu */ #import "Scale.h" #import <math.h> @implementation Scale static unsigned char fourToEight_upper[256]; static unsigned char fourToEight_lower[256]; static unsigned char twoToEight_upper[256]; static unsigned char twoToEight_upperMiddle[256]; static unsigned char twoToEight_lowerMiddle[256]; static unsigned char twoToEight_lower[256]; static void print_info (const char *string, NXBitmapImageRep *bitmap) { printf ("%s\n", string); printf (" bitsPerPixel %d\n", (int)[bitmap bitsPerPixel]); printf (" samplesPerPixel %d\n", (int)[bitmap samplesPerPixel]); printf (" bitsPerSample (NXImageRep) %d\n", (int)[bitmap bitsPerSample]); printf (" isPlanar %d\n", (int)[bitmap isPlanar]); printf (" numPlanes %d\n", (int)[bitmap numPlanes]); printf (" numColors (NXImageRep) %d\n", (int)[bitmap numColors]); printf (" hasAlpha (NXImageRep) %d\n", (int)[bitmap hasAlpha]); printf (" bytesPerPlane %d\n", (int)[bitmap bytesPerPlane]); printf (" bytesPerRow %d\n", (int)[bitmap bytesPerRow]); printf (" colorSpace %d\n", (int)[bitmap colorSpace]); printf (" pixelsWide (NXImageRep) %d\n", (int)[bitmap pixelsWide]); printf (" pixelsHigh (NXImageRep) %d\n", (int)[bitmap pixelsHigh]); printf ("\n"); } static void convertFourBPSMeshed (NXBitmapImageRep *inBitmap, NXBitmapImageRep *outBitmap) { int i, j, width, height, samplesPerPixel; int inBytesPerRow, outBytesPerRow, inWordsPerRow, inRemainderSamples; unsigned char *inData, *inPtr, *outData, *outPtr; width = [inBitmap pixelsWide]; height = [inBitmap pixelsHigh]; samplesPerPixel = [inBitmap samplesPerPixel]; inData = [inBitmap data]; outData = [outBitmap data]; inBytesPerRow = [inBitmap bytesPerRow]; outBytesPerRow = [outBitmap bytesPerRow]; inWordsPerRow = inBytesPerRow / 4; inRemainderSamples = (width * samplesPerPixel - inWordsPerRow * 8); for (i = 0; i < height; i++) { outPtr = outData + i * outBytesPerRow; inPtr = inData + i * inBytesPerRow; for (j = 0; j < inWordsPerRow; j++) { *outPtr++ = fourToEight_upper[*inPtr]; *outPtr++ = fourToEight_lower[*inPtr++]; *outPtr++ = fourToEight_upper[*inPtr]; *outPtr++ = fourToEight_lower[*inPtr++]; *outPtr++ = fourToEight_upper[*inPtr]; *outPtr++ = fourToEight_lower[*inPtr++]; *outPtr++ = fourToEight_upper[*inPtr]; *outPtr++ = fourToEight_lower[*inPtr++]; } for (j = 0; j < inRemainderSamples; j++) { *outPtr++ = fourToEight_upper[*inPtr]; if (++j < inRemainderSamples) *outPtr++ = fourToEight_lower[*inPtr++]; } } } static void convertTwoBPSPlanar (NXBitmapImageRep *inBitmap, NXBitmapImageRep *outBitmap) { int i, j, k, width, height; int inBytesPerRow, inWordsPerRow, inRemainderSamples; int numPlanes, outBytesPerRow; unsigned char *inPlanes[5], *inPlanePtr[5], *outData, *outPtr; width = [inBitmap pixelsWide]; height = [inBitmap pixelsHigh]; numPlanes = [inBitmap numPlanes]; [inBitmap getDataPlanes:inPlanes]; inBytesPerRow = [inBitmap bytesPerRow]; inWordsPerRow = inBytesPerRow / 4; inRemainderSamples = width - inWordsPerRow * 16; outData = [outBitmap data]; outBytesPerRow = [outBitmap bytesPerRow]; for (i = 0; i < height; i++) { outPtr = outData + i * outBytesPerRow; for (k = 0; k < numPlanes; k++) inPlanePtr[k] = inPlanes[k] + i * inBytesPerRow; for (j = 0; j < inWordsPerRow * 4; j++) { for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_upper[*inPlanePtr[k]]; for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_upperMiddle[*inPlanePtr[k]]; for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_lowerMiddle[*inPlanePtr[k]]; for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_lower[*inPlanePtr[k]++]; } for (j = 0; j < inRemainderSamples; j++) { for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_upper[*inPlanePtr[k]]; if (++j < inRemainderSamples) for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_upperMiddle[*inPlanePtr[k]]; if (++j < inRemainderSamples) for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_lowerMiddle[*inPlanePtr[k]]; if (++j < inRemainderSamples) for (k = 0; k < numPlanes; k++) *outPtr++ = twoToEight_lower[*inPlanePtr[k]++]; } } } static void convertEightBPSPlanar (NXBitmapImageRep *inBitmap, NXBitmapImageRep *outBitmap) { int i, j, k, width, height, numPlanes; int inBytesPerRow, outBytesPerRow; unsigned char *inPlanes[5], *inPlanePtr[5], *outData, *outPtr; width = [inBitmap pixelsWide]; height = [inBitmap pixelsHigh]; numPlanes = [inBitmap numPlanes]; [inBitmap getDataPlanes:inPlanes]; inBytesPerRow = [inBitmap bytesPerRow]; outData = [outBitmap data]; outBytesPerRow = [outBitmap bytesPerRow]; for (i = 0; i < height; i++) { outPtr = outData + i * outBytesPerRow; for (k = 0; k < numPlanes; k++) inPlanePtr[k] = inPlanes[k] + i * inBytesPerRow; for (j = 0; j < inBytesPerRow; j++) { for (k = 0; k < numPlanes; k++) *outPtr++ = *inPlanePtr[k]++; } } } - init { [super init]; scratchZone = NXCreateZone (vm_page_size, vm_page_size, YES); return self; } - buildTables:(int)seed { int i; double dx, dy, dz, rr; // Build the different bitmap conversion tables. for (i = 0; i < 256; i++) { fourToEight_upper[i] = ((i >> 4) * 17); fourToEight_lower[i] = ((i & 0x0F) * 17); twoToEight_upper[i] = ((i >> 6) * 85); twoToEight_upperMiddle[i] = (((i & 0x30) >> 4) * 85); twoToEight_lowerMiddle[i] = (((i & 0x0C) >> 2) * 85); twoToEight_lower[i] = ((i & 0x03) * 85); } // Build a table of points whose density falls off as: // 1./sqrt (2.*M_PI*sigma) * exp (r*r/(2.*sigma*sigma)) srandom (seed); for (i = 0; i < NUM_POINTS; i++) { do { dx = 1. - 4. * (double)random () / (double)(0xFFFFFFFF); dy = 1. - 4. * (double)random () / (double)(0xFFFFFFFF); dz = (double)random () / (double)(0xFFFFFFFF); rr = dx * dx + dy * dy; } while (dz > exp (-2. * rr) || rr > 1.); jitterPoint[i].x = dx; jitterPoint[i].y = dy; } jit = jitMin = jitterPoint; jitMax = jitterPoint + NUM_POINTS; tablesBuilt = YES; return self; } - resetJitterIndex { jit = jitMin; return self; } - (NXBitmapImageRep *)convertBitmap:(NXBitmapImageRep *)inBitmap { int bps; BOOL planar; NXBitmapImageRep *standardBitmap; bps = [inBitmap bitsPerSample]; planar = [inBitmap isPlanar]; // If the bitmap is already 8 bits per sample and in meshed // configuration, we don't need to do any conversion. if (bps == 8 && !planar) { freeStandardBitmap = NO; return inBitmap; } // Make space for a bitmap that is one byte for each sample and meshed. // Be sure to remember to free it. freeStandardBitmap = YES; standardBitmap = [[NXBitmapImageRep allocFromZone:scratchZone] initData:NULL pixelsWide:inWidth pixelsHigh:inHeight bitsPerSample:8 samplesPerPixel:[inBitmap samplesPerPixel] hasAlpha:[inBitmap hasAlpha] isPlanar:NO colorSpace:[inBitmap colorSpace] bytesPerRow:0 bitsPerPixel:0]; // Currently the Scale filter only supports the following bitmap formats: // 4 bits per sample meshed (NeXT Station Color). // 2 bits per sample planar (NeXT Station & Cube). // 8 bits per sample planar (Eight bit Gray). // 8 bits per sample meshed (NeXT Dimension) -- no conversion needed. if (bps == 4 && !planar) convertFourBPSMeshed (inBitmap, standardBitmap); else if (bps == 2 && planar) convertTwoBPSPlanar (inBitmap, standardBitmap); else if (bps == 8 && planar) convertEightBPSPlanar (inBitmap, standardBitmap); else { [standardBitmap free]; standardBitmap = nil; } return standardBitmap; } - (NXBitmapImageRep *)scaleBitmap:(NXBitmapImageRep *)inBitmap { int i, j, k, l, x, y; int inBytesPerRow, outBytesPerRow, spp, accbuf[5]; float s, t; unsigned char *inData, *inPtr, *outData, *outPtr; NXBitmapImageRep *outBitmap; inData = [inBitmap data]; inBytesPerRow = [inBitmap bytesPerRow]; spp = [inBitmap samplesPerPixel]; outBitmap = [[NXBitmapImageRep allocFromZone:scratchZone] initData:NULL pixelsWide:outWidth pixelsHigh:outHeight bitsPerSample:8 samplesPerPixel:spp hasAlpha:[inBitmap hasAlpha] isPlanar:NO colorSpace:[inBitmap colorSpace] bytesPerRow:0 bitsPerPixel:0]; outData = [outBitmap data]; outBytesPerRow = [outBitmap bytesPerRow]; for (i = 0; i < outHeight; i++) { outPtr = outData + i * outBytesPerRow; for (j = 0; j < outWidth; j++) { for (l = 0; l < spp; l++) accbuf[l] = 0.; for (k = 0; k < samples; k++) { if (++jit == jitMax) jit = jitMin; s = ((float)j + .5 + focus * jit->x) / scale; t = ((float)i + .5 + focus * jit->y) / scale; if (++jit == jitMax) jit = jitMin; x = (int)(s + .5 + focus * jit->x); y = (int)(t + .5 + focus * jit->y); if (x < 0) x = 0; else if (x >= inWidth) x = inWidth - 1; if (y < 0) y = 0; else if (y >= inHeight) y = inHeight - 1; inPtr = inData + y * inBytesPerRow + x * spp; for (l = 0; l < spp; l++) accbuf[l] += inPtr[l]; } for (l = 0; l < spp; l++) *outPtr++ = (unsigned char)(accbuf[l] / samples); } } return outBitmap; } - filter:(NXBitmapImageRep *)inBitmap { NXBitmapImageRep *standardBitmap, *scaledBitmap; // Do a quick reality check. if (![inBitmap pixelsWide] || ![inBitmap pixelsHigh]) return nil; // Read relevant parameters out of the text fields. focus = [focusField floatValue]; samples = 256; // Determine the input and output sizes in pixels inWidth = [inBitmap pixelsWide]; inHeight = [inBitmap pixelsHigh]; outWidth = outHeight= [outSizeField intValue]; // Figure out the scale factor given the input and output sizes. scale = (float)outWidth / (float)inWidth; // If this is the first time the filter has been called, build the tables // used in jittering and bitmap format conversion. if (!tablesBuilt) [self buildTables:1]; // Convert the bitmap into one that is eight bits per sample // and in meshed configuration. if (!(standardBitmap = [self convertBitmap:inBitmap])) { print_info ("Unknown bitmap format.", inBitmap); return nil; } // Actually do the scaling. scaledBitmap = [self scaleBitmap:standardBitmap]; // If we had to do conversion of the input bitmap, free the tmp one // in the standard format we created. if (freeStandardBitmap) [standardBitmap free]; [inBitmap free]; // Return the 8 bit per sample bitmap. return scaledBitmap; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.