00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 fv.clear(); cv.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 default:
00069 planck_fail("Palette #"+dataToString(num)+" not yet supported.");
00070 }
00071 }
00072
00073 void LS_Image::write_char (int xpos, int ypos, const Colour &col, char c,
00074 int scale)
00075 {
00076 planck_assert ((c>=font.offset) && (c<font.offset+font.num_chars),
00077 "write_char: character out of range");
00078 for (int i=0; i<font.xpix; ++i)
00079 for (int j=0; j<font.ypix; ++j)
00080 {
00081 int ofs = (c-font.offset)*font.xpix*font.ypix + j*font.xpix + i;
00082 if (font.data[ofs]!=' ')
00083 for (int m=0; m<scale; ++m)
00084 for (int n=0; n<scale; ++n)
00085 put_pixel(xpos+scale*i+m,ypos+scale*j+n,col);
00086 }
00087 }
00088
00089 LS_Image::LS_Image ()
00090 : font(medium_bold_font) {}
00091
00092 LS_Image::LS_Image (int xres, int yres)
00093 : font(medium_bold_font), pixel(xres,yres,Colour(0,0,0)) {}
00094
00095 void LS_Image::annotate (int xpos, int ypos, const Colour &col,
00096 const string &text, int scale)
00097 {
00098 for (tsize m=0; m<text.length(); ++m)
00099 write_char(xpos+m*scale*font.xpix, ypos, col, text[m],scale);
00100 }
00101
00102 void LS_Image::annotate_centered (int xpos, int ypos, const Colour &col,
00103 const string &text, int scale)
00104 {
00105 xpos-=(scale*text.length()*font.xpix)/2;
00106 ypos-=scale*font.ypix/2;
00107 annotate (xpos,ypos,col,text,scale);
00108 }
00109
00110 void LS_Image::set_font (const MP_Font &fnt)
00111 { font = fnt; }
00112
00113 void LS_Image::write_TGA (const string &file) const
00114 {
00115 ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00116 planck_assert(out, "could not create file '" + file + "'");
00117
00118 tsize xres=pixel.size1(), yres=pixel.size2();
00119
00120 bostream bo(out);
00121 const uint8 header[18] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00122 uint8(xres%256), uint8(xres/256), uint8(yres%256), uint8(yres/256), 24, 32};
00123
00124 bo.put (header, 18);
00125
00126 for (tsize j=0; j<yres; ++j)
00127 for (tsize i=0; i<xres; ++i)
00128 bo << pixel[i][j].b << pixel[i][j].g << pixel[i][j].r;
00129
00130 planck_assert(out,"error writing output file '" + file + "'");
00131 }
00132
00133 namespace {
00134
00135 void write_equal_range (const arr<Colour8> &px, tsize begin, tsize end,
00136 bostream &file)
00137 {
00138 chunkMaker cm (end-begin,128);
00139 uint64 cbeg, csz;
00140 while (cm.getNext(cbeg,csz))
00141 {
00142 file << uint8(csz-1+128);
00143 file << px[begin].b << px[begin].g << px[begin].r;
00144 }
00145 }
00146 void write_unequal_range (const arr<Colour8> &px, tsize begin, tsize end,
00147 bostream &file)
00148 {
00149 chunkMaker cm (end-begin,128);
00150 uint64 cbeg, csz;
00151 while (cm.getNext(cbeg,csz))
00152 {
00153 file << uint8(csz-1);
00154 for (tsize cnt=begin+cbeg; cnt< begin+cbeg+csz; ++cnt)
00155 file << px[cnt].b << px[cnt].g << px[cnt].r;
00156 }
00157 }
00158
00159 }
00160
00161 void LS_Image::write_TGA_rle(const string &file) const
00162 {
00163 ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00164 planck_assert(out, "could not create file '" + file + "'");
00165
00166 tsize xres=pixel.size1(), yres=pixel.size2();
00167
00168 bostream bo(out);
00169 const uint8 header[18] = { 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00170 uint8(xres%256), uint8(xres/256), uint8(yres%256), uint8(yres/256), 24, 32};
00171
00172 bo.put(header,18);
00173 for (tsize y=0; y<yres; ++y)
00174 {
00175 arr<Colour8> px(xres);
00176 for (tsize x=0; x<xres; ++x) px[x] = pixel[x][y];
00177 tsize xstart=0;
00178 while (xstart<xres)
00179 {
00180 if (xstart==xres-1)
00181 {
00182 write_unequal_range (px,xstart,xstart+1,bo);
00183 xstart=xres;
00184 }
00185 else
00186 {
00187 if (px[xstart+1]==px[xstart])
00188 {
00189 tsize xend=xstart+2;
00190 while ((xend<xres) && (px[xend]==px[xstart])) ++xend;
00191 write_equal_range (px,xstart,xend,bo);
00192 xstart=xend;
00193 }
00194 else
00195 {
00196 tsize xend=xstart+2;
00197 while ((xend<xres) && (px[xend]!=px[xend-1])) ++xend;
00198 write_unequal_range (px,xstart,xend,bo);
00199 xstart=xend;
00200 }
00201 }
00202 }
00203 }
00204 planck_assert(out,"error writing output file '" + file + "'");
00205 }
00206
00207 void LS_Image::write_PPM (const string &file) const
00208 {
00209 ofstream out(file.c_str(), ios_base::out | ios_base::binary);
00210 planck_assert(out, "could not create file '" + file + "'");
00211
00212 tsize xres=pixel.size1(), yres=pixel.size2();
00213
00214 bostream bo(out);
00215
00216 ostringstream header;
00217 header << "P6" << endl << xres << endl << yres << endl << 255 << endl;
00218 string hdrdata = header.str();
00219 bo.put(hdrdata.c_str(),hdrdata.size());
00220
00221 for (tsize j=0; j<yres; ++j)
00222 for (tsize i=0; i<xres; ++i)
00223 bo << pixel[i][j].r << pixel[i][j].g << pixel[i][j].b;
00224
00225 planck_assert(out,"error writing output file '" + file + "'");
00226 }