/*
        File name: Jpeg.m

        Written by Georges CHAN

        Purpose: demonstrate how to use the JpegDecode class
                 with NXBitmapImageRep/NXImage as receiver.
                 Since the purpose of this program is to show
                 how to use the JpegDecode class therefore, users
                 may found that some of the techniques used
                 here may not be the most efficient ones.

        Example showing on how to use the JpegDecode class is mainly
        in the demo method.

        Copyright, All right reserved.

        Feel free to use or distribute this application.

        Date: September 92.

        Note: The author disclaims all warranties with regard to this
              software, including all implied warranties or merchantability,
              in no event shall the author be liable for any special,
              indirect or consequential damages or any damages whatsoever
              resulting from loss of use, data or profits, whether in an
              action of contract, negligence or other tortuous action,
              arising out of or in connection with the use of this software.

*/


/*
    The DEMOBITMAP definition tells the compiler to compile
    codes for demonstration with NXBitmapImageRep as a recipient
    of the images in the JPEG file.
    If you want to run the demo with NXImage as recipient then
    simply comment the following def line
*/
#define DEMOBITMAP 1


/* Generated by Interface Builder */

#import "JpegDecode.h"               // lib for getting JPEG files
#import "Jpeg.h"                     // header file of example prog

#import <appkit/NXBitmapImageRep.h> // lib for bitmaps
#import <appkit/NXImage.h>          // lib for images
#import <string.h>                  // lib for string manipulations
#import <libc.h>                    // lib for unix command, e.g. getwd()
#import <appkit/Window.h>           // lib for windows
#import <appkit/OpenPanel.h>        // lib for open panel
#import <appkit/SavePanel.h>        // lib for save panel
#import <streams/streams.h>         // lib for streams output
#import <appkit/Application.h>      // lib for application
#import <appkit/tiff.h>             // lib for tiff constant, e.g. NX_TIFF_COMPRESSION_LZW
#import <appkit/View.h>             // lib for view
#import <dpsclient/wraps.h>         // lib for displaying PS command


@implementation Jpeg

/*
 *
 * demo method demonstrate how to use the JpegDecode class, i.e.
 * how to load a series of bitmaps which are the decompressed
 * images obtained from a specified JPEG file.
 *
*/
- demo:(char *) filename
{
    id view = nil,                  // view in a window to display images of a JPEG file
       jpeg;                        // JPEG object currently being read
    NXSize windowSize;              // minimum size of the display window
    NXRect bounds;                  // bounds of the displayed window

#ifdef DEMOBITMAP
    jpeg = [[JpegDecode alloc] initFromFile :filename
                                     bitMap :&picture
                                       size :&windowSize
                                    mustSee :YES];
#else
    NXPoint place = {0., 0.};        // hold position to composite picture in demo window

    jpeg = [[JpegDecode alloc] initFromFile :filename
                                      image :&picture
                                       size :&windowSize
                                    mustSee :YES];
#endif

    if (jpeg == nil) // error in reading or decoding JPEG file
       {
         if (!NXRunAlertPanel("WARNING",
                             "ERROR OCURRED: do you still want to see it?",
                             "YES",
                             "NO",
                             NULL))
            return self; // return to editor without doing anything
       }

    // adjust origin of the display window so that the window will be visible
    if (winX + windowSize.width >= screamSize.width)
       winX = 100;

    if (winY + windowSize.height >= screamSize.height)
       winY = 150;

       NXSetRect(&bounds, winX, winY,windowSize.width,windowSize.height);

    // allocate the display window
    win = [Window newContent: &bounds
                       style: NX_TITLEDSTYLE
                     backing: NX_BUFFERED
                  buttonMask: NX_CLOSEBUTTONMASK
                       defer: NO];

    view = [win contentView];

    [win setTitle: filename];   // put file name as title of window

    [win display];

    [view lockFocus];

    // clears the demo window
    [view getBounds: &bounds];
    PSsetgray(NX_BLACK);
    NXRectFill(&bounds);
    [view display];

    // display picture

#ifdef DEMOBITMAP
          [picture draw];
          NXPing();    // flush display buffer
#else
          [picture composite:NX_SOVER toPoint: &place];
          NXPing();    // flush display buffer
          sleep(1);    // composite is too fast! slow it down
#endif
    [view display];

    [view unlockFocus];

    [win orderFront:nil];       // move demo window up to front of screen

    [picture free];             // recycle the memory allocated for picture

    // adjust origin position so that next time, pictures won't totally overlap
    winX += 50;
    winY += 50;

    return self;
}

