From 0292059f4a16434600564cfa3f0ad2309a508a54 Mon Sep 17 00:00:00 2001 From: tpearson Date: Wed, 24 Feb 2010 17:43:19 +0000 Subject: Added libksquirrel for KDE3 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kernel/kls_fli/fmt_codec_fli.cpp | 449 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100644 kernel/kls_fli/fmt_codec_fli.cpp (limited to 'kernel/kls_fli/fmt_codec_fli.cpp') diff --git a/kernel/kls_fli/fmt_codec_fli.cpp b/kernel/kls_fli/fmt_codec_fli.cpp new file mode 100644 index 0000000..d186d98 --- /dev/null +++ b/kernel/kls_fli/fmt_codec_fli.cpp @@ -0,0 +1,449 @@ +/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net) + + Copyright (c) 2005 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_fli_defs.h" +#include "fmt_codec_fli.h" + +#include "../xpm/codec_fli.xpm" + +/* + * + * The FLI file format (sometimes called Flic) + * is one of the most popular + * animation formats found in the MS-DOS and Windows environments today. FLI is + * used widely in animation programs, computer games, and CAD applications + * requiring 3D manipulation of vector drawings. Flic, in common + * with most animation formats, does not support either audio or video data, but + * instead stores only sequences of still image data. + * + */ + +// maximum number of frames in FLI is 1024 +#define MAX_FRAME 1024 + +fmt_codec::fmt_codec() : fmt_codec_base() +{} + +fmt_codec::~fmt_codec() +{} + +void fmt_codec::options(codec_options *o) +{ + o->version = "0.3.2"; + o->name = "FLI Animation"; + o->filter = "*.fli "; + o->config = ""; + o->mime = ""; + o->mimetype = "video/x-flic"; + o->pixmap = codec_fli; + o->readable = true; + o->canbemultiple = true; + 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; + + if(!frs.readK(&flic, sizeof(FLICHEADER))) + return SQE_R_BADFILE; + + if(flic.FileId != 0xAF11)// && flic.FileId != 0xAF12) + return SQE_R_BADFILE; + + if(flic.Flags != 3) + cerr << "libSQ_read_fli: WARNING: Flags != 3" << endl; + + memset(pal, 0, 768); + + currentImage = -1; + + buf = (u8**)calloc(flic.Height, sizeof(u8*)); + + if(!buf) + return SQE_R_NOMEMORY; + + for(s32 i = 0;i < flic.Height;i++) + { + buf[i] = (u8*)0; + } + + for(s32 i = 0;i < flic.Height;i++) + { + buf[i] = (u8*)calloc(flic.Width, sizeof(u8)); + + if(!buf[i]) + return SQE_R_NOMEMORY; + } + + finfo.animated = false; + + return SQE_OK; +} + +s32 fmt_codec::read_next() +{ + currentImage++; + + if(currentImage == flic.NumberOfFrames || currentImage == MAX_FRAME) + return SQE_NOTOK; + + fmt_image image; + + image.w = flic.Width; + image.h = flic.Height; + image.bpp = 8; + image.delay = (s32)((float)flic.FrameDelay * 14.3); + finfo.animated = (currentImage) ? true : false; + +// prs32f("%dx%d@%d, delay: %d\n", flic.Width, flic.Height, flic.PixelDepth, finfo.image[currentImage].delay); + + CHUNKHEADER chunk; + CHUNKHEADER subchunk; + u16 subchunks; + + fstream::pos_type pos = frs.tellg(); +// prs32f("POS AFTER HEADER: %d\n", pos); + + while(true) + { + if(!skip_flood(frs)) + return SQE_R_BADFILE; + + if(!frs.readK(&chunk, sizeof(CHUNKHEADER))) + return SQE_R_BADFILE; + +// prs32f("Read MAIN chunk: size: %d, type: %X\n", chunk.size, chunk.type); + + if(chunk.type != CHUNK_PREFIX_TYPE && + chunk.type != CHUNK_SCRIPT_CHUNK && + chunk.type != CHUNK_FRAME_TYPE && + chunk.type != CHUNK_SEGMENT_TABLE && + chunk.type != CHUNK_HUFFMAN_TABLE) + return SQE_R_BADFILE; + + if(chunk.type != CHUNK_FRAME_TYPE) + frs.seekg(chunk.size - sizeof(CHUNKHEADER), ios::cur); + else + { + if(!frs.readK(&subchunks, sizeof(u16))) + return SQE_R_BADFILE; +// prs32f("Chunk #%X has %d subchunks\n", chunk.type, subchunks); + frs.seekg(sizeof(u16) * 4, ios::cur); + break; + } + } + +// prs32f("POS MAIN: %d\n", ftell(fptr)); +// fsetpos(fptr, (fpos_t*)&pos); +// fseek(fptr, chunk.size, SEEK_CUR); +// prs32f("POS2 MAIN: %d\n", ftell(fptr)); + + while(subchunks--) + { + pos = frs.tellg(); + + if(!frs.readK(&subchunk, sizeof(CHUNKHEADER))) + return SQE_R_BADFILE; + +// prs32f("*** Subchunk: %d\n", subchunk.type); + + switch(subchunk.type) + { + case CHUNK_COLOR_64: + case CHUNK_COLOR_256: + { +// prs32f("*** Palette64 CHUNK\n"); + u8 skip, count; + u16 packets; + RGB e; + + if(!frs.readK(&packets, sizeof(u16))) + return SQE_R_BADFILE; +// prs32f("COLOR_64 packets: %d\n", packets); + + for(s32 i = 0;i < packets;i++) + { + if(!frs.readK(&skip, 1)) return SQE_R_BADFILE; + if(!frs.readK(&count, 1)) return SQE_R_BADFILE; +// prs32f("COLOR64 skip: %d, count: %d\n", skip, count); + + if(count) + { + for(s32 j = 0;j < count;j++) + { + if(!frs.readK(&e, sizeof(RGB))) return SQE_R_BADFILE; +// prs32f("COLOR_64 PALLETTE CHANGE %d,%d,%d\n", e.r, e.g, e.b); + } + } + else + { +// prs32f("Reading pallette...\n"); + if(!frs.readK(pal, sizeof(RGB) * 256)) return SQE_R_BADFILE; + + u8 *pp = (u8 *)pal; + + if(subchunk.type == CHUNK_COLOR_64) + for(s32 j = 0;j < 768;j++) + pp[j] <<= 2; + +// for(s32 j = 0;j < 256;j++) +// prs32f("COLOR_64 PALLETTE %d,%d,%d\n", pal[j].r, pal[j].g, pal[j].b); +// prs32f("\n"); + } + } + } + break; + + case CHUNK_RLE: + { +// prs32f("*** RLE DATA CHUNK\n"); + u8 value; + s8 c; + s32 count; + + for(s32 j = 0;j < image.h;j++) + { + s32 index = 0; + count = 0; + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + while(count < image.w) + { + if(!frs.readK(&c, 1)) return SQE_R_BADFILE; + + if(c < 0) + { + c = -c; + + for(s32 i = 0;i < c;i++) + { + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + buf[j][index] = value; + index++; + } + + count += c; + } + else + { + if(!frs.readK(&value, 1)) return SQE_R_BADFILE; + + for(s32 i = 0;i < c;i++) + { + buf[j][index] = value; + index++; + } + + count += c; + } + } + } + } + break; + + case CHUNK_DELTA_FLI: + { + u16 starty, totaly, ally, index; + u8 packets, skip, byte; + s8 size; + s32 count; + + if(!frs.readK(&starty, 2)) return SQE_R_BADFILE; + if(!frs.readK(&totaly, 2)) return SQE_R_BADFILE; + + ally = starty + totaly; + +// prs32f("Y: %d, Total: %d\n", starty, totaly); + + for(s32 j = starty;j < ally;j++) + { + count = 0; + index = 0; + + if(!frs.readK(&packets, 1)) return SQE_R_BADFILE; + + while(count < image.w) + { + for(s32 k = 0;k < packets;k++) + { +// prs32f("LINE %d\n", j); + if(!frs.readK(&skip, 1)) return SQE_R_BADFILE; + if(!frs.readK(&size, 1)) return SQE_R_BADFILE; + + index += skip; + +// prs32f("SKIP: %d, SIZE: %d\n", skip, size); + + if(size > 0) + { + if(!frs.readK(buf[j]+index, size)) return SQE_R_BADFILE; + } + else if(size < 0) + { + size = -size; + if(!frs.readK(&byte, 1)) return SQE_R_BADFILE; + memset(buf[j]+index, byte, size); + } + + index += size; + count += size; + } + + break; + } + } + } + break; + + case CHUNK_BLACK: + break; + + case CHUNK_COPY: + { +// prs32f("*** COPY DATA CHUNK\n"); + + for(s32 j = 0;j < image.h;j++) + { + if(!frs.readK(buf[j], image.w)) return SQE_R_BADFILE; + } + } + break; + + default: +// prs32f("*** UNKNOWN CHUNK! SEEKING ANYWAY\n"); + frs.seekg(pos); + frs.seekg(subchunk.size, ios::cur); + } + +// prs32f("POS: %d\n", ftell(fptr)); +// prs32f("POS2: %d\n", ftell(fptr)); + } + + image.compression = "RLE/DELTA_FLI"; + image.colorspace = "Color indexed"; + + finfo.image.push_back(image); + + return SQE_OK; +} + +s32 fmt_codec::read_next_pass() +{ + line = -1; + + return SQE_OK; +} + +s32 fmt_codec::read_scanline(RGBA *scan) +{ + line++; + fmt_image *im = image(currentImage); + fmt_utils::fillAlpha(scan, im->w); + + for(s32 i = 0;i < im->w;i++) + { + memcpy(scan+i, pal+buf[line][i], sizeof(RGB)); + } + + return SQE_OK; +} + +void fmt_codec::read_close() +{ + if(buf) + { + for(s32 i = 0;i < flic.Height;i++) + if(buf[i]) + free(buf[i]); + + free(buf); + } + + frs.close(); + + finfo.meta.clear(); + finfo.image.clear(); +} + +bool find_chunk_type(const u16 type) +{ + static const u16 A[] = + { + CHUNK_PREFIX_TYPE, + CHUNK_SCRIPT_CHUNK, + CHUNK_FRAME_TYPE, + CHUNK_SEGMENT_TABLE, + CHUNK_HUFFMAN_TABLE + }; + + static const s32 S = 5; + + for(s32 i = 0;i < S;i++) + if(type == A[i]) + return true; + + return false; +} + +bool fmt_codec::skip_flood(ifstreamK &s) +{ + u8 _f[4]; + u16 b; + fstream::pos_type _pos; + +// prs32f("SKIP_FLOOD pos: %d\n", ftell(f)); + + if(!s.readK(_f, 4)) return false; + + do + { + _pos = s.tellg(); + if(!s.readK(&b, 2)) return false; +// prs32f("SKIP_FLOOD b: %X\n", b); + s.seekg(-1, ios::cur); + }while(!find_chunk_type(b)); + + _pos -= 4; + + s.seekg(_pos); + + return true; + +// prs32f("SKIP_FLOOD pos2: %d\n", ftell(f)); +} + +#include "fmt_codec_cd_func.h" -- cgit v1.2.1