home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / MiniExamples / AppKit / TIFFandEPS / ImageReader.m < prev    next >
Encoding:
Text File  |  1992-07-22  |  9.6 KB  |  343 lines

  1. /* ImageReader.m
  2.  *  Purpose: The application delegate.  This class reads in and saves out EPS
  3.  * and TIFF images.
  4.  *
  5.  *  You may freely copy, distribute, and reuse the code in this example.
  6.  *  NeXT disclaims any warranty of any kind, expressed or  implied, as to its fitness
  7.  *  for any particular use.
  8.  *
  9.  */
  10.  
  11. #import "ImageReader.h"
  12. #import "ImageView.h"
  13.  
  14. @implementation ImageReader : Object
  15.  
  16. /* -windowWillClose:
  17.  *     Window delegate method.  Called before a window is about to be
  18.  * closed.  If the last window is being closed, dim the "Save Image..."
  19.  * menu item.
  20.  */
  21. - windowWillClose:sender
  22. {
  23.     int cnt;
  24.     id menu = [NXApp mainMenu];
  25.     id matrix = [menu itemList];
  26.     id menuCell = [matrix cellAt: 1:0];  /* Location of the "Save..." menu item */
  27.    
  28.     /* The minimum window count for this app is 2 when there */
  29.     /* are no open TIFF/EPS windows -- if 3 or more windows are */
  30.     /* open, then the "Save Image..." menu item should be enabled. */
  31.     NXCountWindows(&cnt);
  32.     if (cnt <= 3)
  33.         [menuCell setEnabled: NO];
  34.     return self;
  35. }
  36.  
  37. /* -windowDidBecomeMain:
  38.  *     Window delegate method.  Called after the window has become main.
  39.  * The theory being if any main windows exist, then enable the "Save Image..."
  40.  * menu item.
  41.  */
  42. - windowDidBecomeMain:sender
  43. {
  44.     id menu = [NXApp mainMenu];
  45.     id matrix = [menu itemList];
  46.     id menuCell = [matrix cellAt: 1:0];
  47.  
  48.     [menuCell setEnabled:YES];
  49.     return self;
  50. }
  51.  
  52. /* -appDidInit:
  53.  *     Application delegate method.  Called after application has been initialized 
  54.  * and before any events are received.   
  55.  */
  56. - appDidInit:sender
  57. {
  58.     /* Ensure that a required file type has been set for the */
  59.     /* save panel.  Also initializes the save panel instance */
  60.     /* variable */
  61.     saveReq = [SavePanel new];
  62.     [saveReq setRequiredFileType: tiffType];
  63.     
  64.     /* The default TIFF compression is LZW.  Disable JPEG */
  65.     /* factor text field. */
  66.     [JPEGvalue setEnabled:NO];
  67.     return self;
  68. }
  69.  
  70. /*  - openRequest:
  71.  *     Called when the user selects "Open Image..." from the menu.  Both EPS 
  72.  * and TIFF images are supported.
  73.  */
  74. - openRequest:sender
  75. {
  76.     id             openReq;
  77.     const char    *fileName;
  78.     const char    *const fileTypes[] = {tiffType, epsType, NULL};  
  79.     
  80.     openReq = [OpenPanel new];
  81.     if ([openReq runModalForTypes:fileTypes] && (fileName =[openReq filename])) 
  82.     {
  83.     [self openFile:fileName];
  84.     }
  85.     return self;
  86. }
  87.  
  88. /* -openFile:
  89.  *     Does the work of creating a window exactly the size of the image [tiff or eps].  
  90.  * Then creates an instance of ImageView and replaces the contentView of the 
  91.  * window with the ImageView instance.
  92.  */
  93. -(BOOL) openFile:(const char *)fileName
  94. {
  95.     id  anImage, window, view;
  96.     NXRect    rect;
  97.     char title[100], *name;
  98.     
  99.     /* Read in the EPS or TIFF image */
  100.     anImage = [[NXImage alloc] initFromFile:fileName];
  101.     if ([anImage lastRepresentation] == nil)
  102.         return NO;
  103.  
  104.     /* We will be scaling this image */
  105.     [anImage setScalable: YES];
  106.  
  107.     /* Create an instance of ImageView */
  108.     if ((view = [[ImageView alloc] initFromImage: anImage]) == nil)
  109.     return NO;
  110.     
  111.     /* Create a new window the size of the image */
  112.     [view getFrame:&rect];
  113.     window = [[Window alloc] initContent:&rect
  114.             style:NX_TITLEDSTYLE
  115.             backing:NX_RETAINED
  116.             buttonMask:NX_CLOSEBUTTONMASK
  117.             defer:NO];
  118.     /* Set the window delegate */
  119.     [window setDelegate:self];
  120.             
  121.     /* Replace the current contentView of the window with my new view */
  122.     /*   and free up the old contentView */
  123.     [[window setContentView:view] free];
  124.     [window center];  /* Put the window in the center of the screen */
  125.  
  126.      /* Set the title of the window to be the title of the file */
  127.     name = rindex(fileName, '/');
  128.     sprintf (title, "%s", name ? name+1 : fileName);
  129.     [window setTitle:title];
  130.     [window makeKeyAndOrderFront:self];
  131.     [window display];
  132.     return YES;
  133. }
  134.  
  135. /* selectFormat:
  136.  *     This method is called when the user selects a button in the formatMatrix.
  137.  * It dims or brightens other panel items, as appropriate.  For example, if saving
  138.  * an image as EPS, the DPI matrix needs to be dimmed as it is not applicable.
  139.  */
  140. - selectFormat:sender
  141. {    
  142.     switch ([formatMatrix selectedCol])
  143.     {
  144.     case TIFF_FORMAT:
  145.         [DPIpopup setEnabled:YES];
  146.     [DPIvalue setEnabled:YES];
  147.     [compressionType setEnabled:YES];
  148.     [saveReq setRequiredFileType: tiffType];
  149.         [self selectCompression: nil];
  150.         break;
  151.     case EPS_FORMAT:
  152.         [DPIpopup setEnabled:NO];
  153.     [DPIvalue setEnabled:NO];
  154.     [compressionType setEnabled:NO];
  155.     [saveReq setRequiredFileType: epsType];
  156.         [JPEGlabel setTextGray: NX_DKGRAY];
  157.     [JPEGvalue setEnabled:NO];
  158.         break;
  159.     }
  160.     return self;
  161. }
  162.  
  163. /* selectCompression:
  164.  *     This method is called when the user selects a button in the 
  165.  * compressionType matrix.  It dims or brightens the JPEG value
  166.  * field, as appropriate.
  167.  */
  168. - selectCompression:sender
  169. {
  170.     switch ([compressionType selectedCol])
  171.     {
  172.     case LZW_COMPRESSION:
  173.         [JPEGlabel setTextGray: NX_DKGRAY];
  174.     [JPEGvalue setEnabled:NO];
  175.         break;
  176.     case JPEG_COMPRESSION:
  177.         [JPEGlabel setTextGray: NX_BLACK];
  178.     [JPEGvalue setEnabled:YES];
  179.         break;
  180.     }
  181.     return self;
  182. }
  183.  
  184. /* -saveRequest:
  185.  *     This method is called when the user selects "Save Image..." from the menu.
  186.  * An accessory view is installed in the save panel which allows the user to specify
  187.  * saving the image as either EPS or TIFF.  In the case of TIFF, the user must
  188.  * provide a DPI value.
  189.  */
  190. - saveRequest:sender
  191. {
  192.     id window;
  193.     const char *fileName, *title;
  194.     char name[100], *extension;
  195.     int cnt;
  196.     
  197.     window = [NXApp keyWindow];
  198.     /* can't save anything if no windows are available */
  199.     if (window == nil) return self;  
  200.     title = [window title];
  201.     /* Yank off the extension */
  202.     extension = index(title, '.');
  203.     cnt = (int)extension-(int)title;
  204.     strncpy(name, title, cnt);
  205.     name[cnt] = '\0';
  206.     
  207.     /* 
  208.      * Insert my accessory view into the save panel.
  209.      * This view allows [forces] the user to select either EPS or TIFF when 
  210.      * saving the image.  If the image is to be saved as TIFF, the user must 
  211.      * supply a DPI value -- the default resolution is 72DPI. 
  212.      */
  213.     if ([saveReq accessoryView] == nil)
  214.         [saveReq setAccessoryView: [accessoryWindow contentView]];
  215.  
  216.     if ([saveReq runModalForDirectory: "."  file: name] && 
  217.        (fileName =[saveReq filename])) 
  218.     {
  219.         switch ([formatMatrix selectedCol])
  220.     {
  221.     case TIFF_FORMAT:
  222.         [self saveTIFF:fileName inWindow: window];
  223.         break;
  224.     case EPS_FORMAT:
  225.         [self saveEPS:fileName inWindow: window];
  226.         break;
  227.     }
  228.     }
  229.     return self;
  230. }
  231.     
  232. /* -saveTIFF: inWindow:
  233.  *    This method saves a specified view to disk with the specified 
  234.  * fileName using the TIFF format.  An instance of NXBitmapImageRep 
  235.  * is created with the desired resolution,  then written to a stream and 
  236.  * then to disk using LZW compression.  The instance of NXBitmapImageRep 
  237.  * is then freed.
  238.  */
  239. - (BOOL)saveTIFF: (const char *)fileName inWindow: window
  240. {
  241.     id tiffImage, theImage;
  242.     NXSize  origSize, newSize;
  243.     NXRect rect;
  244.     int         DPI;
  245.     BOOL error = NO;
  246.     NXStream *s;
  247.     float factor;
  248.     char *dpiInput;
  249.     
  250.     /* Get the original size and squirrel that away. */
  251.     /* We'll be changing the size to reflect the desired DPI of the TIFF file */
  252.     /* and then image it at that resolution. */
  253.     theImage = [[window contentView] image];
  254.     [theImage getSize:&origSize];
  255.     dpiInput = (char *)[DPIpopup title];
  256.     sscanf(dpiInput,"%d",&DPI);
  257.     newSize.width = origSize.width * (float)DPI/ POINTSPERINCH;
  258.     newSize.height = origSize.height * (float)DPI/ POINTSPERINCH;
  259.     [theImage setSize: &newSize];
  260.    
  261.     /* Create a tiff image at the desired size */
  262.     [theImage lockFocus];
  263.     rect.origin.x = rect.origin.y = 0.0;
  264.     rect.size = newSize;
  265.     tiffImage = [[NXBitmapImageRep alloc] initData: NULL  fromRect: &rect];
  266.     [theImage unlockFocus];
  267.     [theImage setSize: &origSize];
  268.     [tiffImage setSize: &origSize];
  269.     
  270.     if (!tiffImage)
  271.         return NO;
  272.     
  273.     s = NXOpenMemory (NULL, 0, NX_READWRITE);
  274.     if (s) 
  275.     {
  276.         switch ([compressionType selectedCol])
  277.     {
  278.     case LZW_COMPRESSION:
  279.         [tiffImage  writeTIFF:s usingCompression:NX_TIFF_COMPRESSION_LZW];
  280.         break;
  281.     case JPEG_COMPRESSION:
  282.         if ([tiffImage bitsPerSample] < 4)
  283.         {
  284.             NXRunAlertPanel("TIFFandEPS Save Error", 
  285.           "JPEG compression requires 4 or 8 bits per sample for grayscale or RGB",
  286.            NULL, NULL, NULL);
  287.         error = YES;
  288.         break;
  289.         }
  290.         factor = [JPEGvalue floatValue];
  291.         if (factor < 1.0) factor = 1.0;
  292.         if (factor > 255.0) factor = 255.0;
  293.         [tiffImage writeTIFF:s usingCompression:NX_TIFF_COMPRESSION_JPEG
  294.             andFactor: factor];
  295.         break;
  296.     }
  297.     NXFlush (s);
  298.     if (!error)
  299.     {
  300.         if (NXSaveToFile (s, fileName)) 
  301.         {
  302.             error = YES;
  303.             perror (fileName);
  304.         } 
  305.     }
  306.     NXCloseMemory (s, NX_FREEBUFFER);
  307.     }
  308.     else error = YES;
  309.     [tiffImage free];
  310.     return (error ? NO : YES);
  311. }
  312.  
  313. /* -saveEPS: inWindow:
  314.  *    This method saves a specified view to disk with the specified 
  315.  * fileName using the EPS format.  To do this the copyPSCode 
  316.  * method of view is used on the view with the result going to a stream 
  317.  * and then to disk.
  318.  */
  319. - (BOOL)saveEPS: (const char *)fileName inWindow: window
  320. {
  321.     NXRect rect;
  322.     BOOL error = NO;
  323.     NXStream *s;
  324.     
  325.     s = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  326.     if (s)
  327.     {
  328.         [[window contentView] getFrame:&rect];
  329.         [[window contentView] copyPSCodeInside:&rect to:s]; 
  330.         NXFlush(s);   
  331.         if (NXSaveToFile (s, fileName)) 
  332.         { 
  333.         error = YES;
  334.         perror (fileName);
  335.         } 
  336.         NXCloseMemory(s, NX_FREEBUFFER);
  337.     }
  338.     else error = YES;
  339.     return (error? NO : YES);
  340. }
  341.  
  342. @end
  343.