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