This is ImageOpr.m in view mode; [Download] [Up]
#import "../ImageOpr.h"
#import <appkit/Application.h>
#import <appkit/publicWraps.h>
#import <appkit/NXEPSImageRep.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/Control.h>
#import <appkit/Panel.h>
#import <appkit/TextField.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <streams/streams.h>
#import <sys/types.h>
#import <libc.h>
#import "../TVController.h"
#import "../ToyWin.h"
#import "../ToyWinEPS.h"
#import "../ToyView.h"
#import "../common.h"
#import "../getpixel.h"
#import "imageOperation.h"
@implementation ImageOpr
- keyParentWindow:(int)op
{
ToyWin *tw, *win;
if ((tw = [theController keyWindow]) == nil)
return nil;
if (op != NoOperation && [tw madeby] == op) {
win = [tw parent];
if (win && [theController isOpenedID: win])
return win;
}
return tw;
}
- (BOOL)checkCommonInfo:(const commonInfo *)cinf filename:(const char *)fn
{
if (cinf->type == Type_eps) {
warnAlert(fn, Err_EPS_IMPL);
return NO;
}
if (cinf->cspace == NX_CMYKColorSpace) {
warnAlert(fn, Err_IMPLEMENT);
return NO;
}
if (cinf->width >= MAXWidth || cinf->height >= MAXWidth) {
errAlert(fn, Err_MEMORY);
return NO;
}
return YES;
}
static void sub_clip(NXRect *select, commonInfo *cinf, commonInfo *newinf,
int idx[], unsigned char **working)
{
int x, y;
int i, pidx, ptr;
int pix[MAXPLANE];
int skipx = select->origin.x;
int skipt = cinf->width - (skipx + select->size.width);
int skipy = cinf->height - (select->origin.y + select->size.height);
for (y = 0; y < skipy; y++) {
for (x = 0; x < cinf->width; x++)
getPixelA(pix);
}
for (y = 0; y < newinf->height; y++) {
ptr = y * newinf->width;
for (x = 0; x < skipx; x++)
getPixelA(pix);
for (x = 0; x < newinf->width; x++) {
getPixelA(pix);
for (i = 0; i <= ALPHA; i++) {
if ((pidx = idx[i]) < 0) continue;
working[pidx][ptr + x] = pix[i];
}
}
for (x = 0; x < skipt; x++)
getPixelA(pix);
}
}
/******* Random Functions ********/
#define ValBAND 32
#define BANDMask 0x1f
#define ValBIAS 16
static int randomFreq = 0, randomMag = 0;
- setRandom:(float)freq :(float)mag
{
if (!randomMag)
srandom(getpid());
randomFreq = freq * freq * 256.0;
randomMag = (int)(mag * mag * (ValBAND - ValBIAS + 256.0)) + ValBIAS;
return self;
}
static int random_value(int pix)
{
long r, v;
r = random();
if ((r & 0xff) >= randomFreq)
return pix;
r = random();
v = randomMag - ((r >> 1) & BANDMask);
if (r & 1) v += pix;
else v = pix - v;
return (v > 255) ? 255 : ((v < 0) ? 0 : v);
}
static void sub_negative(int op, NXRect *select,
commonInfo *newinf, int idx[], unsigned char **working)
{
int x, y;
int i, pidx, ptr, alp;
int pix[MAXPLANE];
int selectflag = NO, yout, xout;
int skipx = 0, skipy = 0, yorig = 0;
if (select && select->size.width > 0) {
skipx = select->origin.x + select->size.width - 1;
skipy = newinf->height - select->origin.y - 1;
yorig = skipy - select->size.height + 1;
selectflag = YES;
}
if ((alp = idx[ALPHA]) < 0)
alp = 0; /* index of Alpha > 0 */
for (y = 0; y < newinf->height; y++) {
yout = (selectflag && (y < yorig || y > skipy));
ptr = y * newinf->width;
for (x = 0; x < newinf->width; x++) {
xout = (yout ||
(selectflag && (x < select->origin.x || x > skipx)));
getPixelA(pix);
if (xout) {
for (i = 0; i < ALPHA; i++) {
if ((pidx = idx[i]) < 0) continue;
working[pidx][ptr + x] = pix[i];
}
}else if (op == Negative) {
for (i = 0; i < ALPHA; i++) {
if ((pidx = idx[i]) < 0) continue;
working[pidx][ptr + x] = 0xff - pix[i];
}
}else {
for (i = 0; i < ALPHA; i++) {
if ((pidx = idx[i]) < 0) continue;
working[pidx][ptr + x] = random_value(pix[i]);
}
}
if (alp) /* Alpha */
working[alp][ptr + x] = pix[i];
}
}
if (newinf->palette) {
unsigned char *p;
paltype *pal = newinf->palette;
for (x = 0; x < newinf->palsteps; x++) {
p = pal[x];
for (i = 0; i < 3; i++)
p[i] = 0xff - p[i];
}
}
}
/* Local Method */
- doBitmap:(int)op parent:parent
filename:(const char *)fn info:(commonInfo *)cinf
to:(int)angle rect:(NXRect *)select
{
ToyWin *tw;
commonInfo *newinf = NULL;
unsigned char *working[MAXPLANE], *planes[MAXPLANE];
int i, pl;
int idx[MAXPLANE];
BOOL rotalpha = NO, hadalpha = NO;
working[0] = planes[0] = NULL;
tw = NULL;
if ((newinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL)
goto ErrEXIT;
*newinf = *cinf;
if (cinf->cspace == NX_OneIsBlackColorSpace)
newinf->cspace = NX_OneIsWhiteColorSpace;
/* getPixel() fixes 0 as Black */
newinf->isplanar = YES;
if (op == Rotation) {
rotate_size(angle, cinf, newinf);
if (newinf->width >= MAXWidth || newinf->height >= MAXWidth)
goto ErrEXIT;
}else if (op == Clip) {
newinf->width = select->size.width;
newinf->height = select->size.height;
}
newinf->xbytes = byte_length(newinf->bits, newinf->width);
/** if rotalpha==YES one color(transparent) is added **/
if (cinf->palette
&& (cinf->alpha || !rotalpha || newinf->palsteps < FIXcount)) {
newinf->palette = copyPalette(cinf->palette, newinf->palsteps);
if (newinf->palette == NULL)
goto ErrEXIT;
}else {
newinf->palette = NULL;
newinf->palsteps = 0;
}
pl = newinf->numcolors;
for (i = 0; i < pl; i++) idx[i] = i;
for (i = pl; i < MAXPLANE; i++) idx[i] = -1;
if (op == Rotation && (angle % 90 != 0))
newinf->alpha = rotalpha = YES;
if (newinf->alpha) idx[ALPHA] = pl++;
if (allocImage(working, newinf->width, newinf->height, 8, pl))
goto ErrEXIT;
tw = [[ToyWin alloc] init:parent by:op];
[tw initLocateWindow:fn width:newinf->width height:newinf->height];
if (op == Clip) {
sub_clip(select, cinf, newinf, idx, working);
if (newinf->alpha) {
int aw = newinf->width * newinf->height;
unsigned char *ap = working[pl-1];
for (i = 0; i < aw; i++, ap++)
if (isAlphaTransp(*ap)) {
hadalpha = YES;
break;
}
}
}else if (op == Negative || op == RandomPttn) {
sub_negative(op, select, newinf, idx, working);
if (newinf->alpha) hadalpha = hadAlpha();
}else /* Rotation | Horizontal | Vertical */ {
if (sub_rotate(op, angle, cinf, newinf, idx, working))
goto ErrEXIT;
if (rotalpha)
hadalpha = YES;
else if (newinf->alpha)
hadalpha = hadAlpha();
}
if (newinf->alpha && !hadalpha) {
newinf->alpha = NO;
working[--pl] = NULL;
}
if (newinf->alpha && newinf->palette && newinf->palsteps >= 256) {
free((void *)newinf->palette); /* 256 colors are too much */
newinf->palette = NULL;
newinf->palsteps = 0;
}
[tw makeComment: newinf from: cinf];
if (newinf->bits < 8) {
if (allocImage(planes, newinf->width, newinf->height,
newinf->bits, pl))
goto ErrEXIT;
packWorkingImage(newinf, pl, working, planes);
if ([tw drawView:planes info: newinf] == nil)
goto ErrEXIT;
free((void *)working[0]);
}else {
if ([tw drawView:working info: newinf] == nil)
goto ErrEXIT;
}
[theController newWindow: tw];
return self;
ErrEXIT:
if (working[0]) free((void *)working[0]);
if (planes[0]) free((void *)planes[0]);
if (newinf) {
if (newinf->palette) free((void *)newinf->palette);
free((void *)newinf);
}
if (tw) [[tw window] performClose: self];
/* This call frees tw */
return nil;
}
- doRotateFlipClip: (int)op to:(int)angle
{
ToyWin *tw;
ToyView *tv = NULL;
NXImageRep *rep;
commonInfo *cinf;
NXRect *select = NULL;
unsigned char *map[MAXPLANE];
const char *ex = NULL, *fnam;
char fn[256];
int err;
if ((tw = [theController keyWindow]) != nil) {
tv = [tw toyView];
if (op == Clip) {
select = [tv selectedScaledRect];
if (select->size.width < 1.0 || select->size.height < 1.0)
tw = nil;
}else if (op == Negative || op == RandomPttn)
select = [tv selectedScaledRect];
}
if (tw == nil) {
NXBeep();
return self;
}
cinf = [tv commonInfo];
if (cinf->width >= MAXWidth || cinf->height >= MAXWidth) {
errAlert([tw filename], Err_MEMORY);
return self;
}
switch (op) {
case Rotation: ex = "Rotate"; break;
case Clip: ex = "Clip"; break;
case Negative: ex = "Negative"; break;
case RandomPttn: ex = "Random"; break;
case Horizontal:
case Vertical:
default: ex = "Flip"; break;
}
fnam = [tw filename];
sprintf(fn, "%s(%s)", fnam, ex);
if (cinf->type == Type_eps) {
NXStream *stream;
ToyWinEPS *newtw;
commonInfo info;
if (op == Negative || op == RandomPttn) {
warnAlert(fnam, Err_EPS_IMPL);
return self;
}
if (op == Clip)
stream = [(ToyWinEPS *)tw clipEPS:select error:&err];
else { /* Rotate | Horizontal | Vertical */
rotate_size(angle, cinf, &info);
stream = [(ToyWinEPS *)tw rotateEPS:op to:angle
width:info.width height:info.height
name:fn error:&err];
}
if (stream == NULL) {
errAlert(fnam, err);
return self;
}
newtw = [[ToyWinEPS alloc] init:tw by:op];
err = [newtw drawFromFile:(const char *)fn or:stream];
NXCloseMemory(stream, NX_FREEBUFFER);
if (err) {
errAlert(fnam, err);
[newtw free];
}else
[theController newWindow: newtw];
return self;
}
if (cinf->cspace == NX_CMYKColorSpace) {
warnAlert(fnam, Err_IMPLEMENT);
return self;
}
rep = [[tv image] bestRepresentation];
[(NXBitmapImageRep *)rep getDataPlanes: map];
if ((err = initGetPixel(cinf)) != 0) {
errAlert(fnam, err);
return self;
}
resetPixel(map, 0);
if ([self doBitmap:op parent:tw
filename:fn info:cinf to:angle rect:select] == nil)
errAlert(fn, Err_MEMORY);
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.