You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
362 lines
7.4 KiB
362 lines
7.4 KiB
/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net)
|
|
|
|
Copyright (c) 2004 Dmitry Baryshev <ksquirrel@tut.by>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation;
|
|
either version 2 of the License, or (at your option) any later
|
|
version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
as32 with this library; see the file COPYING. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ksquirrel-libs/fmt_types.h"
|
|
#include "ksquirrel-libs/fileio.h"
|
|
#include "ksquirrel-libs/error.h"
|
|
#include "ksquirrel-libs/fmt_utils.h"
|
|
|
|
#include "fmt_codec_ras_defs.h"
|
|
#include "fmt_codec_ras.h"
|
|
|
|
#include "../xpm/codec_ras.xpm"
|
|
|
|
/*
|
|
*
|
|
* The Sun Raster image file format is the native bitmap format of the Sun
|
|
* Microsystems UNIX platforms using the SunOS operating system. This format is
|
|
* capable of storing black-and-white, gray-scale, and color bitmapped data of any
|
|
* pixel depth. The use of color maps and a simple Run-Length data compression
|
|
* are also supported. Typically, most images found on a SunOS system are Sun
|
|
* Raster images, and this format is supported by most UNIX imaging applications.
|
|
*
|
|
*/
|
|
|
|
bool fmt_readdata(ifstreamK &, u8 *, u32, bool);
|
|
|
|
fmt_codec::fmt_codec() : fmt_codec_base()
|
|
{}
|
|
|
|
fmt_codec::~fmt_codec()
|
|
{}
|
|
|
|
void fmt_codec::options(codec_options *o)
|
|
{
|
|
o->version = "0.6.3";
|
|
o->name = "SUN Raster";
|
|
o->filter = "*.ras ";
|
|
o->config = "";
|
|
o->mime = "\x0059\x00A6\x006A\x0095";
|
|
o->mimetype = "image/x-ras";
|
|
o->pixmap = codec_ras;
|
|
o->readable = true;
|
|
o->canbemultiple = false;
|
|
o->writestatic = false;
|
|
o->writeanimated = false;
|
|
o->needtempfile = false;
|
|
}
|
|
|
|
s32 fmt_codec::read_init(const std::string &file)
|
|
{
|
|
frs.open(file.c_str(), ios::binary | ios::in);
|
|
|
|
if(!frs.good())
|
|
return SQE_R_NOFILE;
|
|
|
|
currentImage = -1;
|
|
rle = false;
|
|
isRGB = false;
|
|
buf = NULL;
|
|
|
|
finfo.animated = false;
|
|
|
|
return SQE_OK;
|
|
}
|
|
|
|
s32 fmt_codec::read_next()
|
|
{
|
|
currentImage++;
|
|
|
|
if(currentImage)
|
|
return SQE_NOTOK;
|
|
|
|
fmt_image image;
|
|
|
|
if(!frs.be_getlong(&rfh.ras_magic)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_width)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_height)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_depth)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_length)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_type)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_maptype)) return SQE_R_BADFILE;
|
|
if(!frs.be_getlong(&rfh.ras_maplength)) return SQE_R_BADFILE;
|
|
|
|
if(rfh.ras_magic != RAS_MAGIC) return SQE_R_BADFILE;
|
|
|
|
if(rfh.ras_type != RAS_OLD && rfh.ras_type != RAS_STANDARD && rfh.ras_type != RAS_BYTE_ENCODED && rfh.ras_type != RAS_RGB &&
|
|
rfh.ras_type != RAS_TIFF && rfh.ras_type != RAS_IFF && rfh.ras_type != RAS_EXPERIMENTAL)
|
|
return SQE_R_BADFILE;
|
|
else if(rfh.ras_type == RAS_EXPERIMENTAL)
|
|
return SQE_R_NOTSUPPORTED;
|
|
|
|
image.w = rfh.ras_width;
|
|
image.h = rfh.ras_height;
|
|
image.bpp = rfh.ras_depth;
|
|
|
|
switch(rfh.ras_maptype)
|
|
{
|
|
case RMT_NONE :
|
|
{
|
|
if (rfh.ras_depth < 24)
|
|
{
|
|
s32 numcolors = 1 << rfh.ras_depth, i;
|
|
|
|
for (i = 0; i < numcolors; i++)
|
|
{
|
|
pal[i].r = (255 * i) / (numcolors - 1);
|
|
pal[i].g = (255 * i) / (numcolors - 1);
|
|
pal[i].b = (255 * i) / (numcolors - 1);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case RMT_EQUAL_RGB:
|
|
{
|
|
s8 *g, *b;
|
|
|
|
s32 numcolors = 1 << rfh.ras_depth;
|
|
|
|
s8 r[3 * numcolors];
|
|
|
|
g = r + numcolors;
|
|
b = g + numcolors;
|
|
|
|
if(!frs.readK(r, 3 * numcolors)) return SQE_R_BADFILE;
|
|
|
|
for(s32 i = 0; i < numcolors; i++)
|
|
{
|
|
pal[i].r = r[i];
|
|
pal[i].g = g[i];
|
|
pal[i].b = b[i];
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RMT_RAW:
|
|
{
|
|
s8 colormap[rfh.ras_maplength];
|
|
|
|
if(!frs.readK(colormap, rfh.ras_maplength)) return SQE_R_BADFILE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch(rfh.ras_type)
|
|
{
|
|
case RAS_OLD:
|
|
case RAS_STANDARD:
|
|
case RAS_TIFF:
|
|
case RAS_IFF:
|
|
break;
|
|
|
|
case RAS_BYTE_ENCODED:
|
|
rle = true;
|
|
break;
|
|
|
|
case RAS_RGB:
|
|
isRGB = true;
|
|
break;
|
|
}
|
|
|
|
if(rfh.ras_depth == 1)
|
|
linelength = (short)((rfh.ras_width / 8) + (rfh.ras_width % 8 ? 1 : 0));
|
|
else
|
|
linelength = (short)rfh.ras_width;
|
|
|
|
fill = (linelength % 2) ? 1 : 0;
|
|
|
|
buf = new u8 [rfh.ras_width * sizeof(RGB)];
|
|
|
|
if(!buf)
|
|
return SQE_R_NOMEMORY;
|
|
|
|
image.compression = ((isRGB) ? "-":"RLE");
|
|
image.colorspace = "RGB";
|
|
|
|
finfo.image.push_back(image);
|
|
|
|
return SQE_OK;
|
|
}
|
|
|
|
s32 fmt_codec::read_next_pass()
|
|
{
|
|
return SQE_OK;
|
|
}
|
|
|
|
s32 fmt_codec::read_scanline(RGBA *scan)
|
|
{
|
|
u32 i;
|
|
fmt_image *im = image(currentImage);
|
|
fmt_utils::fillAlpha(scan, im->w);
|
|
|
|
switch(im->bpp)
|
|
{
|
|
case 1:
|
|
break;
|
|
|
|
case 8:
|
|
if(!fmt_readdata(frs, buf, linelength, rle))
|
|
return SQE_R_BADFILE;
|
|
|
|
for(i = 0;i < rfh.ras_width;i++)
|
|
memcpy(scan+i, &pal[i], sizeof(RGB));
|
|
|
|
if(fill)
|
|
{
|
|
if(!fmt_readdata(frs, &fillchar, fill, rle))
|
|
return SQE_R_BADFILE;
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
{
|
|
u8 *b = buf;
|
|
|
|
if(!fmt_readdata(frs, buf, rfh.ras_width * 3, rle))
|
|
return SQE_R_BADFILE;
|
|
|
|
if(isRGB)
|
|
for (i = 0; i < rfh.ras_width; i++)
|
|
{
|
|
scan[i].r = *b;
|
|
scan[i].g = *(b+1);
|
|
scan[i].b = *(b+2);
|
|
b += 3;
|
|
}
|
|
else
|
|
for (i = 0; i < rfh.ras_width; i++)
|
|
{
|
|
scan[i].r = *(b + 2);
|
|
scan[i].g = *(b + 1);
|
|
scan[i].b = *b;
|
|
b += 3;
|
|
}
|
|
|
|
if(fill)
|
|
{
|
|
if(!fmt_readdata(frs, &fillchar, fill, rle))
|
|
return SQE_R_BADFILE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 32:
|
|
{
|
|
u8 *b = buf;
|
|
|
|
if(!fmt_readdata(frs, buf, rfh.ras_width * 4, rle))
|
|
return SQE_R_BADFILE;
|
|
|
|
if(isRGB)
|
|
for (i = 0; i < rfh.ras_width; i++)
|
|
{
|
|
scan[i].a = *b;
|
|
scan[i].r = *(b+1);
|
|
scan[i].g = *(b+2);
|
|
scan[i].b = *(b+3);
|
|
b += 4;
|
|
}
|
|
else
|
|
for (i = 0; i < rfh.ras_width; i++)
|
|
{
|
|
scan[i].r = *(b + 3);
|
|
scan[i].g = *(b + 2);
|
|
scan[i].b = *(b + 1);
|
|
scan[i].a = *b;
|
|
b += 4;
|
|
}
|
|
|
|
if(fill)
|
|
{
|
|
if(!fmt_readdata(frs, &fillchar, fill, rle))
|
|
return SQE_R_BADFILE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
return SQE_OK;
|
|
}
|
|
|
|
void fmt_codec::read_close()
|
|
{
|
|
frs.close();
|
|
|
|
delete [] buf;
|
|
buf = NULL;
|
|
|
|
finfo.meta.clear();
|
|
finfo.image.clear();
|
|
}
|
|
|
|
bool fmt_readdata(ifstreamK &ff, u8 *_buf, u32 length, bool rle)
|
|
{
|
|
u8 repchar, remaining = 0;
|
|
|
|
if(rle)
|
|
{
|
|
while(length--)
|
|
{
|
|
if (remaining)
|
|
{
|
|
remaining--;
|
|
*(_buf++)= repchar;
|
|
}
|
|
else
|
|
{
|
|
if(!ff.readK(&repchar, 1)) return false;
|
|
|
|
if(repchar == RESC)
|
|
{
|
|
if(!ff.readK(&remaining, 1)) return false;
|
|
|
|
if (remaining == 0)
|
|
*(_buf++) = RESC;
|
|
else
|
|
{
|
|
if(!ff.readK(&repchar, 1)) return false;
|
|
*(_buf++) = repchar;
|
|
}
|
|
}
|
|
else
|
|
*(_buf++) = repchar;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!ff.readK(_buf, length)) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#include "fmt_codec_cd_func.h"
|