diff options
Diffstat (limited to 'kernel/kls_iff/fmt_codec_pnm.cpp')
-rw-r--r-- | kernel/kls_iff/fmt_codec_pnm.cpp | 1470 |
1 files changed, 1470 insertions, 0 deletions
diff --git a/kernel/kls_iff/fmt_codec_pnm.cpp b/kernel/kls_iff/fmt_codec_pnm.cpp new file mode 100644 index 0000000..06aedd6 --- /dev/null +++ b/kernel/kls_iff/fmt_codec_pnm.cpp @@ -0,0 +1,1470 @@ +/* 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 kdelibs-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 kdelibs-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" |