/*
 *
 * init method will initialize the window. Initialization is
 * achieved by overriding the superclass's initFrame method
 *
*/
- init
{
    [super init];             // run superclass init method from class object

    getwd(home);         // get current working directory

    // first window is stuck at (100,200)
    winX = 100;
    winY = 150;

    // get limit of screen size
    [NXApp getScreenSize: &screamSize];
    screamSize.width -= 100;
    screamSize.height -= 100;

    return self;
}

/*
 *
 * method for getting the name of the input data file through the use of the open panel
 *
*/
- getlfname:(char *) fname :(int *) goon
{
    char **files,
         *typo[] = {"jpg", "JPG", NULL};  // get only files with "map" extension
    id openwin = [OpenPanel new];

    [openwin allowMultipleFiles:YES];
    *goon = 1;
    if (![openwin runModalForDirectory:home file:NULL types:typo])
       { // cancel action selected
         *goon = 0;
         return self;
       }

    *goon = 1;                    // yes! user selected an input file
    files = (char **) [openwin filenames];

    strcpy(home, [openwin directory]);
    strcpy(fname, files[0]);

    return self;
}


/*
 *
 * method for performing a retrievement of a data file for mapping
 *
*/
- load:sender
{
    char fname[FNAMELEN],      // hold name of the input file
         full[MAXLEN];         // hold full path name + file name
    int goon;                  // flag for continue loading action

    [self getlfname:fname :&goon];    // get the name of the input file
    if (goon && strlen(fname))
       { // have selected a file
         strcpy(full,home);    // find the full path to the selected file
         strcat(full,"/");
         strcat(full,fname);   // stick the name of the file at the end
         [self demo: full];
       }

    return self;

}


/*
 *
 * save method will save the content of a window to
 * a file by using TIFF format.
 *
*/
- save:sender
{
    NXRect rect;          // hold size of screen rectangle
    id bitmap,            // hold bitmap of screen
       view;              // view to save
    char fname[MAXLEN];   // hold name of the output file
    SavePanel *saveWin = [SavePanel new];   // open save panel

    if (![NXApp keyWindow])
       {
         fprintf(stderr, "You must select or have a JPEG image window!!!\n");
         return self;
       }

    [saveWin setRequiredFileType: "tiff"];  // add tiff extension to file name
    if (![saveWin runModalForDirectory: home file:NULL])
       return self;     // nothing selected
    strcpy(fname, [saveWin filename]); // stick the name of the file

    view = [[NXApp keyWindow] contentView];
    [view lockFocus];
    [view getBounds: &rect];  // get size of the map
    bitmap = [[NXBitmapImageRep alloc] initData:NULL fromRect:&rect]; // get bitmap 
    [view unlockFocus];

     if (bitmap)
        { // save bitmap as TIFF file in /tmp directory
          NXStream *s = NXOpenMemory(NULL, 0, NX_READWRITE);
          if (s)
             { // save bitmap screen to tiff file
               [bitmap writeTIFF:s usingCompression: NX_TIFF_COMPRESSION_LZW];
               NXFlush(s);
               if (NXSaveToFile (s, fname))
                  fprintf(stderr, "Cannot save to %s\n", fname);
               NXCloseMemory (s, NX_FREEBUFFER);
             }
          [bitmap free];
        }

    return self;
}

@end
