/*$Copyright:
 * Copyright (C) 1992.5.22. Recruit Co.,Ltd. 
 * Institute for Supercomputing Research
 * All rights reserved.
 * NewsBase  by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue
 *
 * You may freely copy, distribute and reuse the code in this program under 
 * following conditions.
 * - to include this notice in the source code, if it is to be distributed 
 *   with source code.
 * - to add the file named "COPYING" within the code, which shall include 
 *   GNU GENERAL PUBLIC LICENSE(*).
 * - to display an acknowledgement in binary code as follows: "This product
 *   includes software developed by Recruit Co.,Ltd., ISR."
 * - to display a notice which shall state that the users may freely copy,
 *   distribute and reuse the code in this program under GNU GENERAL PUBLIC
 *   LICENSE(*)
 * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*)
 *
 *   (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
$*/

// IEpsD is the media class for EPS.  The file extension, RTF control word
// and pasteboard type are "eps", "MMeps" and NXPostScriptPboardtype,
// respectively.

#import "IGifD.h"
#import <appkit/NXImage.h>
#import <appkit/Pasteboard.h>
#import <libc.h>
#import "errdebug.h"

@implementation IGifD

static NXAtom rtfControlWord;
static NXAtom fileExtension;
static NXAtom pasteboardType;
static NXImage *icon;

+ initialize
{
    rtfControlWord = NXUniqueStringNoCopy("MMgif");
    fileExtension = NXUniqueStringNoCopy("gif");
    pasteboardType = NXUniqueStringNoCopy("GIF Format");
    [IMediaD getFileIconFor:(Class)self];
    return(self);
}

+ (NXAtom)rtfControlWord
{
    return(rtfControlWord);
}

+ (NXAtom)fileExtension;
{
    return(fileExtension);
}

+ (NXAtom)pasteboardType
{
    return(pasteboardType);
}

+ setIcon:(NXImage *)theIcon
{
    icon = theIcon;
    return(self);
}

+ (NXImage *)icon
{
    return(icon);
}

- initWithKey:(char *)pathName
{
    [super initWithKey:pathName];
    image = nil;
    twoBitData = NULL;
    return(self);
}

- (NXImage *)image 
{
    return(image);
}

- (BOOL)readFromStream:(NXStream *)inStream
{
    char tmpGifFile[64];
     struct timeval timeValue;
     struct timezone timeZone;
    char *buffer;
    int len, maxLen;
    char *data;
    int width, height, maxValue;
    NXSize imageSize;
    char command[256];

    [super readFromStream:inStream];
    sprintf(tmpGifFile, "/tmp/NewsBaseTmpGifFile%d.gif", getpid());
    if (NXSaveToFile(stream, tmpGifFile) != 0) {
        return(NO);
    }
    gettimeofday(&timeValue, &timeZone);
    sprintf(tmpPpmFile, "/tmp/NewsBaseTmpPpmFile%d-%d.ppm", getpid(),
        timeValue.tv_sec);
    sprintf(command, "giftoppm %.120s %.120s", tmpGifFile, tmpPpmFile);
    system(command);
    unlink(tmpGifFile);
    if ((ppmStream = NXMapFile(tmpPpmFile, NX_READONLY)) == NULL) {
        return(NO);
    }
    if (NXScanf(ppmStream, "P6 %d %d %d", &width, &height, &maxValue) != 3) {
        NXCloseMemory(ppmStream, NX_FREEBUFFER);
        unlink(tmpPpmFile);
        return(NO);
    }
    NXGetMemoryBuffer(ppmStream, &buffer, &len, &maxLen);
    data = buffer + NXTell(ppmStream) + 1;
    bitmap = [NXBitmapImageRep alloc];
    [bitmap initData:(unsigned char *)data pixelsWide:width pixelsHigh:height
        bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO
        colorSpace:NX_RGBColorSpace bytesPerRow:3 * width bitsPerPixel:24];
    imageSize.width = width;
    imageSize.height = height;
    image = [[NXImage allocFromZone:[self zone]] initSize:&imageSize];
    [image useCacheWithDepth:NX_TwentyFourBitRGBDepth];
    [image lockFocus];
    [bitmap draw];
    [image unlockFocus];
    [image setDataRetained:YES];
    return(YES);
}

- free
{
    if (image != nil) {
        [image free];
    }
    if (twoBitData != NULL) {
        NXZoneFree([self zone], twoBitData);
    }
    if (ppmStream != NULL) {
        NXCloseMemory(ppmStream, NX_FREEBUFFER);
        unlink(tmpPpmFile);
    }
    return([super free]);
}

- addTwoBitGrayRepresentation
{
    NXRect		rect;
    NXImage		*convertedImage;
    NXBitmapImageRep	*convertedBitmap;
    NXBitmapImageRep	*twoBitBitmap;
    unsigned char	*sptr, *tptr;
    int			x, y;

    [image getSize:&rect.size];
    rect.origin.x = rect.origin.y = 0.0;
    rect.size.width = rect.size.width / 4 * 4;
    convertedImage = [[NXImage alloc] initSize:&rect.size];
    [convertedImage useCacheWithDepth:NX_EightBitGrayDepth];
    [convertedImage lockFocusOn:[convertedImage lastRepresentation]];
    [[image lastRepresentation] draw];
    convertedBitmap = [[NXBitmapImageRep alloc] initData:NULL fromRect:&rect];
    [convertedImage unlockFocus];
    [convertedImage free];
    convertedImage = nil;
    if ([convertedBitmap bitsPerPixel] != 8) {
        [convertedBitmap free];
        convertedBitmap = nil;
        twoBitData = NULL;
        return self;
    }
    twoBitData = NXZoneMalloc([self zone],
        (int)rect.size.width * (int)rect.size.height / 4);
    sptr = [convertedBitmap data], tptr = twoBitData;
    for (y = 0; y < rect.size.height; ++y) {
        for (x = 0; x < rect.size.width; x += 4, sptr += 4, tptr += 1) {
            *tptr = ((*(sptr + 0) & 0xc0) >> 0) |
                    ((*(sptr + 1) & 0xc0) >> 2) |
                    ((*(sptr + 2) & 0xc0) >> 4) |
                    ((*(sptr + 3) & 0xc0) >> 6);
        }
    }
    [convertedBitmap free];
    convertedBitmap = nil;
    twoBitBitmap = [[NXBitmapImageRep alloc]
        initData:twoBitData pixelsWide:(int)rect.size.width
        pixelsHigh:(int)rect.size.height bitsPerSample:2
        samplesPerPixel:1 hasAlpha:NO isPlanar:YES
        colorSpace:NX_OneIsWhiteColorSpace
        bytesPerRow:((int)rect.size.width * 2 + 7) / 8 bitsPerPixel:2];
    [image useRepresentation:twoBitBitmap];
    return(self);
}

@end
