[wx-dev] Support for SGI RGB file format

Tonda Míšek miseka at naxo.net
Mon Jul 7 12:33:37 PDT 2008


Hello,
we need to read SGI RGB files so I implemented appropriate wxImageHandler.
I used source code from 
http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/ and 
wxPNMHandler as template.
The support is not fully complete, only RGB, RGBA, G and GA with one 
byte per color formats are supported, SaveFile is not implemented.
The original autor Paul Bourke agrees with publication under wxWidgets 
licence so you can use it in mainstream.

Have a nice day,
Antonín Míšek

/////////////////////////////////////////////////////////////////////////////
// Name:        imagrgb.cpp
// Purpose:     wxImage RGB handler
// Author:      Paul Bourke & Antonin Misek
// RCS-ID:      
// Copyright:   (c) 
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

//#if wxUSE_IMAGE && wxUSE_RGB

#include "imagrgb.h"

#ifndef WX_PRECOMP
    #include "wx/intl.h"
    #include "wx/log.h"
#endif

#include "wx/txtstrm.h"

//-----------------------------------------------------------------------------
// wxRGBHandler
//-----------------------------------------------------------------------------

//IMPLEMENT_DYNAMIC_CLASS(wxRGBHandler,wxImageHandler)

//#if wxUSE_STREAMS

void wxRGBHandler::ConvertShort(unsigned short *array, long length)
{
	unsigned b1, b2;
	unsigned char *ptr;

	ptr = (unsigned char *)array;
	while (length--) {
		b1 = *ptr++;
		b2 = *ptr++;
		*array++ = (b1 << 8) | (b2);
	}
}

void wxRGBHandler::ConvertLong(unsigned *array, long length)
{
	unsigned b1, b2, b3, b4;
	unsigned char *ptr;

	ptr = (unsigned char *)array;
	while (length--) {
		b1 = *ptr++;
		b2 = *ptr++;
		b3 = *ptr++;
		b4 = *ptr++;
		*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
	}
}

ImageRec *wxRGBHandler::ImageOpen(wxBufferedInputStream &buf_stream)
{
	union {
		int testWord;
		char testByte[4];
	} endianTest;
	ImageRec *img;
	int swapFlag;
	int x;

	endianTest.testWord = 1;
	if (endianTest.testByte[0] == 1) {
		swapFlag = 1;
	} else {
		swapFlag = 0;
	}

	// Read the RGB header
	img = (ImageRec *)malloc(sizeof(ImageRec));
	if (img == NULL) {
		wxLogError(_("RGB: Out of memory."));
		return NULL;
	}
	buf_stream.Read(img, 12);
	if (swapFlag) {
		ConvertShort(&img->imagic, 6);
	}
	img->tmp = (unsigned char *)malloc(img->xsize*256);
	img->tmpR = (unsigned char *)malloc(img->xsize*256);
	img->tmpG = (unsigned char *)malloc(img->xsize*256);
	img->tmpB = (unsigned char *)malloc(img->xsize*256);
	if (img->tmp == NULL || img->tmpR == NULL || img->tmpG == NULL || img->tmpB == NULL) {
		wxLogError(_("RGB: Out of memory."));
		return NULL;
	}

	if ((img->type & 0xFF00) == 0x0100) {
		x = img->ysize * img->zsize * sizeof(unsigned);
		img->rowStart = (unsigned *)malloc(x);
		img->rowSize = (int *)malloc(x);
		if (img->rowStart == NULL || img->rowSize == NULL) {
			wxLogError(_("RGB: Out of memory."));
			return NULL;
		}
		img->rleEnd = 512 + (2 * x);
		buf_stream.SeekI(512);
		buf_stream.Read(img->rowStart, x);
		buf_stream.Read(img->rowSize, x);
		if (swapFlag) {
			ConvertLong(img->rowStart, x/(int)sizeof(unsigned));
			ConvertLong((unsigned *)img->rowSize, x/(int)sizeof(int));
		}
	} else {
		img->rowStart = NULL;
		img->rowSize = NULL;
	}
	return img;
}

void wxRGBHandler::ImageClose(ImageRec *img) 
{
	free(img->tmp);
	free(img->tmpR);
	free(img->tmpG);
	free(img->tmpB);
	free(img->rowSize);
	free(img->rowStart);
	free(img);
}

void wxRGBHandler::ImageGetRow(wxBufferedInputStream &buf_stream, ImageRec *img, unsigned char *buf, int y, int z) 
{
	unsigned char *iPtr, *oPtr, pixel;
	int count;

	if ((img->type & 0xFF00) == 0x0100) {
		buf_stream.SeekI((long)img->rowStart[y+z*img->ysize]);
		buf_stream.Read(img->tmp, (unsigned int)img->rowSize[y+z*img->ysize]);

		iPtr = img->tmp;
		oPtr = buf;
		for (;;) {
			pixel = *iPtr++;
			count = (int)(pixel & 0x7F);
			if (!count) {
				return;
			}
			if (pixel & 0x80) {
				while (count--) {
					*oPtr++ = *iPtr++;
				}
			} else {
				pixel = *iPtr++;
				while (count--) {
					*oPtr++ = pixel;
				}
			}
		}
	} else {
		buf_stream.SeekI(512+(y*img->xsize)+(z*img->xsize*img->ysize));
		buf_stream.Read(buf, img->xsize);
	}
}

