/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) Copyright (c) 2004 Dmitry Baryshev 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 #include #include #include #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"