[Slightly OT] for all you coders out there...

kelvSYC

Chieftain
Joined
Jun 30, 2004
Messages
34
I'm trying to code a BIC editor based on information scattered about the net, but I've hit one of several problems.

Is there a library or something-or-other in Java or Objective-C that I can use to deal with PCX files?
 
Hi. I've created a Cocoa converter that reads a .pcx file into an NSBitmapImageRep. It specifically works with the terrain files, and I haven't tried it with any others. For example, I've made some assumptions about the transparency colors that may not apply generally.

Here's the code:

Code:
- (NSBitmapImageRep*) imageRepFromPCXFile: (NSString*) filePath {
	typedef struct PaletteEntry {
		unsigned char red;
		unsigned char green;
		unsigned char blue;
	} PaletteEntry;
	NSData* pcxData = [NSData dataWithContentsOfFile: filePath];
	const unsigned char* pcxBytes = [pcxData bytes];
	if (pcxBytes[1] != 0x05) { NSLog (@"ERROR: PCX is not version 3"); return nil; }
	// version 3 - check for a palette
	PaletteEntry* palettePtr = (PaletteEntry*) (pcxBytes + [pcxData length]-768);
	if ( *((unsigned char*)palettePtr - 1) != 0x0c) { NSLog (@"ERROR: PCX has no palette"); return nil; }
	// found the palette pointer
	// now get the image dimensions
	unsigned bitsPerPixel = pcxBytes[3];
	if (bitsPerPixel != 8) { NSLog (@"ERROR; Invalid PCX pixel size"); return nil; }
	unsigned numPlanes = pcxBytes[65];
	if (numPlanes != 1) { NSLog (@"ERROR: Invalid PCX number of planes"); return nil; }
	unsigned bytesPerLine = pcxBytes[66] + (pcxBytes[67] << 8);
	unsigned pcxWidth = pcxBytes[8] + (pcxBytes[9] << 8) - pcxBytes[4] + (pcxBytes[5] << 8) +1;
	unsigned pcxHeight = pcxBytes[10] + (pcxBytes[11] << 8) - pcxBytes[6] + (pcxBytes[7] << 8) +1;
	unsigned pcxRowBytes = bytesPerLine * numPlanes;
			
	NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil
		pixelsWide: pcxWidth
		pixelsHigh: pcxHeight
		bitsPerSample: 8 
		samplesPerPixel: 4
		hasAlpha:true
		isPlanar: NO
		colorSpaceName: NSDeviceRGBColorSpace
		bytesPerRow: 0
		bitsPerPixel: 0];

	// populate the pixel map
	const unsigned char* pcxByte = pcxBytes + 128;
	unsigned char* bmpByte = [imageRep bitmapData];
	int y; for (y = 0; y < pcxHeight; y++) {
		// decode a pcx line
		int repeat = 0;
		int inX = pcxRowBytes;
		int outX = pcxWidth;
		while (inX--) {
			unsigned char c;
			if (repeat == 0) { // next byte
				c = *(pcxByte++);
				if (c >= 0xc0) { // start repeating next byte
					repeat = c - 0xc0 - 1;
					c = *(pcxByte++);
				}
			} else
				repeat --;
			if (outX-- > 0) {
				// write out the color elements
				PaletteEntry* color = palettePtr + c;
				if ((color->red == 255 && color->green == 0 && color->blue == 255) ||
					(color->red == 0 && color->green == 255 && color->blue == 0)) {
					// magenta and green are transparent
					*(bmpByte++) = 0;
					*(bmpByte++) = 0;
					*(bmpByte++) = 0;
					*(bmpByte++) = 0;
				} else {
					*(bmpByte++) = color->red;
					*(bmpByte++) = color->green;
					*(bmpByte++) = color->blue;
					*(bmpByte++) = 255;
				}
			}
		}
	}
	return imageRep;
}

HTH, the license is open source - you give me any fixes or improvements you discover, and please keep us informed about your progress ;)
 
Back
Top Bottom