This is Thumber.m in view mode; [Download] [Up]
#import <Foundation/Foundation.h> #import <mach/mach_init.h> #import "Thumber.h" #define BIT(x) (((unsigned char)1)<<(x)) #define BITS(from, to) ((((BIT((to)) - (unsigned char)1)<<1) + (unsigned char)1) & ~(BIT((from)) - (unsigned char)1)) #define FBITS(from, to) (BITS(7 - (to), 7 - (from))) extern NSConditionLock *globalLock; extern TransferData global; @implementation Thumber static int filterCoef[3] = {4,3,2}; static unsigned char _lkt1bit[2] = {0x0,0xff}; static unsigned char _lkt2bit[4] = {0x0,0x55,0xaa,0xff}; static unsigned char _lkt4bit[16] = {0x0,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; static unsigned char *lookupTable[7] = { _lkt1bit, _lkt2bit, NULL, _lkt4bit, NULL, NULL, NULL }; + (void)connectWithPorts:(NSArray *)portArray { NSAutoreleasePool *pool; NSConnection *clientConnection; Thumber *thumber; pool = [[NSAutoreleasePool alloc] init]; clientConnection = [NSConnection connectionWithReceivePort:[portArray objectAtIndex:0] sendPort:[portArray objectAtIndex:1]]; thumber = [[self alloc] initWithClient:(id)[clientConnection rootProxy]]; [(id)[clientConnection rootProxy] setThumber:thumber]; [thumber release]; [[NSRunLoop currentRunLoop] run]; [pool release]; [NSThread exit]; return; } - initWithClient:(id)aClient { client = [aClient retain]; [client setProtocolForProxy:@protocol(DisplayMethods)]; return self; } - (oneway void)thumbWithSize:(float)thumbSize { unsigned char **planes, **thumbplanes, **thumbSharpenedPlanes, **originalPlanes; NSZone *zone; int bitsPerPixel, samplesPerPixel, thumbSamplesPerPixel, numberOfPlanes, bytesPerPlane, bytesPerRow, bitsPerPixelAndSample; int b,i, j, k,l,d,h,pixelsHigh, pixelsWide, bitCount, byteCount, n, m, z, bitsPerRow, bitsRestPerRow, bitRowCount; int thumbHigh, thumbWide; BOOL isPlanar; unsigned char *data, *p, *q, *qs; unsigned char c,c1,c2; [client provideGlobalData]; [globalLock lockWhenCondition:HAS_DATA]; if(!global.full || (global.imageInfo.pixelsHigh < thumbSize && global.imageInfo.pixelsWide < thumbSize) || !global.imageData || !global.imagePlanes[0]){ global.thumbnailPlanes = NULL; [globalLock unlock]; [client displayGlobalData]; return; } zone = NSCreateZone(vm_page_size * 2, vm_page_size, YES); NSSetZoneName(zone, @"Scrapper"); bitsPerPixel = global.imageInfo.bitsPerPixel; samplesPerPixel = global.imageInfo.samplesPerPixel; bitsPerPixelAndSample = global.imageInfo.bitsPerSample; isPlanar = global.imageInfo.isPlanar; numberOfPlanes = global.imageInfo.numberOfPlanes; bytesPerPlane = global.imageInfo.bytesPerPlane; bytesPerRow = global.imageInfo.bytesPerRow; pixelsHigh = global.imageInfo.pixelsHigh; pixelsWide = global.imageInfo.pixelsWide; data = global.imageData; originalPlanes = global.imagePlanes; planes = NSZoneMalloc(zone, samplesPerPixel * sizeof(unsigned char *)); for(i = 0;i < samplesPerPixel; i++) planes[i] = NSZoneMalloc(zone, pixelsHigh * pixelsWide * sizeof(unsigned char)); if(bitsPerPixelAndSample == 8){ if(isPlanar){ for(i = 0;i < samplesPerPixel; i++){ p = originalPlanes[i]; for(j = 0; j < pixelsHigh * pixelsWide; j++) planes[i][j] = p[j]; } } else { for(j = 0, p = data; j < pixelsHigh * pixelsWide; j++, p += samplesPerPixel) for(i = 0;i < samplesPerPixel; i++) planes[i][j] = p[i]; } } else { if(isPlanar){ bitsPerRow = pixelsWide * bitsPerPixelAndSample; bitsRestPerRow = (bytesPerRow << 3) - bitsPerRow; for(i = 0;i < samplesPerPixel; i++){ p = originalPlanes[i]; bitCount = 0; bitRowCount = 0; for(j = 0; j < pixelsHigh * pixelsWide; j++){ byteCount = bitCount >> 3; // planes[i][j] setzt sich zusammen aus // [bitCount, bitCount + bitsPerPixelAndSample) bits aus dem bitstrom if((bitCount + bitsPerPixelAndSample) <= ((byteCount + 1) << 3)){ n = bitCount - (byteCount << 3); // planes[i][j] besteht aus [n,n + bitsPerPixelAndSample) von p[byteCount] c1 = FBITS(n, n + bitsPerPixelAndSample - 1); c = (p[byteCount] & c1) >> (8 - n - bitsPerPixelAndSample); } else { n = bitCount + bitsPerPixelAndSample - ((byteCount + 1) << 3); // planes[i][j] besteht aus // MostSignificantPart: [0,n) bits von p[byteCount + 1] // LeastSignificantPart: [8 - (bitsPerPixelAndSample - n), 8) bits von p[byteCount] c1 = FBITS(0, n - 1); c1 = (p[byteCount + 1] & c1) >> (8 - n); c1 = c1 << (bitsPerPixelAndSample - n + 1); c2 = FBITS(8 - (bitsPerPixelAndSample - n), 7); c2 = (p[byteCount] & c2); c = c1 | c2; } planes[i][j] = lookupTable[bitsPerPixelAndSample - 1][c]; bitCount += bitsPerPixelAndSample; bitRowCount += bitsPerPixelAndSample; if(bitRowCount == bitsPerRow){ bitCount += bitsRestPerRow; bitRowCount = 0; } } } } else { p = data; bitCount = 0; bitRowCount = 0; bitsPerRow = pixelsWide * bitsPerPixel; bitsRestPerRow = (bytesPerRow << 3) - bitsPerRow; for(j = 0; j < pixelsHigh * pixelsWide; j++){ for(i = 0;i < samplesPerPixel; i++){ byteCount = bitCount >> 3; if((bitCount + bitsPerPixelAndSample) <= ((byteCount + 1) << 3)){ n = bitCount - (byteCount << 3); // planes[i][j] besteht aus [n,n + bitsPerPixelAndSample) von p[byteCount] c1 = FBITS(n, n + bitsPerPixelAndSample - 1); c = (p[byteCount] & c1) >> (8 - n - bitsPerPixelAndSample); } else { n = bitCount + bitsPerPixelAndSample - ((byteCount + 1) << 3); // planes[i][j] besteht aus // MostSignificantPart: [0,n) bits von p[byteCount + 1] // LeastSignificantPart: [8 - (bitsPerPixelAndSample - n), 8) bits von p[byteCount] c1 = FBITS(0, n - 1); c1 = (p[byteCount + 1] & c1) >> (8 - n); c1 = c1 << (bitsPerPixelAndSample - n + 1); c2 = FBITS(8 - (bitsPerPixelAndSample - n), 7); c2 = (p[byteCount] & c2); c = c1 | c2; } planes[i][j] = lookupTable[bitsPerPixelAndSample - 1][c]; bitCount += bitsPerPixelAndSample; bitRowCount += bitsPerPixelAndSample; if(bitRowCount == bitsPerRow){ bitCount += bitsRestPerRow; bitRowCount = 0; } } } } } if(global.imageInfo.hasAlpha) thumbSamplesPerPixel = samplesPerPixel; else thumbSamplesPerPixel = samplesPerPixel + 1; if(pixelsHigh > pixelsWide){ thumbHigh = thumbSize; thumbWide = pixelsWide * thumbSize / pixelsHigh; } else { thumbWide = thumbSize; thumbHigh = pixelsHigh * thumbSize / pixelsWide; } m = (pixelsWide << 6) / thumbWide; thumbplanes = NSZoneMalloc(NSDefaultMallocZone(), thumbSamplesPerPixel * sizeof(unsigned char *)); thumbSharpenedPlanes = NSZoneMalloc(NSDefaultMallocZone(), thumbSamplesPerPixel * sizeof(unsigned char *)); for(i = 0;i < thumbSamplesPerPixel; i++){ thumbplanes[i] = NSZoneMalloc(NSDefaultMallocZone(), thumbHigh * thumbWide * sizeof(unsigned char)); thumbSharpenedPlanes[i] = NSZoneMalloc(NSDefaultMallocZone(), thumbHigh * thumbWide * sizeof(unsigned char)); } for(i = 0 ;i < samplesPerPixel; i++) for(j = 0, q = thumbplanes[i], qs = thumbSharpenedPlanes[i]; j < thumbHigh;j++, q += thumbWide, qs += thumbWide){ z = (j * m) >> 6; p = planes[i] + z * pixelsWide; for(k = 0; k < thumbWide;k++){ h = (k * m) >> 6; d = (int)p[h]; b = d << filterCoef[0]; for(l = 1;l < 3 && h - l >= 0;l++){ d = (int)p[h - l]; b += d << filterCoef[l]; } for(l = 1;l < 3 && h + l < pixelsWide;l++){ d = (int)p[h + l]; b += d << filterCoef[l]; } for(l = 1;l < 3 && z - l >= 0;l++){ d = (int)(p - l * pixelsWide)[h]; b += d << filterCoef[l]; } for(l = 1;l < 3 && z + l < pixelsHigh;l++){ d = (int)(p + l * pixelsWide)[h]; b += d << filterCoef[l]; } q[k] = qs[k] = (unsigned char)(b >> 6); } } for(i = 0 ;i < thumbSamplesPerPixel - 1; i++) for(j = 1, q = thumbplanes[i], qs = thumbSharpenedPlanes[i]; j < thumbHigh - 1;j++, q += thumbWide, qs += thumbWide){ for(k = 1; k < thumbWide - 1;k++){ b = (int)q[k]; b = (b << 2) + b; b -= (int)q[k - 1]; b -= (int)q[k + 1]; b -= (int)(q - thumbWide)[k]; b -= (int)(q + thumbWide)[k]; if(b >= 0 && b < 256) qs[k] = (unsigned char)(b); } } for(i = 0 ;i < thumbSamplesPerPixel - 1; i++) for(j = 0, qs = thumbSharpenedPlanes[i]; j < thumbHigh;j++, qs += thumbWide){ for(k = 0; k < thumbWide;k++) qs[k] >>= 1; } for(j = 0, qs = thumbSharpenedPlanes[thumbSamplesPerPixel - 1]; j < thumbHigh;j++, qs += thumbWide) for(k = 0; k < thumbWide;k++) qs[k] = 127; if(thumbSamplesPerPixel > samplesPerPixel) for(j = 0, q = thumbplanes[thumbSamplesPerPixel - 1]; j < thumbHigh;j++, q += thumbWide) for(k = 0; k < thumbWide;k++) q[k] = 255; global.thumbnailPlanes = thumbplanes; global.thumbnailSharpenedPlanes = thumbSharpenedPlanes; global.thumbnailInfo.pixelsWide = thumbWide; global.thumbnailInfo.pixelsHigh = thumbHigh; global.thumbnailInfo.bitsPerSample = 8; global.thumbnailInfo.samplesPerPixel = thumbSamplesPerPixel; global.thumbnailInfo.isPlanar = YES; global.thumbnailInfo.hasAlpha = YES; global.thumbnailInfo.bytesPerRow = thumbWide; global.thumbnailInfo.bitsPerPixel = 8; global.thumbnailInfo.numberOfPlanes = thumbSamplesPerPixel; global.thumbnailInfo.bytesPerPlane = thumbWide * thumbHigh; for(i = 0;i < samplesPerPixel; i++) NSZoneFree(zone,planes[i]); NSZoneFree(zone,planes); NSRecycleZone(zone); [globalLock unlock]; [client displayGlobalData]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.