home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula
/
nebula.bin
/
SourceCode
/
MiniExamples
/
TIFFandEPS
/
ImageReader.m
< prev
next >
Wrap
Text File
|
1993-01-19
|
10KB
|
359 lines
/* ImageReader.m
* Purpose: The application delegate. This class reads in and saves out EPS
* and TIFF images.
*
* You may freely copy, distribute, and reuse the code in this example.
* NeXT disclaims any warranty of any kind, expressed or implied, as to its fitness
* for any particular use.
*
*/
#import <math.h>
#import <strings.h>
#import <dpsclient/wraps.h>
#import <appkit/graphics.h>
#import <appkit/OpenPanel.h>
#import <appkit/SavePanel.h>
#import <appkit/NXImage.h>
#import <appkit/Application.h>
#import <appkit/Menu.h>
#import <appkit/MenuCell.h>
#import <appkit/Matrix.h>
#import <appkit/TextField.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/Control.h>
#import <appkit/publicWraps.h>
#import <appkit/tiff.h>
#import "ImageReader.h"
#import "ImageView.h"
@implementation ImageReader : Object
/* -windowWillClose:
* Window delegate method. Called before a window is about to be
* closed. If the last window is being closed, dim the "Save Image..."
* menu item.
*/
- windowWillClose:sender
{
int cnt;
id menu = [NXApp mainMenu];
id matrix = [menu itemList];
id menuCell = [matrix cellAt: 1:0]; /* Location of the "Save..." menu item */
/* The minimum window count for this app is 2 when there */
/* are no open TIFF/EPS windows -- if 3 or more windows are */
/* open, then the "Save Image..." menu item should be enabled. */
NXCountWindows(&cnt);
if (cnt <= 3)
[menuCell setEnabled: NO];
return self;
}
/* -windowDidBecomeMain:
* Window delegate method. Called after the window has become main.
* The theory being if any main windows exist, then enable the "Save Image..."
* menu item.
*/
- windowDidBecomeMain:sender
{
id menu = [NXApp mainMenu];
id matrix = [menu itemList];
id menuCell = [matrix cellAt: 1:0];
[menuCell setEnabled:YES];
return self;
}
/* -appDidInit:
* Application delegate method. Called after application has been initialized
* and before any events are received.
*/
- appDidInit:sender
{
/* Ensure that a required file type has been set for the */
/* save panel. Also initializes the save panel instance */
/* variable */
saveReq = [SavePanel new];
[saveReq setRequiredFileType: tiffType];
/* The default TIFF compression is LZW. Disable JPEG */
/* factor text field. */
[JPEGvalue setEnabled:NO];
return self;
}
/* - openRequest:
* Called when the user selects "Open Image..." from the menu. Both EPS
* and TIFF images are supported.
*/
- openRequest:sender
{
id openReq;
const char *fileName;
const char *const fileTypes[] = {tiffType, epsType, NULL};
openReq = [OpenPanel new];
if ([openReq runModalForTypes:fileTypes] && (fileName =[openReq filename]))
{
[self openFile:fileName];
}
return self;
}
/* -openFile:
* Does the work of creating a window exactly the size of the image [tiff or eps].
* Then creates an instance of ImageView and replaces the contentView of the
* window with the ImageView instance.
*/
-(BOOL) openFile:(const char *)fileName
{
id anImage, window, view;
NXRect rect;
char title[100], *name;
/* Read in the EPS or TIFF image */
anImage = [[NXImage alloc] initFromFile:fileName];
if ([anImage lastRepresentation] == nil)
return NO;
/* We will be scaling this image */
[anImage setScalable: YES];
/* Create an instance of ImageView */
if ((view = [[ImageView alloc] initFromImage: anImage]) == nil)
return NO;
/* Create a new window the size of the image */
[view getFrame:&rect];
window = [[Window alloc] initContent:&rect
style:NX_TITLEDSTYLE
backing:NX_RETAINED
buttonMask:NX_CLOSEBUTTONMASK
defer:NO];
/* Set the window delegate */
[window setDelegate:self];
/* Replace the current contentView of the window with my new view */
/* and free up the old contentView */
[[window setContentView:view] free];
[window center]; /* Put the window in the center of the screen */
/* Set the title of the window to be the title of the file */
name = rindex(fileName, '/');
sprintf (title, "%s", name ? name+1 : fileName);
[window setTitle:title];
[window makeKeyAndOrderFront:self];
[window display];
return YES;
}
/* selectFormat:
* This method is called when the user selects a button in the formatMatrix.
* It dims or brightens other panel items, as appropriate. For example, if saving
* an image as EPS, the DPI matrix needs to be dimmed as it is not applicable.
*/
- selectFormat:sender
{
switch ([formatMatrix selectedCol])
{
case TIFF_FORMAT:
[DPIpopup setEnabled:YES];
[DPIvalue setEnabled:YES];
[compressionType setEnabled:YES];
[saveReq setRequiredFileType: tiffType];
[self selectCompression: nil];
break;
case EPS_FORMAT:
[DPIpopup setEnabled:NO];
[DPIvalue setEnabled:NO];
[compressionType setEnabled:NO];
[saveReq setRequiredFileType: epsType];
[JPEGlabel setTextGray: NX_DKGRAY];
[JPEGvalue setEnabled:NO];
break;
}
return self;
}
/* selectCompression:
* This method is called when the user selects a button in the
* compressionType matrix. It dims or brightens the JPEG value
* field, as appropriate.
*/
- selectCompression:sender
{
switch ([compressionType selectedCol])
{
case LZW_COMPRESSION:
[JPEGlabel setTextGray: NX_DKGRAY];
[JPEGvalue setEnabled:NO];
break;
case JPEG_COMPRESSION:
[JPEGlabel setTextGray: NX_BLACK];
[JPEGvalue setEnabled:YES];
break;
}
return self;
}
/* -saveRequest:
* This method is called when the user selects "Save Image..." from the menu.
* An accessory view is installed in the save panel which allows the user to specify
* saving the image as either EPS or TIFF. In the case of TIFF, the user must
* provide a DPI value.
*/
- saveRequest:sender
{
id window;
const char *fileName, *title;
char name[100], *extension;
int cnt;
window = [NXApp keyWindow];
/* can't save anything if no windows are available */
if (window == nil) return self;
title = [window title];
/* Yank off the extension */
extension = index(title, '.');
cnt = (int)extension-(int)title;
strncpy(name, title, cnt);
name[cnt] = '\0';
/*
* Insert my accessory view into the save panel.
* This view allows [forces] the user to select either EPS or TIFF when
* saving the image. If the image is to be saved as TIFF, the user must
* supply a DPI value -- the default resolution is 72DPI.
*/
if ([saveReq accessoryView] == nil)
[saveReq setAccessoryView: [accessoryWindow contentView]];
if ([saveReq runModalForDirectory: "." file: name] &&
(fileName =[saveReq filename]))
{
switch ([formatMatrix selectedCol])
{
case TIFF_FORMAT:
[self saveTIFF:fileName inWindow: window];
break;
case EPS_FORMAT:
[self saveEPS:fileName inWindow: window];
break;
}
}
return self;
}
/* -saveTIFF: inWindow:
* This method saves a specified view to disk with the specified
* fileName using the TIFF format. An instance of NXBitmapImageRep
* is created with the desired resolution, then written to a stream and
* then to disk using LZW compression. The instance of NXBitmapImageRep
* is then freed.
*/
- (BOOL)saveTIFF: (const char *)fileName inWindow: window
{
id tiffImage, theImage;
NXSize origSize, newSize;
NXRect rect;
int DPI;
BOOL error = NO;
NXStream *s;
float factor;
char *dpiInput;
/* Get the original size and squirrel that away. */
/* We'll be changing the size to reflect the desired DPI of the TIFF file */
/* and then image it at that resolution. */
theImage = [[window contentView] image];
[theImage getSize:&origSize];
dpiInput = (char *)[DPIpopup title];
sscanf(dpiInput,"%d",&DPI);
newSize.width = origSize.width * (float)DPI/ POINTSPERINCH;
newSize.height = origSize.height * (float)DPI/ POINTSPERINCH;
[theImage setSize: &newSize];
/* Create a tiff image at the desired size */
[theImage lockFocus];
rect.origin.x = rect.origin.y = 0.0;
rect.size = newSize;
tiffImage = [[NXBitmapImageRep alloc] initData: NULL fromRect: &rect];
[theImage unlockFocus];
[theImage setSize: &origSize];
[tiffImage setSize: &origSize];
if (!tiffImage)
return NO;
s = NXOpenMemory (NULL, 0, NX_READWRITE);
if (s)
{
switch ([compressionType selectedCol])
{
case LZW_COMPRESSION:
[tiffImage writeTIFF:s usingCompression:NX_TIFF_COMPRESSION_LZW];
break;
case JPEG_COMPRESSION:
if ([tiffImage bitsPerSample] < 4)
{
NXRunAlertPanel("TIFFandEPS Save Error",
"JPEG compression requires 4 or 8 bits per sample for grayscale or RGB",
NULL, NULL, NULL);
error = YES;
break;
}
factor = [JPEGvalue floatValue];
if (factor < 1.0) factor = 1.0;
if (factor > 255.0) factor = 255.0;
[tiffImage writeTIFF:s usingCompression:NX_TIFF_COMPRESSION_JPEG
andFactor: factor];
break;
}
NXFlush (s);
if (!error)
{
if (NXSaveToFile (s, fileName))
{
error = YES;
perror (fileName);
}
}
NXCloseMemory (s, NX_FREEBUFFER);
}
else error = YES;
[tiffImage free];
return (error ? NO : YES);
}
/* -saveEPS: inWindow:
* This method saves a specified view to disk with the specified
* fileName using the EPS format. To do this the copyPSCode
* method of view is used on the view with the result going to a stream
* and then to disk.
*/
- (BOOL)saveEPS: (const char *)fileName inWindow: window
{
NXRect rect;
BOOL error = NO;
NXStream *s;
s = NXOpenMemory(NULL, 0, NX_WRITEONLY);
if (s)
{
[[window contentView] getFrame:&rect];
[[window contentView] copyPSCodeInside:&rect to:s];
NXFlush(s);
if (NXSaveToFile (s, fileName))
{
error = YES;
perror (fileName);
}
NXCloseMemory(s, NX_FREEBUFFER);
}
else error = YES;
return (error? NO : YES);
}
@end