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.
ksquirrel/ksquirrel/sq_imageloader.cpp

262 lines
6.2 KiB

/***************************************************************************
sq_imageloader.cpp - description
-------------------
begin : Tue Sep 20 2005
copyright : (C) 2005 by Baryshev Dmitry
email : ksquirrel.iv@gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <tqfile.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sq_imageloader.h"
#include "sq_libraryhandler.h"
#include <ksquirrel-libs/fileio.h>
#include <ksquirrel-libs/fmt_utils.h>
#include <ksquirrel-libs/fmt_codec_base.h>
#include <ksquirrel-libs/error.h>
SQ_ImageLoader * SQ_ImageLoader::m_instance = 0;
SQ_ImageLoader::SQ_ImageLoader(TQObject *parent) : TQObject(parent), m_errors(0)
{
m_instance = this;
m_image = 0;
dumbscan = 0;
finfo = new fmt_info;
}
SQ_ImageLoader::~SQ_ImageLoader()
{
delete finfo;
if(dumbscan) free(dumbscan);
if(m_image) free(m_image);
}
/*
* Try to determine image dimensions.
*/
bool SQ_ImageLoader::tasteImage(const TQString &path, int *w, int *h, SQ_LIBRARY *_lib)
{
SQ_LIBRARY *lib;
int res;
fmt_codec_base *codeK;
// determine library for file
lib = _lib ? _lib : SQ_LibraryHandler::instance()->libraryForFile(path);
if(!lib)
return false;
// determine codec
codeK = lib->codec_il;
if(!codeK)
return false;
// init...
res = codeK->read_init(TQString(TQFile::encodeName(path)).ascii());
// error in init()!
if(res != SQE_OK)
{
codeK->read_close();
return false;
}
// advance to next page
res = codeK->read_next();
if(res != SQE_OK)
{
codeK->read_close();
return false;
}
else
{
fmt_image *image;
image = codeK->image(0);
*w = image->w;
*h = image->h;
codeK->read_close();
return true;
}
}
/*
* Try to load image and store a pointer to decoded image data in m_image. Aslo
* store information about the image in finfo.
*/
bool SQ_ImageLoader::loadImage(const TQString &pixPath, const SQ_CodecSettings::settings &sett, bool multi, int nomorethan)
{
SQ_LIBRARY *lib;
int res, current = 0, i, j;
RGBA *scan;
fmt_codec_base *codeK;
fmt_image *image;
finfo->image.clear();
finfo->meta.clear();
#define SQ_SAVE_INF \
*finfo = codeK->information(); \
codeK->read_close();
// reset error count
m_errors = 0;
// determine library for file
lib = SQ_LibraryHandler::instance()->libraryForFile(pixPath);
if(!lib)
return false;
// determine codec
codeK = lib->codec_il;
if(!codeK)
return false;
if(sett != SQ_CodecSettings::None)
SQ_CodecSettings::applySettings(lib, sett);
// init...
res = codeK->read_init(TQString(TQFile::encodeName(pixPath)).ascii());
// error in init()!
if(res != SQE_OK)
{
codeK->read_close();
return false;
}
// read all pages in image...
while(true)
{
if(m_errors || (!multi && current) || (multi && current == nomorethan))
break;
// advance to next page
i = codeK->read_next();
// error occured while decoding first page
if(i != SQE_OK && i != SQE_NOTOK && !current)
{
codeK->read_close();
return false;
}
else if((i != SQE_OK && i != SQE_NOTOK && current) || (i == SQE_NOTOK && current))
break;
image = codeK->image(current);
// realloc memory
if(!current)
{
const int S = image->w * image->h * sizeof(RGBA);
m_image = (RGBA *)realloc(m_image, S);
if(!m_image)
{
codeK->read_close();
return false;
}
memset(m_image, 255, S);
}
else
{
dumbscan = (RGBA *)realloc(dumbscan, image->w * image->h * sizeof(RGBA));
if(!dumbscan)
{
SQ_SAVE_INF
return false;
}
}
// read all passes
for(int pass = 0;pass < image->passes;pass++)
{
codeK->read_next_pass();
if(!current)
{
for(j = 0;j < image->h;j++)
{
scan = m_image + j * image->w;
i = codeK->read_scanline(scan);
m_errors += (i != SQE_OK);
}
}
else
{
for(j = 0;j < image->h;j++)
{
i = codeK->read_scanline(dumbscan);
SQ_SAVE_INF
return (i == SQE_OK);
}
}
}
// flip decoded image, if needed
if(image->needflip && !current)
fmt_utils::flipv((char *)m_image, image->w * sizeof(RGBA), image->h);
current++;
}
SQ_SAVE_INF
// all done!
return true;
}
// Delete buffers...
void SQ_ImageLoader::cleanup(bool del)
{
if(dumbscan) free(dumbscan);
if(del && m_image) free(m_image);
dumbscan = 0;
m_image = 0;
}
/*
* Return decoded image as TQImage.
*/
TQImage SQ_ImageLoader::image() const
{
TQImage image((unsigned char*)bits(), finfo->image[0].w, finfo->image[0].h, 32, 0, 0, TQImage::LittleEndian);
// if the image has alpha channel, let TQImage know it
if(finfo->image[0].hasalpha)
image.setAlphaBuffer(true);
return image.swapRGB();
}