This is ImageEdge.m in view mode; [Download] [Up]
/*
Edge Enhancement coded by T.Ogihara
*/
#import "../ImageOpr.h"
#import <appkit/Application.h>
#import <appkit/publicWraps.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/Control.h>
#import <appkit/Panel.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <streams/streams.h>
#import "../TVController.h"
#import "../ToyWin.h"
#import "../ToyView.h"
#import "../common.h"
#import "../getpixel.h"
#import "Posterizer.h"
#import "imageOperation.h"
@implementation ImageOpr (Edge)
static const char enhanceTab[5][5] = {
{0, 1, 1, 1, 0},
{1, 2, 3, 2, 1},
{1, 3, 0, 3, 1},
{1, 2, 3, 2, 1},
{0, 1, 1, 1, 0}
};
static const char embossTab[5][5] = {
{0, 0, 0, 0, 0},
{0, -2, -1, 0, 0},
{0, -1, 0, 1, 0},
{0, 0, 1, 2, 0},
{0, 0, 0, 0, 0}
};
static int edge(int op, commonInfo *cinf,
float factor, float bright, unsigned char **planes)
{
int i, j, x, y, ptr;
int cnum, pnum;
int elm[MAXPLANE];
int alp, err;
const char (*weight)[5];
cnum = pnum = cinf->numcolors;
if (cinf->alpha) alp = pnum++;
else alp = 0;
weight = (op == Enhance) ? enhanceTab: embossTab;
err = allocImage(planes, cinf->width, cinf->height + 3, 8, pnum);
if (err) return err;
for (y = 0; y < cinf->height; y++) {
ptr = cinf->width * (y + 3);
for (x = 0; x < cinf->width; x++) {
getPixel(&elm[0], &elm[1], &elm[2], &elm[3]);
for (i = 0; i < cnum; i++)
planes[i][ptr] = elm[i];
if (alp) planes[alp][ptr] = elm[3];
ptr++;
}
}
for (y = 0; y < cinf->height; y++) {
int curp, pw, n, v, w, totalw, totalv;
int xlow, xhigh, ylow, yhigh;
ylow = (y > 2) ? -2 : -y;
if ((yhigh = cinf->height - 1 - y) > 2) yhigh = 2;
ptr = cinf->width * (y + 3);
curp = cinf->width * y;
for (x = 0; x < cinf->width; x++, ptr++, curp++) {
if (alp) {
planes[alp][curp] = w = planes[alp][ptr];
if (w == AlphaTransp) {
for (n = 0; n < cnum; n++)
planes[n][curp] = 255;
continue;
}
}
xlow = (x > 2) ? -2 : -x;
if ((xhigh = cinf->width - 1 - x) > 2) xhigh = 2;
for (n = 0; n < cnum; n++) {
totalv = 0;
totalw = 0;
for (i = ylow; i < yhigh; i++) {
pw = cinf->width * (y + 3 + i);
for (j = xlow; j < xhigh; j++) {
totalw += w = weight[i+2][j+2];
if (w)
totalv += planes[n][pw+x+j] * w;
}
}
if (op == Enhance) {
w = planes[n][ptr];
v = totalv / totalw - w;
w -= (int)(factor * v + 0.5);
}else {
w = (int)(factor * totalv);
v = (planes[n][ptr] - 128) * bright;
w += v + 128;
}
planes[n][curp] = (w < 0) ? 0
: ((w > 255) ? 255 : w);
}
}
}
return 0;
}
/* Local Method */
- (int)doEnhance:(int)op filename:(const char *)fn map:(unsigned char **)map
parent:(ToyWin *)parent
info:(commonInfo *)cinf with:(float)degree : (float)bright
{
ToyWin *tw;
int err = 0;
id text;
commonInfo *newinf = NULL;
unsigned char *working[MAXPLANE];
working[0] = NULL;
tw = NULL;
if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
goto ErrEXIT;
*newinf = *cinf;
newinf->bits = 8;
newinf->isplanar = YES;
newinf->xbytes = newinf->width;
newinf->palsteps = 0;
newinf->palette = NULL;
text = [theController messageDisplay:
(op == Enhance) ? "Enhancing..." :
((op == Emboss) ? "Embossing..." : "Posterizing...")];
tw = [[ToyWin alloc] init:parent by:op];
[tw initLocateWindow:fn width:newinf->width height:newinf->height];
if (op == Posterize) {
id pos = [Posterizer alloc];
if (pos != nil && [pos initWith:cinf newmap:working]) {
[pos setMessageText: text];
[pos posterize:map with:degree : bright];
}else
err = Err_MEMORY;
if (pos) [pos free];
}else {
resetPixel(map, 0);
err = edge(op, cinf, degree, bright, working);
}
[theController messageDisplay:NULL];
if (err) goto ErrEXIT;
[tw makeComment: newinf from: cinf];
if ([tw drawView:working info: newinf] == nil)
goto ErrEXIT;
[theController newWindow: tw];
return 0;
ErrEXIT:
if (working[0]) free((void *)working[0]);
if (newinf) free((void *)newinf);
if (tw) [tw free];
return Err_MEMORY;
}
/* Local Method */
- enhanceOrEmboss:(int)op and:(float)degree :(float)bright
{
ToyWin *tw;
ToyView *tv = NULL;
NXImageRep *rep;
commonInfo *cinf;
unsigned char *map[MAXPLANE];
char fn[MAXFILENAMELEN];
const char *fnam, *opstr;
int err;
if (degree == 0.0 || (tw = [self keyParentWindow: op]) == nil) {
NXBeep();
return self;
}
tv = [tw toyView];
fnam = [tw filename];
cinf = [tv commonInfo];
if (![self checkCommonInfo:cinf filename:fnam]
|| cinf->width >= MAXWidth - 4)
return self;
rep = [[tv image] bestRepresentation];
[(NXBitmapImageRep *)rep getDataPlanes: map];
if ((err = initGetPixel(cinf)) != 0) {
errAlert(fnam, err);
return self;
}
opstr = (op == Enhance) ? "Enhance":
((op == Emboss) ? "Emboss" : "Posterize");
sprintf(fn, "%s(%s)", fnam, opstr);
if ((err = [self doEnhance:op filename:fn map:map
parent:tw info:cinf with:degree :bright]) != 0)
errAlert(fnam, err);
return self;
}
- enhanceWith:(float)degree
{
[self enhanceOrEmboss:Enhance and:degree : 0.0];
return self;
}
- embossWith:(float)degree and:(float)bright
{
[self enhanceOrEmboss:Emboss and:degree : bright];
return self;
}
- posterizeWith:(float)diff and:(float)ctrl
{
[self enhanceOrEmboss:Posterize and:diff : ctrl];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.