bool wxRGBHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
{
	image->Destroy();
	wxBufferedInputStream buf_stream(stream);

	unsigned char *rbuf, *gbuf, *bbuf, *abuf;
	ImageRec *img;
	int y;

	img = ImageOpen(buf_stream);

	if(!img)
		return false;
	image->Create( img->xsize, img->ysize );
	if (((img->zsize>=4)||(img->zsize==2)) && (!image->HasAlpha()))
		image->InitAlpha();
	rbuf = (unsigned char *)malloc(img->xsize*sizeof(unsigned char));
	gbuf = (unsigned char *)malloc(img->xsize*sizeof(unsigned char));
	bbuf = (unsigned char *)malloc(img->xsize*sizeof(unsigned char));
	abuf = (unsigned char *)malloc(img->xsize*sizeof(unsigned char));
	if(!rbuf || !gbuf || !bbuf)
		return false;
	for (y=0; y<img->ysize; y++) {
		if (img->zsize>=4) {
			ImageGetRow(buf_stream, img,rbuf,y,0);
			ImageGetRow(buf_stream, img,gbuf,y,1);
			ImageGetRow(buf_stream, img,bbuf,y,2);
			ImageGetRow(buf_stream, img,abuf,y,3);
			for (int x=0; x<img->xsize; x++)
			{
				image->SetRGB(x, y, rbuf[x], gbuf[x], bbuf[x]);
				image->SetAlpha(x, y, abuf[x]);
			}
		} else if(img->zsize==3) {
			ImageGetRow(buf_stream, img,rbuf,y,0);
			ImageGetRow(buf_stream, img,gbuf,y,1);
			ImageGetRow(buf_stream, img,bbuf,y,2);
			for (int x=0; x<img->xsize; x++)
			{
				image->SetRGB(x, y, rbuf[x], gbuf[x], bbuf[x]);
			}
		} else if(img->zsize==2) {
			ImageGetRow(buf_stream, img,rbuf,y,0);
			ImageGetRow(buf_stream, img,abuf,y,1);
			for (int x=0; x<img->xsize; x++)
			{
				image->SetRGB(x, y, rbuf[x], rbuf[x], rbuf[x]);
				image->SetAlpha(x, y, abuf[x]);
			}
		} else {
			ImageGetRow(buf_stream, img,rbuf,y,0);
			for (int x=0; x<img->xsize; x++)
			{
				image->SetRGB(x, y, rbuf[x], rbuf[x], rbuf[x]);
			}
		}
	}
	ImageClose(img);
	free(rbuf);
	free(gbuf);
	free(bbuf);
	free(abuf);

	return true;
}

bool wxRGBHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool WXUNUSED(verbose) )
{
	return false;
/*    wxTextOutputStream text_stream(stream);

    //text_stream << "P6" << endl
    //<< image->GetWidth() << " " << image->GetHeight() << endl
    //<< "255" << endl;
    text_stream << wxT("P6\n") << image->GetWidth() << wxT(" ") << image->GetHeight() << wxT("\n255\n");
    stream.Write(image->GetData(),3*image->GetWidth()*image->GetHeight());

    return stream.IsOk();*/
}

bool wxRGBHandler::DoCanRead( wxInputStream& stream )
{
    if ( (stream.GetC() == 1) && (stream.GetC() == 218))
		return true;
    return false;
}

//#endif // wxUSE_STREAMS

//#endif // wxUSE_IMAGE && wxUSE_RGB

------------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////////////
// Name:        imagrgb.h
// Purpose:     wxImage RGB handler
// Author:      Paul Bourke & Antonin Misek
// RCS-ID:      
// Copyright:   (c) 
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#ifndef _WX_IMAGRGB_H_
#define _WX_IMAGRGB_H_

#include "wx/image.h"

typedef struct _ImageRec {
		unsigned short imagic;
		unsigned short type;
		unsigned short dim;
		unsigned short xsize, ysize, zsize;
		unsigned int min, max;
		unsigned int wasteBytes;
		char name[80];
		unsigned long colorMap;
		FILE *file;
		unsigned char *tmp, *tmpR, *tmpG, *tmpB;
		unsigned long rleEnd;
		unsigned int *rowStart;
		int *rowSize;
	} ImageRec;
//-----------------------------------------------------------------------------
// wxRGBHandler
//-----------------------------------------------------------------------------

//#if wxUSE_RGB
class WXDLLEXPORT wxRGBHandler : public wxImageHandler
{
public:
    inline wxRGBHandler()
    {
        m_name = wxT("RGB file");
        m_extension = wxT("rgb");
        m_type = wxBITMAP_TYPE_ANY;//wxBITMAP_TYPE_RGB;
        m_mime = wxT("image/rgb");
    }

#if wxUSE_STREAMS
    virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
    virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
protected:
    virtual bool DoCanRead( wxInputStream& stream );
#endif

private:
//	DECLARE_DYNAMIC_CLASS(wxRGBHandler)

	void ConvertShort(unsigned short *array, long length);
	void ConvertLong(unsigned *array, long length);
	ImageRec *ImageOpen(wxBufferedInputStream &buf_stream);
	void ImageClose(ImageRec *img);
	void ImageGetRow(wxBufferedInputStream &buf_stream, ImageRec *img, unsigned char *buf, int y, int z);
};
//#endif


#endif
  // _WX_IMAGRGB_H_




More information about the wx-dev mailing list