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.
libksquirrel/kernel/kls_neo/fmt_codec_pnm.cpp

1471 lines
34 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>
// we will use fork()
#if defined CODEC_DJVU \
|| defined CODEC_CAMERA \
|| defined CODEC_DXF \
|| defined CODEC_XCF \
|| defined CODEC_TTF \
|| defined CODEC_FIG \
|| defined CODEC_LJPEG \
|| defined CODEC_NETPBM
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdio>
#endif
#ifdef CODEC_EPS
#include <cstdio>
#include <sstream>
#include <cmath>
#endif
#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_pnm_defs.h"
#include "fmt_codec_pnm.h"
#if defined CODEC_CAMERA
#include "../xpm/codec_camera.xpm"
#elif defined CODEC_DJVU
#include "../xpm/codec_djvu.xpm"
#elif defined CODEC_XCF
#include "../xpm/codec_xcf.xpm"
#elif defined CODEC_DXF
#include "../xpm/codec_dxf.xpm"
#elif defined CODEC_NEO
#include "../xpm/codec_neo.xpm"
#elif defined CODEC_LEAF
#include "../xpm/codec_leaf.xpm"
#elif defined CODEC_PI1
#include "../xpm/codec_pi1.xpm"
#elif defined CODEC_PI3
#include "../xpm/codec_pi3.xpm"
#elif defined CODEC_XIM
#include "../xpm/codec_xim.xpm"
#elif defined CODEC_UTAH
#include "../xpm/codec_utah.xpm"
#elif defined CODEC_PICT
#include "../xpm/codec_pict.xpm"
#elif defined CODEC_IFF
#include "../xpm/codec_iff.xpm"
#elif defined CODEC_MAC
#include "../xpm/codec_mac.xpm"
#elif defined CODEC_TTF
#include "../xpm/codec_ttf.xpm"
#elif defined CODEC_FIG
#include "../xpm/codec_fig.xpm"
#elif defined CODEC_LJPEG
#include "../xpm/codec_ljpeg.xpm"
#elif defined CODEC_EPS
#include "../xpm/codec_eps.xpm"
#else
#include "../xpm/codec_pnm.xpm"
#endif
/*
*
* PBM, PGM,
* PNM, and PPM are
* intermediate formats used in the conversion of many little known
* formats via pbmplus, the Portable Bitmap Utilities. These
* formats are mainly available under UNIX and
* on Intel-based PCs.
*
*/
static RGB palmono[2] = {RGB(255,255,255), RGB(0,0,0)};
fmt_codec::fmt_codec() : fmt_codec_base()
{}
fmt_codec::~fmt_codec()
{
#ifdef CODEC_DXF
std::string tmmp = tmp + ".ppm";
unlink(tmmp.c_str());
#endif
}
void fmt_codec::options(codec_options *o)
{
#if defined CODEC_CAMERA
o->version = "8.77"; // dcraw version
o->name = "Photos from different cameras";
o->filter = "*.arw *.bay *.bmq *.cr2 *.crw *.cs1 *.dc2 *.dcr *.dng *.erf *.fff *.hdr *.ia *.k25 *.kc2 *.kdc *.mdc *.mos *.mrw *.nef *.orf *.pef *.pxn *.raf *.raw *.rdc *.sr2 *.srf *.sti *.x3f ";
o->config = std::string(CAMERA_UI);
o->mime = "";
o->mimetype = "image/x-raw";
o->pixmap = codec_camera;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_DJVU
o->version = "1.0.0";
o->name = "DjVu Document";
o->filter = "*.djvu *.djv *.iw4 *.iw44 ";
o->config = std::string(DJVU_UI);
o->mime = "";
o->mimetype = "image/x-djvu;image/x.djvu";
o->pixmap = codec_djvu;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_DXF
o->version = "1.0.0";
o->name = "AutoCAD/QCAD Drawing";
o->filter = "*.dxf ";
o->config = std::string(DXF_UI);
o->mime = "";
o->mimetype = "image/x-dxf";
o->pixmap = codec_dxf;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_XCF
o->version = "1.0.0";
o->name = "GIMP XCF";
o->filter = "*.xcf ";
o->config = std::string(XCF_UI);
o->mime = "";
o->mimetype = "image/x-xcf-gimp";
o->pixmap = codec_xcf;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_NEO
o->version = "1.0.0";
o->name = "Neochrome NEO";
o->filter = "*.neo ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-neo";
o->pixmap = codec_neo;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_LEAF
o->version = "1.0.0";
o->name = "ILEAF Image";
o->filter = "*.leaf ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-leaf";
o->pixmap = codec_leaf;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_PI1
o->version = "1.0.0";
o->name = "Degas PI1";
o->filter = "*.pi1 ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-pi1";
o->pixmap = codec_pi1;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_PI3
o->version = "1.0.0";
o->name = "Degas PI3";
o->filter = "*.pi3 ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-pi3";
o->pixmap = codec_pi3;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_XIM
o->version = "1.0.0";
o->name = "X IMage";
o->filter = "*.xim ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-xim";
o->pixmap = codec_xim;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_UTAH
o->version = "1.0.0";
o->name = "UTAH RLE";
o->filter = "*.rle ";
o->config = "";
o->mime = "\x0052\x00CC";
o->mimetype = "image/x-utah";
o->pixmap = codec_utah;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_PICT
o->version = "1.0.0";
o->name = "Macintosh PICT";
o->filter = "*.pict ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-pict";
o->pixmap = codec_pict;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_IFF
o->version = "1.0.0";
o->name = "Interchange File Format";
o->filter = "*.iff *.ilbm *.lbm ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-iff";
o->pixmap = codec_iff;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_MAC
o->version = "1.0.0";
o->name = "Macintosh Paint";
o->filter = "*.mac ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-mac";
o->pixmap = codec_mac;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_FIG
o->version = "0.1.0";
o->name = "XFIG";
o->filter = "*.fig ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-xfig";
o->pixmap = codec_fig;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_TTF
o->version = "0.3.0";
o->name = "TrueType and Other Fonts";
o->filter = "*.ttf *.ttc *.pfa *.pfb *.otf ";
o->config = "";
o->mime = "";
o->mimetype = "application/x-font-ttf;application/x-font-ttc;application/x-font-otf;application/x-font-type1";
o->pixmap = codec_ttf;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_LJPEG
o->version = "0.1.0";
o->name = "Lossless JPEG";
o->filter = "*.ljpg *.ljpeg ";
o->config = "";
o->mime = "";
o->mimetype = "image/ljpeg";
o->pixmap = codec_ljpeg;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#elif defined CODEC_EPS
o->version = "0.1.0";
o->name = "Encapsulated PostScript";
o->filter = "*.eps ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-eps";
o->pixmap = codec_eps;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = true;
#else
o->version = "0.6.4";
o->name = "Portable aNy Map";
o->filter = "*.pnm *.pgm *.pbm *.ppm ";
o->config = "";
o->mime = "P[123456]";
o->mimetype = "image/x-portable-bitmap;image/x-portable-greymap;image/x-portable-pixmap";
o->pixmap = codec_pnm;
o->readable = true;
o->canbemultiple = false;
o->writestatic = true;
o->writeanimated = false;
o->needtempfile = false;
#endif
}
#if defined CODEC_CAMERA
void fmt_codec::fill_default_settings()
{
settings_value val;
// scale factor in percents
val.type = settings_value::v_bool;
val.bVal = true;
m_settings["half_size"] = val;
m_settings["automatic_white"] = val;
m_settings["camera_white"] = val;
val.bVal = false;
m_settings["dontstretch"] = val;
m_settings["camera_date"] = val;
m_settings["document_mode"] = val;
m_settings["interpolate_rggb"] = val;
m_settings["icc_cam"] = val;
m_settings["embedded_cm"] = val;
val.type = settings_value::v_int;
val.iVal = 0;
m_settings["highlights"] = val;
m_settings["different"] = val;
m_settings["flipping"] = val; // 0 means camera settings
val.iVal = 0; // 1,2,3 are accepted numbers. 1 means no interpolation
m_settings["quick"] = val;
val.iVal = -1; // don't use black pixel
m_settings["black"] = val;
val.iVal = 99; // values 100...1000 are accepted. 99 means no threshold
m_settings["threshold"] = val;
val.iVal = 1;
m_settings["brightness"] = val;
val.type = settings_value::v_string;
val.sVal = "";
m_settings["icc_file"] = val;
}
#elif defined CODEC_DJVU
void fmt_codec::fill_default_settings()
{
settings_value val;
// page number
val.type = settings_value::v_int;
val.iVal = 1;
m_settings["page"] = val;
val.iVal = 2;
m_settings["scaledown"] = val;
}
#elif defined CODEC_DXF
void fmt_codec::fill_default_settings()
{
settings_value val;
// page number
val.type = settings_value::v_int;
val.iVal = 0;
m_settings["width"] = val;
val.iVal = 0;
m_settings["height"] = val;
}
#elif defined CODEC_XCF
void fmt_codec::fill_default_settings()
{
settings_value val;
// background color
val.type = settings_value::v_string;
val.sVal = "#ffffff";
m_settings["background"] = val;
val.type = settings_value::v_bool;
val.bVal = false;
m_settings["autocrop"] = val;
}
#endif
#ifdef CODEC_EPS
/*
* Stolen from KImageIO EPS plugin from tdelibs-3.4.0, which is
* under GNU LGPL
*/
#define BUFLEN 200
#define BBOX "%%BoundingBox:"
#define BBOX_LEN strlen(BBOX)
static bool seekToCodeStart(ifstreamK *io, size_t &ps_offset, size_t &ps_size)
{
char buf[4]; // We at most need to read 4 bytes at a time
ps_offset = 0L;
ps_size = 0L;
if(!io->readK(buf, 2)) // Read first two bytes
return false;
if(buf[0]=='%' && buf[1]=='!') // Check %! magic
{
}
else if(buf[0] == char(0xc5) && buf[1] == char(0xd0)) // Check start of MS-DOS EPS magic
{ // May be a MS-DOS EPS file
if(!io->readK(buf+2, 2)) // Read further bytes of MS-DOS EPS magic
return false;
if(buf[2] == char(0xd3) && buf[3] == char(0xc6)) // Check last bytes of MS-DOS EPS magic
{
if(!io->readK(buf, 4)) // Get offset of PostScript code in the MS-DOS EPS file.
return false;
ps_offset // Offset is in little endian
= ((unsigned char) buf[0])
+ ((unsigned char) buf[1] << 8)
+ ((unsigned char) buf[2] << 16)
+ ((unsigned char) buf[3] << 24);
if (!io->readK(buf, 4)) // Get size of PostScript code in the MS-DOS EPS file.
return false;
ps_size // Size is in little endian
= ((unsigned char) buf[0])
+ ((unsigned char) buf[1] << 8)
+ ((unsigned char) buf[2] << 16)
+ ((unsigned char) buf[3] << 24);
if(!io->seekg(ps_offset, ios::beg)) // Get offset of PostScript code in the MS-DOS EPS file.
return false;
if(!io->readK(buf, 2)) // Read first two bytes of what should be the Postscript code
return false;
if(buf[0] != '%' || buf[1] != '!') // Check %! magic
return false;
}
else
return false;
}
else
return false;
return true;
}
static bool bbox(ifstreamK *io, int *x1, int *y1, int *x2, int *y2)
{
char buf[BUFLEN+1];
bool ret = false;
while(io->getline(buf, BUFLEN).good() && strlen(buf))
{
if(strncmp(buf, BBOX, BBOX_LEN) == 0)
{
// Some EPS files have non-integer values for the bbox
// We don't support that currently, but at least we parse it
float _x1, _y1, _x2, _y2;
if(sscanf(buf, "%*s %f %f %f %f", &_x1, &_y1, &_x2, &_y2) == 4)
{
*x1 = (int)_x1;
*y1 = (int)_y1;
*x2 = (int)_x2;
*y2 = (int)_y2;
ret = true;
break;
}
}
}
return ret;
}
#endif
s32 fmt_codec::read_init(const std::string &file)
{
fptr = 0;
#if defined CODEC_CAMERA
std::vector<std::string> params;
int status;
bool half_size,
dontstretch,
camera_date,
automatic_white,
camera_white,
document_mode,
interpolate_rggb,
icc_cam,
embedded_cm;
int quick,
threshold,
black,
different,
highlights,
flipping,
brightness;
std::string icc_file;
fmt_settings::iterator it = m_settings.find("half_size");
half_size = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
true : (*it).second.bVal;
it = m_settings.find("icc_cam");
icc_cam = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("embedded_cm");
embedded_cm = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("dontstretch");
dontstretch = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("camera_date");
camera_date = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("automatic_white");
automatic_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
true : (*it).second.bVal;
it = m_settings.find("camera_white");
camera_white = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
true : (*it).second.bVal;
it = m_settings.find("document_mode");
document_mode = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("interpolate_rggb");
interpolate_rggb = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
it = m_settings.find("quick");
quick = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
1 : (*it).second.iVal;
if(quick < 0 || quick > 3)
quick = 0;
it = m_settings.find("highlights");
highlights = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
0 : (*it).second.iVal;
if(highlights < 0 || highlights > 9)
highlights = 0; // revert to default value
it = m_settings.find("flipping");
flipping = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
0 : (*it).second.iVal;
if(flipping != 0 && flipping != 1 && flipping != 3 && flipping != 5 && flipping != 6)
flipping = 0; // revert to default value
it = m_settings.find("black");
black = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
-1 : (*it).second.iVal;
if(black < -1 || black > 255)
black = -1;
it = m_settings.find("different");
different = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
0 : (*it).second.iVal;
if(different < 0 || different > 99)
different = 0; // revert to default
it = m_settings.find("threshold");
threshold = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
100 : (*it).second.iVal;
if(threshold < 99 || threshold > 1000)
threshold = 99; // revert to default
it = m_settings.find("brightness");
brightness = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
1 : (*it).second.iVal;
if(brightness < 1 || brightness > 255)
brightness = 1;
it = m_settings.find("icc_file");
icc_file = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ?
"" : (*it).second.sVal;
if(embedded_cm)
params.push_back("+M");
else
params.push_back("-M");
if(half_size) params.push_back("-h");
if(dontstretch) params.push_back("-j");
if(camera_date) params.push_back("-z");
if(automatic_white) params.push_back("-a");
if(camera_white) params.push_back("-w");
if(document_mode) params.push_back("-d");
if(interpolate_rggb) params.push_back("-f");
char ss[32];
if(quick)
{
if(quick == 1)
quick = 0;
sprintf(ss, "%d", quick);
params.push_back("-q");
params.push_back(ss);
}
if(threshold != 99)
{
sprintf(ss, "%d", threshold);
params.push_back("-n");
params.push_back(ss);
}
if(black >= 0)
{
sprintf(ss, "%d", black);
params.push_back("-k");
params.push_back(ss);
}
sprintf(ss, "%d", different);
params.push_back("-s");
params.push_back(ss);
sprintf(ss, "%d", brightness);
params.push_back("-b");
params.push_back(ss);
sprintf(ss, "%d", highlights);
params.push_back("-H");
params.push_back(ss);
if(flipping)
{
if(flipping == 1)
flipping = 0; // 0, 3, 5, 6 are accepted
sprintf(ss, "%d", flipping);
params.push_back("-t");
params.push_back(ss);
}
#ifndef NO_LCMS
if(icc_cam)
{
params.push_back("-p");
params.push_back("embed");
}
else if(icc_file.length())
{
params.push_back("-p");
params.push_back(icc_file);
}
#endif
const s32 argc = 9 + params.size();
const char *argv[argc];
argv[0] = KLDCRAW_S;
for(int i = 1;i < argc-8;i++)
argv[i] = params[i-1].c_str();
argv[argc-8] = "-c"; // write to stdout
argv[argc-7] = "--input";
argv[argc-6] = file.c_str();
argv[argc-5] = "--binary";
argv[argc-4] = KLDCRAW;
argv[argc-3] = "--output";
argv[argc-2] = tmp.c_str();
argv[argc-1] = (char *)0;
pid_t pid = fork();
if(!pid)
{
execvp(argv[0], (char *const *)argv);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_DJVU
fmt_settings::iterator it = m_settings.find("scaledown");
// get aspect
s32 aspect = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
1 : (*it).second.iVal;
// correct
if(aspect < 1 || aspect > 12)
aspect = 2;
it = m_settings.find("page");
// get page number
s32 ipage = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
1 : (*it).second.iVal;
// correct
if(ipage < 0 || ipage > 1000)
ipage = 1;
int status;
s8 subsample[20];
s8 pagesp[20];
snprintf(subsample, 20, "-subsample=%d", aspect);
snprintf(pagesp, 20, "-page=%d", ipage);
pid_t pid = fork();
if(!pid)
{
execlp(DJVU, DJVU, "-format=ppm", subsample, pagesp, file.c_str(), tmp.c_str(), (char *)0);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_DXF
std::string tmmp = tmp + ".ppm";
fmt_settings::iterator it = m_settings.find("width");
// get aspect
s32 width = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
0 : (*it).second.iVal;
// correct
if(width < 0 || width > 10000)
width = 0;
it = m_settings.find("height");
// get page number
s32 height = (it == m_settings.end() || (*it).second.type != settings_value::v_int) ?
0 : (*it).second.iVal;
// correct
if(height < 0 || height > 10000)
height = 0;
s32 status;
s8 swidth[20], sheight[20];
const int argc = 8;
const char *argv[argc];
const char *x = "-x", *y = "-y";
int i = 3;
argv[0] = VEC2WEB;
argv[1] = file.c_str();
argv[2] = tmmp.c_str();
if(width)
{
snprintf(swidth, 20, "%d", width);
argv[i++] = x;
argv[i++] = swidth;
}
if(height)
{
snprintf(sheight, 20, "%d", height);
argv[i++] = y;
argv[i++] = sheight;
}
argv[i] = (char *)0;
pid_t pid = fork();
if(!pid)
{
execvp(VEC2WEB, (char* const*)argv);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmmp.c_str(), "rb");
#elif defined CODEC_XCF
const s32 argc = 9;
int status;
fmt_settings::iterator it = m_settings.find("background");
// background for transparent images
std::string bkgr = (it == m_settings.end() || (*it).second.type != settings_value::v_string) ?
"#ffffff" : (*it).second.sVal;
it = m_settings.find("autocrop");
// autocrop ?
bool autocrop = (it == m_settings.end() || (*it).second.type != settings_value::v_bool) ?
false : (*it).second.bVal;
const char *argv[argc];
argv[0] = KLXCF2PNM;
std::string bg = "-b";
bg += bkgr;
argv[1] = bg.c_str();
int i = 2;
if(autocrop)
{
argv[i++] = "-C";
}
argv[i++] = "-T";
argv[i++] = "-c";
argv[i++] = "-o";
argv[i++] = tmp.c_str();
argv[i++] = file.c_str();
argv[i++] = (char *)0;
pid_t pid = fork();
if(!pid)
{
execvp(KLXCF2PNM, (char *const *)argv);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0); // TODO check for errors
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_NETPBM
int status;
pid_t pid = fork();
if(!pid)
{
execlp(NETPBM_S, NETPBM_S, file.c_str(), tmp.c_str(), (char *)0);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_LJPEG
int status;
pid_t pid = fork();
if(!pid)
{
execlp(LJPEG2PPM_S, LJPEG2PPM_S, "--input", file.c_str(), "--binary", LJPEG2PPM, "--output", tmp.c_str(), (char *)0);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_FIG
int status;
pid_t pid = fork();
if(!pid)
{
execlp(XFIG_S, XFIG_S, file.c_str(), tmp.c_str(), (char *)0);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_TTF
int status;
pid_t pid = fork();
if(!pid)
{
execlp(TTF2PNM, TTF2PNM, file.c_str(), tmp.c_str(), (char *)0);
exit(1);
}
else if(pid == -1)
return SQE_R_BADFILE;
::waitpid(pid, &status, 0);
if(WIFEXITED(status))
if(WEXITSTATUS(status))
return SQE_R_BADFILE;
else;
else
return SQE_R_BADFILE;
fptr = fopen(tmp.c_str(), "rb");
#elif defined CODEC_EPS
/*
* EPS code was grabbed from KImageIO plugin for tdelibs-3.4.0. It is under LGPL.
*/
FILE * ghostfd;
int x1, y1, x2, y2;
std::string cmdBuf;
size_t ps_offset, ps_size;
ifstreamK io;
io.open(file.c_str(), ios::in);
if(!io.good())
return SQE_R_NOFILE;
// find start of PostScript code
if (!seekToCodeStart(&io, ps_offset, ps_size))
return SQE_R_BADFILE;
// find bounding box
if(!bbox(&io, &x1, &y1, &x2, &y2))
return SQE_R_BADFILE;
x2 -= x1;
y2 -= y1;
double xScale = 1.0;
double yScale = 1.0;
bool needsScaling = false;
int wantedWidth = x2;
int wantedHeight = y2;
std::stringstream str(cmdBuf);
str << EPS2PPM << " -sOutputFile=";
str << tmp;
str << " -q -g";
str << wantedWidth << "x" << wantedHeight;
str << " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
"0 0 moveto "
"1000 0 lineto "
"1000 1000 lineto "
"0 1000 lineto "
"1 1 254 255 div setrgbcolor fill "
"0 0 0 setrgbcolor - -c showpage quit";
ghostfd = popen(str.str().c_str(), "w");
if(ghostfd == 0)
return SQE_R_BADFILE;
fprintf(ghostfd, "\n%d %d translate\n", int(-floorf(x1*xScale)), int(-floorf(y1*yScale)));
if(needsScaling)
fprintf(ghostfd, "%g %g scale\n", xScale, yScale);
io.seekg(0, ios::beg);
char bbuf[4096];
if(ps_offset > 0) // We have an offset
io.seekg(ps_offset, ios::beg);
std::string buffer;
while(!io.eof())
{
io.read(bbuf, sizeof(bbuf));
buffer.append(bbuf, io.gcount());
}
// If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
if (ps_size <= 0 || ps_size > buffer.size())
ps_size = buffer.size();
fwrite(buffer.c_str(), sizeof(char), ps_size, ghostfd);
pclose(ghostfd);
fptr = fopen(tmp.c_str(), "rb");
#else
fptr = fopen(file.c_str(), "rb");
#endif
if(!fptr)
return SQE_R_NOFILE;
currentImage = -1;
finfo.animated = false;
return SQE_OK;
}
s32 fmt_codec::read_next()
{
currentImage++;
if(currentImage)
return SQE_NOTOK;
fmt_image image;
s8 str[256];
s32 w, h;
u32 maxcolor;
if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE;
pnm = str[1] - 48;
if(pnm < 1 || pnm > 6)
return SQE_R_BADFILE;
while(true)
{
if(!sq_fgets(str, 255, fptr)) return SQE_R_BADFILE;
if(str[0] != '#')
break;
}
sscanf(str, "%d%d", &w, &h);
image.w = w;
image.h = h;
switch(pnm)
{
case 1:
case 4:
image.bpp = 1;
break;
case 2:
case 5:
image.bpp = 8;
break;
case 3:
case 6:
image.bpp = 8;
break;
}
if(pnm != 4 && pnm != 1)
{
fscanf(fptr, "%d", &maxcolor);
if(sq_ferror(fptr)) return SQE_R_BADFILE;
if((pnm == 5 || pnm == 6) && maxcolor > 255)
return SQE_R_BADFILE;
if(pnm == 2 || pnm == 3)
{
if(!skip_flood(fptr))
return SQE_R_BADFILE;
}
else
{
u8 dummy;
if(!sq_fgetc(fptr, &dummy)) return SQE_R_BADFILE;
}
if(maxcolor <= 9)
strcpy(format, "%1d");
else if(maxcolor >= 9 && maxcolor <= 99)
strcpy(format, "%2d");
else if(maxcolor > 99 && maxcolor <= 999)
strcpy(format, "%3d");
else if(maxcolor > 999 && maxcolor <= 9999)
strcpy(format, "%4d");
koeff = 255.0 / maxcolor;
}
else if(pnm == 1)
{
strcpy(format, "%1d");
koeff = 1.0;
}
image.compression = "-";
image.colorspace = ((pnm == 1 || pnm == 4) ? "Monochrome":"Color indexed");
finfo.image.push_back(image);
return SQE_OK;
}
s32 fmt_codec::read_scanline(RGBA *scan)
{
RGB rgb;
u8 bt;
s32 i, a;
fmt_image *im = image(currentImage);
fmt_utils::fillAlpha(scan, im->w);
switch(pnm)
{
case 1:
{
for(i = 0;i < im->w;i++)
{
fscanf(fptr, format, &a);
if(sq_ferror(fptr)) return SQE_R_BADFILE;
a = (s32)(a * koeff);
memcpy(scan+i, palmono+a, sizeof(RGB));
}
if(!skip_flood(fptr))
return SQE_R_BADFILE;
}
break;
case 2:
{
for(i = 0;i < im->w;i++)
{
fscanf(fptr, format, &a);
if(sq_ferror(fptr)) return SQE_R_BADFILE;
a = (s32)(a * koeff);
memset(scan+i, a, sizeof(RGB));
}
if(!skip_flood(fptr))
return SQE_R_BADFILE;
}
break;
case 3:
for(i = 0;i < im->w;i++)
{
fscanf(fptr, format, &a); rgb.r = a;
fscanf(fptr, format, &a); rgb.g = a;
fscanf(fptr, format, &a); rgb.b = a;
if(sq_ferror(fptr)) return SQE_R_BADFILE;
memcpy(scan+i, &rgb, sizeof(RGB));
}
if(!skip_flood(fptr))
return SQE_R_BADFILE;
break;
case 6:
for(i = 0;i < im->w;i++)
{
if(!sq_fread(&rgb, sizeof(RGB), 1, fptr)) return SQE_R_BADFILE;
memcpy(scan+i, &rgb, sizeof(RGB));
}
break;
case 5:
{
for(i = 0;i < im->w;i++)
{
if(!sq_fread(&bt, 1, 1, fptr)) return SQE_R_BADFILE;
memset(scan+i, int(bt*koeff), sizeof(RGB));
}
}
break;
case 4:
{
s32 index;//, remain = im->w % 8;
for(i = 0;;)
{
if(!sq_fread(&bt,1,1,fptr)) return SQE_R_BADFILE;
index = (bt&128)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&64)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&32)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&16)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&8)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&4)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&2)?1:0;
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
index = (bt&1);
memcpy(scan+i, palmono+index, 3);i++; if(i >= im->w) break;
}
}
break;
}
return SQE_OK;
}
s32 fmt_codec::read_next_pass()
{
return SQE_OK;
}
void fmt_codec::read_close()
{
if(fptr)
fclose(fptr);
finfo.meta.clear();
finfo.image.clear();
}
bool skip_flood(FILE *f)
{
s32 pos;
u8 b;
while(true)
{
pos = ftell(f);
if(!sq_fread(&b, 1, 1, f)) return false;
if(!isspace(b))
{
if(b == '#')
{
while(true)
{
if(!sq_fgetc(f, &b)) return false;
if(b == '\n')
break;
}
}
break;
}
}
fsetpos(f, (fpos_t*)&pos);
return true;
}
#ifdef CODEC_PNM
void fmt_codec::getwriteoptions(fmt_writeoptionsabs *opt)
{
opt->interlaced = false;
opt->compression_scheme = CompressionNo;
opt->compression_min = 0;
opt->compression_max = 0;
opt->compression_def = 0;
opt->passes = 1;
opt->needflip = false;
opt->palette_flags = 0 | fmt_image::pure32;
}
s32 fmt_codec::write_init(const std::string &file, const fmt_image &image, const fmt_writeoptions &opt)
{
if(!image.w || !image.h || file.empty())
return SQE_W_WRONGPARAMS;
writeimage = image;
writeopt = opt;
fws.open(file.c_str(), ios::binary | ios::out);
if(!fws.good())
return SQE_W_NOFILE;
return SQE_OK;
}
s32 fmt_codec::write_next()
{
fws << "P6" << endl << writeimage.w << " " << writeimage.h << endl << 255 << endl;
return fws.good() ? SQE_OK : SQE_W_ERROR;
}
s32 fmt_codec::write_next_pass()
{
return SQE_OK;
}
s32 fmt_codec::write_scanline(RGBA *scan)
{
for(s32 i = 0;i < writeimage.w;i++)
{
if(!fws.writeK(scan+i, sizeof(RGB)))
return SQE_W_ERROR;
}
return SQE_OK;
}
void fmt_codec::write_close()
{
fws.close();
}
std::string fmt_codec::extension(const s32 /*bpp*/)
{
return std::string("pnm");
}
#endif // CODEC_PNM
#include "fmt_codec_cd_func.h"