/* 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 // 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 #include #include #include #endif #ifdef CODEC_EPS #include #include #include #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 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"