1// 2// PXGifExporter.m 3// Pixen-XCode 4// 5// Created by Andy Matuschak on Fri Jul 16 2004. 6// Copyright (c) 2004 Open Sword Group. All rights reserved. 7// 8 9#import "PXGifExporter.h" 10#import "gif_lib.h" 11 12@implementation PXGifExporter 13 14+ gifDataForImage:anImage 15{ 16 id image = [[[NSImage alloc] initWithData:[anImage TIFFRepresentation]] autorelease]; 17 NSSize size = [image size]; 18 [image lockFocus]; 19 20 // first we find a valid transparent color 21 id transparentColor = [NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:1]; 22 BOOL found = YES; 23 while (found) // I know this is ugly. It works. 24 { 25 found = NO; 26 int i, j; 27 for (i = 0; i < size.width; i++) 28 { 29 for (j = 0; j < size.height; j++) 30 { 31 id converted = [NSReadPixel(NSMakePoint(i, j)) colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 32 if ((unsigned char)([converted redComponent] * 255) == (unsigned char)([transparentColor redComponent] * 255) && (unsigned char)([converted greenComponent] * 255) == (unsigned char)([transparentColor greenComponent] * 255) && (unsigned char)([converted blueComponent] * 255) == (unsigned char)([transparentColor blueComponent] * 255)) 33 { 34 if ([transparentColor redComponent] < 1) 35 { 36 transparentColor = [NSColor colorWithCalibratedRed:[transparentColor redComponent]+0.1 green:[transparentColor greenComponent] blue:[transparentColor blueComponent] alpha:1]; 37 } 38 else if ([transparentColor greenComponent] < 1) 39 { 40 transparentColor = [NSColor colorWithCalibratedRed:[transparentColor redComponent] green:[transparentColor greenComponent]+0.1 blue:[transparentColor blueComponent] alpha:1]; 41 } 42 else if ([transparentColor blueComponent] < 1) 43 { 44 transparentColor = [NSColor colorWithCalibratedRed:[transparentColor redComponent] green:[transparentColor greenComponent] blue:[transparentColor blueComponent]+0.1 alpha:1]; 45 } 46 found = YES; 47 } 48 } 49 } 50 } 51 52 int colorMapSize = 256; 53 GifByteType *redBuffer = malloc(size.width * size.height); 54 GifByteType *greenBuffer = malloc(size.width * size.height); 55 GifByteType *blueBuffer = malloc(size.width * size.height); 56 EGifSetGifVersion("89a"); 57 58 int i, j, count = 0; 59 for (j = size.height - 1; j >= 0; j--) 60 { 61 for (i = 0; i < size.width; i++, count++) 62 { 63 NSColor * color = [NSReadPixel(NSMakePoint(i, j)) colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 64 if ([color alphaComponent] < 0.5) { color = transparentColor; } 65 66 redBuffer[count] = (GifByteType)([color redComponent] * 255); 67 greenBuffer[count] = (GifByteType)([color greenComponent] * 255); 68 blueBuffer[count] = (GifByteType)([color blueComponent] * 255); 69 } 70 } 71 72 ColorMapObject *colorMap = MakeMapObject(colorMapSize, NULL); 73 GifByteType *outputBuffer = malloc(size.width * size.height * sizeof(GifByteType)); 74 QuantizeBuffer(size.width, size.height, &colorMapSize, redBuffer, greenBuffer, blueBuffer, outputBuffer, colorMap->Colors); 75 76 GifFileType *gifFile = EGifOpenFileName("/tmp/dummy.gif", NO); 77 78 //find the index of the transparent color in the color map 79 unsigned transparentIndex = 0, bestDelta = 1000; 80 for (i = 0; i < colorMapSize; i++) 81 { 82 unsigned char transRed = (unsigned char)([transparentColor redComponent] * 255); 83 unsigned char transGreen = (unsigned char)([transparentColor greenComponent] * 255); 84 unsigned char transBlue = (unsigned char)([transparentColor blueComponent] * 255); 85 GifColorType color = colorMap->Colors[i]; 86 if (color.Red == transRed && color.Green == transGreen && color.Blue == transBlue) 87 { 88 transparentIndex = i; 89 } 90 else 91 { 92 unsigned int tempDelta = (color.Red < transRed ? transRed - color.Red : color.Red - transRed) + 93 (color.Green < transGreen ? transGreen - color.Green : color.Green - transGreen) + 94 (color.Blue < transBlue ? transBlue - color.Blue : color.Blue - transBlue); 95 if (tempDelta < bestDelta) 96 { 97 transparentIndex = i; 98 bestDelta = tempDelta; 99 } 100 } 101 } 102 103 EGifPutScreenDesc(gifFile, size.width, size.height, colorMapSize, 0, colorMap); 104 unsigned char extension[4] = { 0 }; 105 extension[0] = 0x01; // byte 1 is a flag; 00000001 turns transparency on. 106 extension[1] = 0x00; // byte 2 is delay time, presumably for animation. 107 extension[2] = 0x00; // byte 3 is continued delay time. 108 extension[3] = transparentIndex; // byte 4 is the index of the transparent color in the palette. 109 EGifPutExtension(gifFile, 0xF9, sizeof(extension), extension); // 0xf9 is the transparency extension magic code 110 EGifPutImageDesc(gifFile, 0, 0, size.width, size.height, 0, NULL); 111 112 GifByteType * position = outputBuffer; 113 for (i = 0; i < size.height; i++) 114 { 115 EGifPutLine(gifFile, position, size.width); 116 position += (int)size.width; 117 } 118 EGifCloseFile(gifFile); 119 120 [image unlockFocus]; 121 id finalData = [NSData dataWithContentsOfFile:@"/tmp/dummy.gif"]; 122 remove("/tmp/dummy.gif"); 123 return finalData; 124} 125 126@end 127