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.