// // MyDocument.m // PRICE // // Created by Riccardo Mottola on Thu Dec 12 2002. // Copyright (c) 2002-2005 Carduus. All rights reserved. // // This program is free software; you can redistribute it and/or modify it under the terms of the version 2 of the GNU General Public License as published by the Free Software Foundation. // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. #import "MyDocument.h" #import #import "PRGrayscaleFilter.h" #import "PRConvolve55.h" #import "PRTransforms.h" #import "PRFourier.h" #import "PRDFTLowPass.h" #import "PRDFTHighPass.h" #import "PREqualize.h" #import "PRTraceEdges.h" #import "PRCustTraceEdges.h" #import "PRMedian.h" #import "PRScale.h" #import "PRCrop.h" #import "PRBriCon.h" @implementation MyDocument // eliminated windowNibName since we use makeWindowControllers - (void)windowControllerDidLoadNib:(NSWindowController *) aController { [super windowControllerDidLoadNib:aController]; // Add any code here that need to be executed once the windowController has loaded the document's window. } - (NSData *)dataRepresentationOfType:(NSString *)aType { // Insert code here to write your document from the given data. You can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead. // return nil; return [activeImage TIFFRepresentation]; } - (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType { // Insert code here to read your document from the given data. You can also choose to override -loadFileWrapperRepresentation:ofType: or -readFromFile:ofType: instead. PRImage *tempImage; tempImage = [[PRImage alloc] initWithData:data]; if (tempImage != nil) { NSBitmapImageRep *tmpImageRep; PRImage *newImage; NSBitmapImageRep *newImageRep; unsigned char *dataPtr; unsigned char *dataPtr2; unsigned int k; unsigned int w, h, s; /* if the loaded image is in BlackColorSpace we convert it to WhiteColorSpace */ /* which is the only TIFF rep used internally and generated by PRICE */ tmpImageRep = [[tempImage representations] objectAtIndex: 0]; w = [tmpImageRep pixelsWide]; h = [tmpImageRep pixelsHigh]; if ([[tmpImageRep colorSpaceName] isEqualToString: NSCalibratedBlackColorSpace] || [[tmpImageRep colorSpaceName] isEqualToString: NSDeviceBlackColorSpace]) { /* converting the colorspace */ newImage = [[PRImage alloc] initWithSize:NSMakeSize(w, h)]; newImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:w pixelsHigh:h bitsPerSample:8 samplesPerPixel:1 hasAlpha:NO isPlanar:NO colorSpaceName:NSCalibratedWhiteColorSpace bytesPerRow:0 bitsPerPixel:0]; s = w * h; dataPtr = [tmpImageRep bitmapData]; dataPtr2 = [newImageRep bitmapData]; for (k = 0; k < s; k++) *dataPtr2++ = UCHAR_MAX - *dataPtr++; [newImageRep setColorSpaceName:NSCalibratedWhiteColorSpace]; [newImage addRepresentation:newImageRep]; [newImageRep release]; [tempImage release]; tempImage = [newImage retain]; } } oldImage = nil; /* returns a bool to be able to know if loading was successul */ if (tempImage != nil) { /* we setActiveImage won't set the image info yet (why?) */ [self setActiveImage:tempImage]; [tempImage release]; return YES; } else return NO; } - (IBAction)saveDocumentAs:(id)sender /* we override the super class to change the extensionand type of the file */ { NSString *filepath; filepath = [self fileName]; filepath = [[filepath stringByDeletingPathExtension] stringByAppendingString: @".tiff"]; [self setFileName:filepath]; [self setFileType: @"tiff"]; [super saveDocumentAs: sender]; } - (void)makeWindowControllers /* instantiate PRWindowController */ { windowController = [[PRWindowController alloc] initWithWindowNibName:@"PRWindow"]; [self addWindowController:windowController]; [windowController release]; /* set undo levels */ [[self undoManager] setLevelsOfUndo:1]; } - (NSWindow *)window { return [windowController window]; } - (NSView *)view { return [windowController view]; } - (PRImage *)activeImage /* method to access the active image */ { return activeImage; } - (void)setActiveImage: (PRImage *)theImage /* method to set the active image */ { if (activeImage != nil) [activeImage release]; activeImage = [theImage retain]; /* window controller is still nil here the first time we load an image * thus the info must be manually set after the nib finished loading */ [windowController setImageToDraw:activeImage]; } - (void)copy:(id)sender { NSPasteboard *pboard; pboard = [NSPasteboard generalPasteboard]; [pboard declareTypes:[NSArray arrayWithObjects:NSTIFFPboardType, nil] owner:nil]; [pboard setData:[activeImage TIFFRepresentation] forType:NSTIFFPboardType]; } - (void)paste:(id)sender { NSUndoManager *uMgr; NSPasteboard *pboard; NSString *type; NSData *tempData; PRImage *tempImage; pboard = [NSPasteboard generalPasteboard]; type = [pboard availableTypeFromArray:[NSArray arrayWithObjects:NSTIFFPboardType, nil]]; if (type != nil) { if ([type isEqualToString:NSTIFFPboardType]) { /* get the clipboard data */ tempData = [pboard dataForType:NSTIFFPboardType]; if (tempData != nil) { uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Paste"]; /* save the current image */ [self saveCurrentImage]; tempImage = [[PRImage alloc] initWithData:tempData]; [self setActiveImage: tempImage]; [tempImage release]; [[windowController view] setFrameSize:[activeImage size]]; [[windowController view] setNeedsDisplay:YES]; } else { /* guidelines say I should put a panel */ /* #### fixme */ NSLog(@"something went wrong in paste"); } } else NSLog(@"received a paste of unhandled type: %@", type); } } - (void)makeGrayscale:(id)sender { PRGrayscaleFilter *filter; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Make Grayscale"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ filter = [[PRGrayscaleFilter alloc] init]; [self setActiveImage: [filter filterImage:activeImage]]; [filter release]; } - (void)makeConvolve55:(int[5][5])mat: (int)offset :(float)scale :(BOOL)autoScale :(PRCProgress *)prPan { PRConvolve55 *conv; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Convolve 5x5"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ conv = [[PRConvolve55 alloc] init]; [self setActiveImage: [conv convolveImage:activeImage :mat :offset :scale :autoScale :prPan]]; [conv release]; } - (void)makeDFT:(id)sender { PRFourier *fourier; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"FFT"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ fourier = [[PRFourier alloc] init]; [self setActiveImage: [fourier transformImage:activeImage]]; [fourier release]; } - (void)makeDFTLowPass :(BOOL)autoRange :(float) bandPassFreq :(float) bandStopFreq :(PRCProgress *)prPan { PRDFTLowPass *dftLP; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"DFT LowPass"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ dftLP = [[PRDFTLowPass alloc] init]; [self setActiveImage: [dftLP transformImage:activeImage :autoRange :bandPassFreq :bandStopFreq :prPan]]; [dftLP release]; } - (void)makeDFTHighPass :(BOOL)autoRange :(float) bandPassFreq :(float) bandStopFreq :(PRCProgress *)prPan { PRDFTHighPass *dftHP; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"DFT HighPass"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ dftHP = [[PRDFTHighPass alloc] init]; [self setActiveImage: [dftHP transformImage:activeImage :autoRange :bandPassFreq :bandStopFreq :prPan]]; [dftHP release]; } - (void)makeTransposed:(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Transpose"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr = [[PRTransforms alloc] init]; [self setActiveImage: [tr transposeImage:activeImage]]; [tr release]; [[windowController view] setFrameSize:[activeImage size]]; [[windowController view] setNeedsDisplay:YES]; } - (void)makeRotated90 :(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Rotate 90"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr = [[PRTransforms alloc] init]; [self setActiveImage: [tr rotateImage90:activeImage]]; [tr release]; [[windowController view] setFrameSize:[activeImage size]]; [[windowController view] setNeedsDisplay:YES]; } - (void)makeRotated180 :(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Rotate 180"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr= [[PRTransforms alloc] init]; [self setActiveImage: [tr rotateImage180:activeImage]]; [tr release]; } - (void)makeRotated270 :(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Rotate 270"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr = [[PRTransforms alloc] init]; [self setActiveImage: [tr rotateImage270:activeImage]]; [tr release]; [[windowController view] setFrameSize:[activeImage size]]; [[windowController view] setNeedsDisplay:YES]; } - (void)makeFlippedVert :(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Flip Vertical"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr = [[PRTransforms alloc] init]; [self setActiveImage: [tr flipImageVert:activeImage]]; [tr release]; } - (void)makeFlippedHoriz :(id)sender { PRTransforms *tr; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Flip Horizontal"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ tr = [[PRTransforms alloc] init]; [self setActiveImage: [tr flipImageHoriz:activeImage]]; [tr release]; } - (void)makeEqualization :(int)colorSpace :(id)sender { PREqualize *equal; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Equalize"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ equal = [[PREqualize alloc] init]; [self setActiveImage: [equal equalizeImage:activeImage :colorSpace]]; [equal release]; } - (void)makeBriCon :(int)bri :(float)con { PRBriCon *briCon; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Brightness & Contrast"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ briCon = [[PRBriCon alloc] init]; [self setActiveImage: [briCon adjustImage :activeImage :bri :con]]; [briCon release]; } - (void)makeTraceEdges :(int)filterType :(BOOL)useTh :(float)thLev :(BOOL)doZeroC { PRTraceEdges *traceEdges; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Trace Edges"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ traceEdges = [[PRTraceEdges alloc] init]; [self setActiveImage: [traceEdges edgeImage :activeImage :filterType :useTh :thLev :doZeroC]]; [traceEdges release]; } - (void)makeCustTraceEdges :(int)filterType :(float)thLev :(BOOL)doZeroC :(BOOL)do1 :(enum medianForms)form1 :(int)size1 :(BOOL)sep1 :(BOOL)do2 :(enum medianForms)form2 :(int)size2 :(BOOL)sep2 :(BOOL)do3 :(enum medianForms)form3 :(int)size3 :(BOOL)sep3 :(PRCProgress *)prPan { PRCustTraceEdges *traceEdges; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Custom Trace Edges"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ traceEdges = [[PRCustTraceEdges alloc] init]; [self setActiveImage: [traceEdges edgeImage :activeImage :filterType :thLev :doZeroC :do1 :form1 :size1 :sep1 :do2 :form2 :size2 :sep2 :do3 :form3 :size3 :sep3 :prPan]]; [traceEdges release]; } - (void)makeMedian :(enum medianForms)form :(int)size :(BOOL)sep :(PRCProgress *)prPan { PRMedian *median; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Median"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ median = [[PRMedian alloc] init]; [self setActiveImage: [median medianImage :activeImage :form :size :sep :prPan]]; [median release]; } - (void)makeScale :(int)sizeX :(int)sizeY :(int)method :(PRCProgress *)prPan { PRScale *scale; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Scale"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ scale = [[PRScale alloc] init]; [self setActiveImage: [scale scaleImage :activeImage :sizeX :sizeY :method :prPan]]; [scale release]; [[windowController view] setFrameSize:[activeImage size]]; [[windowController view] setNeedsDisplay:YES]; } - (void)makeCrop :(int)sizeTop :(int)sizeBottom :(int)sizeLeft :(int)sizeRight { PRCrop *crop; NSUndoManager *uMgr; uMgr = [self undoManager]; /* save the method on the undo stack */ [[uMgr prepareWithInvocationTarget: self] restoreLastImage]; [uMgr setActionName:@"Crop"]; /* save the current image */ [self saveCurrentImage]; /* instantiate and run the filter */ crop = [[PRCrop alloc] init]; [self setActiveImage: [crop cropImage :activeImage :sizeTop :sizeBottom :sizeRight :sizeLeft]]; [crop release]; [[windowController view] setFrameSize:[activeImage size]]; [windowController scaleImage]; [[windowController view] setNeedsDisplay:YES]; } - (void)restoreLastImage { PRImage *tempImage; tempImage = [[PRImage alloc] initWithData: [activeImage TIFFRepresentation]]; [self setActiveImage: oldImage]; [oldImage release]; oldImage = tempImage; [[[self undoManager] prepareWithInvocationTarget: self] restoreLastImage]; [[windowController view] setFrameSize:[activeImage size]]; [windowController scaleImage]; [[windowController view] setNeedsDisplay:YES]; } - (void)saveCurrentImage { if (activeImage != nil) { if (oldImage != nil) [oldImage release]; oldImage = [[PRImage alloc] initWithData: [activeImage TIFFRepresentation]]; } } - (void)dealloc { [activeImage release]; [super dealloc]; } @end