This is ImageColorHalf.m in view mode; [Download] [Up]
#import "../ImageOpr.h" #import <appkit/Application.h> #import <appkit/publicWraps.h> #import <appkit/NXBitmapImageRep.h> #import <appkit/Control.h> #import <appkit/Panel.h> #import <appkit/TextField.h> #import <objc/NXBundle.h> /* LocalizedString */ #import <stdio.h> #import <stdlib.h> #import <string.h> #import <libc.h> #import <streams/streams.h> #import "../TVController.h" #import "../ToyWin.h" #import "../ToyWinEPS.h" #import "../ToyView.h" #import "../common.h" #import "../strfunc.h" #import "../getpixel.h" #import "../ColorMap.h" #import "imageOperation.h" #import "MDAmethod.h" #import "Dither.h" @implementation ImageOpr (ColorHalf) /* Local Method */ - (commonInfo *)colorHalfMap:(unsigned char **)newmap method:(int)tag from:(ToyWin *)tw with:(commonInfo *)cinf colors:(int)colnum alpha:(BOOL)hasalpha { id msgtext; commonInfo *newinf = NULL; int i, x, y, mdaidx, bits; int pl, err = 0; const char *fnam; unsigned char *working[MAXPLANE]; unsigned char apool[MAXWidth]; unsigned char *q[4]; id <Dithering> dither[3]; static int MDAbits[3][3] = { {8,8,4}, {4,4,4}, {2,2,2} }; fnam = [tw filename]; newmap[0] = working[0] = NULL; switch (colnum) { default: case 256: mdaidx = 0; bits = 4; break; case 64: mdaidx = 1; bits = 2; break; case 8: mdaidx = 2; bits = 1; break; } pl = hasalpha ? 4 : 3; err = allocImage(working, cinf->width, cinf->height, 8, pl); if (err) goto ErrEXIT; err = allocImage(newmap, cinf->width, cinf->height, bits, pl); if (err) goto ErrEXIT; if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL) { err = Err_MEMORY; goto ErrEXIT; } *newinf = *cinf; newinf->xbytes = byte_length(bits, newinf->width); newinf->bits = bits; newinf->numcolors = 3; newinf->isplanar = YES; newinf->alpha = hasalpha; newinf->palsteps = 0; newinf->palette = NULL; for (i = 0; i < 3; i++) { dither[i] = tag ? [MDAmethod alloc] : [Dither alloc]; if (dither[i] == nil || [dither[i] init:MDAbits[mdaidx][i] width:newinf->width] == nil) goto ErrEXIT; } msgtext = [theController messageDisplay:"Reducing..."]; for (y = 0; y < newinf->height; y++) { unsigned char *qn, *ptr; int elm[MAXPLANE]; for (i = 0; i < 3; i++) q[i] = [dither[i] buffer]; for (x = 0; x < newinf->width; x++) { getPixel(&elm[0], &elm[1], &elm[2], &elm[3]); for (i = 0; i < 3; i++) q[i][x] = elm[i]; apool[x] = elm[3]; } for (i = 0; i < 3; i++) { qn = [dither[i] getNewLine]; ptr = &working[i][y * newinf->width]; for (x = 0; x < newinf->width; x++) *ptr++ = *qn++; } if (pl == 4) { for (i = 0; i < pl; i++) q[i] = &working[i][y * newinf->width]; ptr = q[ALPHA]; for (x = 0; x < newinf->width; x++) if (apool[x] == AlphaTransp) { for (i = 0; i < 3; i++) q[i][x] = 255; ptr[x] = AlphaTransp; }else ptr[x] = AlphaOpaque; } } if (hasalpha && colnum == 256) { /* reduce to 255 */ int cnum = 0; BOOL al; ColorMap *colormap = nil; commonInfo tmpinf; tmpinf = *newinf; tmpinf.xbytes = newinf->width; tmpinf.bits = 8; /* Temporally */ tmpinf.alpha = NO; if (initGetPixel(&tmpinf) > 0 || (colormap = [[ColorMap alloc] init]) == nil || [colormap allocFullColor] == nil) cnum = 0; else cnum = [colormap getAllColor:working limit:0 alpha:&al]; if (colormap) [colormap free]; if (cnum == 256) { const unsigned char *lv; [msgtext setStringValue: "Reducing into 255 colors"]; NXPing(); lv = [dither[RED] threshold]; for (y = 0; y < newinf->height; y++) { for (i = 0; i < 3; i++) q[i] = &working[i][y * newinf->width]; for (x = 0; x < newinf->width; x++) { if (q[GREEN][x] == 0 && q[BLUE][x] == 0 && q[RED][x] == lv[1]) q[RED][x] = ((x ^ y) & 1) ? lv[2] : 0; } } } colnum = 255; } for (i = 0; i < 3; i++) [dither[i] free]; [msgtext setStringValue: "Packing Bits..."]; NXPing(); packWorkingImage(newinf, pl, working, newmap); free((void *)working[0]); [tw freeTempBitmap]; [theController messageDisplay:NULL]; sprintf(newinf->memo, "%d x %d %dcolors(%dbit%s)%s", newinf->width, newinf->height, colnum, newinf->bits, ((newinf->bits > 1) ? "s" : ""), (newinf->alpha ? " Alpha" : "")); comment_copy(newinf->memo, cinf->memo); return newinf; ErrEXIT: if (err) errAlert(fnam, err); [tw freeTempBitmap]; if (newmap[0]) { free((void *)newmap[0]); newmap[0] = NULL; } if (working[0]) free((void *)working[0]); if (newinf) free((void *)newinf); return NULL; } - colorHalftoneWith:(int)colnum method:(int)tag /* by Dither or MDA (Mean Density Approximation Method) */ { ToyWin *tw, *newtw; commonInfo *cinf, *newinf = NULL; unsigned char *map[MAXPLANE], *newmap[MAXPLANE]; const char *fnam; char fn[256]; BOOL needflag = NO, hasalpha; int cnum, err = 0; if ((tw = [self keyParentWindow: Reduction]) == nil) { NXBeep(); return self; } fnam = [tw filename]; cinf = [[tw toyView] commonInfo]; if (![self checkCommonInfo:cinf filename:fnam]) return self; if (cinf->numcolors == 1) { err = Err_OPR_IMPL; goto ErrEXIT; } if (cinf->palette && cinf->palsteps <= colnum) { if ([self needReduce:fnam colors:cinf->palsteps ask:YES]) needflag = YES; else return self; } if ((err = [tw getBitmap:map info: &cinf]) == 0) err = initGetPixel(cinf); if (err) goto ErrEXIT; hasalpha = cinf->alpha; if (!needflag) { ColorMap *colormap = [[ColorMap alloc] init]; if ([colormap allocFullColor] != nil) { cnum = [colormap getAllColor:map limit:0 alpha:&hasalpha]; [colormap free]; }else { err = Err_MEMORY; goto ErrEXIT; } if (cnum <= colnum && ![self needReduce:fnam colors:cnum ask:YES]) goto ErrEXIT; } resetPixel(map, 0); newinf = [self colorHalfMap:newmap method:tag from:tw with:cinf colors:colnum alpha:hasalpha]; if (newinf == NULL) goto ErrEXIT; newtw = [[ToyWin alloc] init:tw by:Reduction]; sprintf(fn, "%s(%s%d)", fnam, (tag ? "Halftone" : "Dither"), colnum); [newtw initLocateWindow:fn width:newinf->width height:newinf->height]; // [newtw makeComment: newinf]; if ([newtw drawView:newmap info: newinf] == nil) { err = Err_MEMORY; [newtw free]; free((void *)newmap[0]); goto ErrEXIT; }else [theController newWindow: newtw]; return self; ErrEXIT: if (err) errAlert(fnam, err); [tw freeTempBitmap]; if (newinf) free((void *)newinf); return NULL; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.