ls_image.cc

00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*
00026  *  Classes for creation and output of image files
00027  *
00028  *  Copyright (C) 2003-2015 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include <fstream>
00033 #include <sstream>
00034 #include "ls_image.h"
00035 #include "bstream.h"
00036 #include "font_data.inc"
00037 #include "string_utils.h"
00038 #include "share_utils.h"
00039 
00040 using namespace std;
00041 
00042 const MP_Font medium_bold_font = { 0, 128, 7, 13, medium_bold_font_data };
00043 const MP_Font giant_font = { 0, 128, 9, 15, giant_font_data };
00044 
00045 void Palette::setPredefined (int num)
00046   {
00047   clear();
00048   switch(num)
00049     {
00050     case 0:
00051       add(0,Colour(0,0,0));
00052       add(1,Colour(1,1,1));
00053       break;
00054     case 1:
00055       add(0,Colour(0,0,0));
00056       add(0.4f,Colour(0,0,0.5f));
00057       add(0.75f,Colour(0,0.6f,1));
00058       add(1,Colour(1,1,1));
00059       break;
00060     case 4:
00061       add(0,Colour(0,0,.5f));
00062       add(0.15f,Colour(0,0,1));
00063       add(0.4f,Colour(0,1,1));
00064       add(0.7f,Colour(1,1,0));
00065       add(0.9f,Colour(1,.33f,0));
00066       add(1,Colour(.5f,0,0));
00067       break;
00068     case 10: // Planck colours 1
00069       addb(  0,  0,  0,255);
00070       addb( 42,  0,112,255);
00071       addb( 85,  0,221,255);
00072       addb(127,255,237,217);
00073       addb(170,255,180,  0);
00074       addb(212,255, 75,  0);
00075       addb(255,100,  0,  0);
00076       break;
00077     case 11: // Planck colours 2
00078       addb(  0,  0,  0,255);
00079       addb( 13, 10, 20,255);
00080       addb( 26, 30,184,255);
00081       addb( 38, 80,235,255);
00082       addb( 52,191,239,250);
00083       addb( 65,228,240,245);
00084       addb( 76,241,241,212);
00085       addb( 77,241,241,212);
00086       addb( 88,245,240,175);
00087       addb(101,248,235,130);
00088       addb(114,250,204, 38);
00089       addb(127,243,153, 13);
00090       addb(140,204, 77,  0);
00091       addb(153,165, 32, 32);
00092       addb(166,114,  0, 32);
00093       addb(179,128,128,153);
00094       addb(192,179,179,204);
00095       addb(205,204,204,230);
00096       addb(218,230,230,242);
00097       addb(231,242,242,250);
00098       addb(255,252,252,255);
00099       break;
00100     default:
00101       planck_fail("Palette #"+dataToString(num)+" not yet supported.");
00102     }
00103   }
00104 
00105 void LS_Image::write_char (int xpos, int ypos, const Colour &col, char c,
00106   int scale)
00107   {
00108   planck_assert ((c>=font.offset) && (c<font.offset+font.num_chars),
00109     "write_char: character out of range");
00110   for (int i=0; i<font.xpix; ++i)
00111     for (int j=0; j<font.ypix; ++j)
00112       {
00113       int ofs = (c-font.offset)*font.xpix*font.ypix + j*font.xpix + i;
00114       if (font.data[ofs]!=' ')
00115         for (int m=0; m<scale; ++m)
00116           for (int n=0; n<scale; ++n)
00117             put_pixel(xpos+scale*i+m,ypos+scale*j+n,col);
00118       }
00119   }
00120 
00121 LS_Image::LS_Image ()
00122   : font(medium_bold_font) {}
00123 
00124 LS_Image::LS_Image (int xres, int yres)
00125   : font(medium_bold_font), pixel(xres,yres,Colour(0,0,0)) {}
00126 
00127 void LS_Image::annotate (int xpos, int ypos, const Colour &col,
00128   const string &text, int scale)
00129   {
00130   for (tsize m=0; m<text.length(); ++m)
00131     write_char(xpos+m*scale*font.xpix, ypos, col, text[m],scale);
00132   }
00133 
00134 void LS_Image::annotate_centered (int xpos, int ypos, const Colour &col,
00135   const string &text, int scale)
00136   {
00137   xpos-=(scale*text.length()*font.xpix)/2;
00138   ypos-=scale*font.ypix/2;
00139   annotate (xpos,ypos,col,text,scale);
00140   }
00141 
00142 void LS_Image::set_font (const MP_Font &fnt)
00143   { font = fnt; }
00144 
00145 void LS_Image::write_TGA (const string &file) const
00146   {
00147   ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00148   planck_assert(out, "could not create file '" + file + "'");
00149 
00150   tsize xres=pixel.size1(), yres=pixel.size2();
00151 
00152   bostream bo(out);
00153   const uint8 header[18] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00154     uint8(xres%256), uint8(xres/256), uint8(yres%256), uint8(yres/256), 24, 32};
00155 
00156   bo.put (header, 18);
00157   vector <uint8> line(3*xres);
00158   for (tsize j=0; j<yres; ++j)
00159     {
00160     for (tsize i=0; i<xres; ++i)
00161       {
00162       line[i*3  ]=pixel[i][j].b;
00163       line[i*3+1]=pixel[i][j].g;
00164       line[i*3+2]=pixel[i][j].r;
00165       }
00166     bo.put(line.data(),3*xres);
00167     }
00168   planck_assert(out,"error writing output file '" + file + "'");
00169   }
00170 
00171 namespace {
00172 
00173 void write_equal_range (const arr<Colour8> &px, tsize begin, tsize end,
00174   vector<uint8> &buf)
00175   {
00176   chunkMaker cm (end-begin,128);
00177   uint64 cbeg, csz;
00178   while (cm.getNext(cbeg,csz))
00179     {
00180     buf.push_back(uint8(csz-1+128));
00181     buf.push_back(px[begin].b);
00182     buf.push_back(px[begin].g);
00183     buf.push_back(px[begin].r);
00184     }
00185   }
00186 void write_unequal_range (const arr<Colour8> &px, tsize begin, tsize end,
00187   vector<uint8> &buf)
00188   {
00189   chunkMaker cm (end-begin,128);
00190   uint64 cbeg, csz;
00191   while (cm.getNext(cbeg,csz))
00192     {
00193     buf.push_back(uint8(csz-1));
00194     for (tsize cnt=begin+cbeg; cnt< begin+cbeg+csz; ++cnt)
00195       {
00196       buf.push_back(px[cnt].b);
00197       buf.push_back(px[cnt].g);
00198       buf.push_back(px[cnt].r);
00199       }
00200     }
00201   }
00202 
00203 } // unnamed namespace
00204 
00205 void LS_Image::write_TGA_rle(const string &file) const
00206   {
00207   ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00208   planck_assert(out, "could not create file '" + file + "'");
00209 
00210   tsize xres=pixel.size1(), yres=pixel.size2();
00211 
00212   bostream bo(out);
00213   const uint8 header[18] = { 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00214     uint8(xres%256), uint8(xres/256), uint8(yres%256), uint8(yres/256), 24, 32};
00215 
00216   bo.put(header,18);
00217   vector<uint8> buf;
00218   arr<Colour8> px(xres);
00219   for (tsize y=0; y<yres; ++y)
00220     {
00221     buf.clear();
00222     for (tsize x=0; x<xres; ++x)
00223       px[x] = pixel[x][y];
00224     tsize xstart=0;
00225     while (xstart<xres)
00226       {
00227       if (xstart==xres-1)
00228         {
00229         write_unequal_range (px,xstart,xstart+1,buf);
00230         xstart=xres;
00231         }
00232       else
00233         {
00234         if (px[xstart+1]==px[xstart]) // range of equal pixels
00235           {
00236           tsize xend=xstart+2;
00237           while ((xend<xres) && (px[xend]==px[xstart])) ++xend;
00238           write_equal_range (px,xstart,xend,buf);
00239           xstart=xend;
00240           }
00241         else
00242           {
00243           tsize xend=xstart+2;
00244           while ((xend<xres) && (px[xend]!=px[xend-1])) ++xend;
00245           write_unequal_range (px,xstart,xend,buf);
00246           xstart=xend;
00247           }
00248         }
00249       }
00250     bo.put(buf.data(), buf.size());
00251     }
00252   planck_assert(out,"error writing output file '" + file + "'");
00253   }
00254 
00255 void LS_Image::write_PPM (const string &file) const
00256   {
00257   ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00258   planck_assert(out, "could not create file '" + file + "'");
00259 
00260   tsize xres=pixel.size1(), yres=pixel.size2();
00261 
00262   bostream bo(out);
00263 
00264   ostringstream header;
00265   header << "P6" << endl << xres << endl << yres << endl << 255 << endl;
00266   string hdrdata = header.str();
00267   bo.put(hdrdata.c_str(),hdrdata.size());
00268 
00269   vector <uint8> line(3*xres);
00270   for (tsize j=0; j<yres; ++j)
00271     {
00272     for (tsize i=0; i<xres; ++i)
00273       {
00274       line[i*3  ]=pixel[i][j].r;
00275       line[i*3+1]=pixel[i][j].g;
00276       line[i*3+2]=pixel[i][j].b;
00277       }
00278     bo.put(line.data(),3*xres);
00279     }
00280   planck_assert(out,"error writing output file '" + file + "'");
00281   }

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library