/* -*- C++ -*- * Copyright ©2004 Hugo Mills * * This software is distributed under the terms of the GNU GPL v3 * For more information on the GPL, see the file COPYING or * visit http://www.gnu.org/ * * This software is distributed without warranty */ #include "content_bitmap.h" #include #include #include "magellan/options.h" extern "C" PluginInfo* getmodules(int i) { if(i==0) { PluginInfo_Content* pi = new PluginInfo_Content(); pi->name = "Bitmap content"; pi->author = "Hugo Mills"; pi->copyright = "©2005 Hugo Mills"; pi->version = 0x10001; pi->parser = Content_Bitmap::parse; return pi; } else return NULL; } Content* Content_Bitmap::parse( ConfigLexer* lex, const std::string& type, const std::string& subtype ) { if(type != "bitmap") return NULL; std::string filename = ""; std::string fmt = ""; bool smth = false; while(!lex->eos()) { if(readkeyedvalue(lex, "file", &filename) || readkeyedvalue(lex, "format", &fmt) || readbooleanvalue(lex, "smooth", &smth) ) { } else throw(UnknownConfigToken(lex)); } if(filename == "") throw PluginInitError("Filename not specified"); std::string tmp = opts->find_data_file("bitmap", filename); if(tmp == "") throw PluginInitError("File '" + filename + "' not found"); filename = tmp; return new Content_Bitmap(filename, fmt, smth); } Content_Bitmap::Content_Bitmap( std::string fn, std::string fmt, bool smt ) : filename(fn), format(fmt), smooth(smt) { #ifdef HAVE_PAINTLIB PLAnyPicDecoder decoder; try { // std::cerr << "Opening " << filename << std::endl; decoder.MakeBmpFromFile(filename.c_str(), &source_bitmap, PLPixelFormat::R8G8B8); } catch(PLTextException Ex) { throw PluginInitError(Ex); } // Get the addresses of the bitmap lines pixlines = source_bitmap.GetLineArray32(); wid = source_bitmap.GetWidth(); hgt = source_bitmap.GetHeight(); #else #ifdef HAVE_LIBJPEG // Allocate & init a JPEG decomp object struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); // Specify source of data FILE* infile = std::fopen(filename.c_str(), "rb"); if(infile == NULL) { std::cerr << "Can't open file " << filename << std::endl; throw PluginInitError(""); } jpeg_stdio_src(&cinfo, infile); // Call jpeg_read_header to get image info jpeg_read_header(&cinfo, true); // Set parameters for decomp jpeg_start_decompress(&cinfo); // Allocate data object wid = cinfo.output_width; hgt = cinfo.output_height; bpp = cinfo.output_components; bitmap_data = new JSAMPROW[hgt]; for(int i=0; ibottom(); bm_pos[1] < viewport->top(); bm_pos[1]++) { for(bm_pos[0] = viewport->left(); bm_pos[0] < viewport->right(); bm_pos[0]++) { if(!viewport->g(map_pos, bm_pos)) continue; if(projection->g(shifted_pos, map_pos) && orbit->g(globe_pos, shifted_pos) && sphere->g(latlong, globe_pos)) { dvec2 pixelpos; pixelpos[0] = (latlong[0]+M_PI)*xconv; pixelpos[1] = (latlong[1]+M_PI_2)*yconv; if(smooth) { getpixel(c00, pixelpos); pixelpos[0]++; getpixel(c10, pixelpos); pixelpos[1]++; getpixel(c11, pixelpos); pixelpos[0]--; getpixel(c01, pixelpos); blend(colour, c00, c10, c11, c01, pixelpos[0] - int(pixelpos[0]), pixelpos[1] - int(pixelpos[1])); } else { getpixel(colour, pixelpos); } } else { colour[0] = colour[1] = colour[2] = 0; continue; } bitmap->setpixel(bm_pos, colour); } } } void Content_Bitmap::getpixel(ivec3& result, const dvec2& p) const { dvec2 pos = p; if(pos[0] < 0) pos[0] += wid; if(pos[1] < 0) pos[1] += hgt; if(pos[0] >= wid) pos[0] -= wid; if(pos[1] >= hgt) pos[1] -= hgt; // Flip vertically, as coordinate systems are different pos[1] = hgt - pos[1] - 1; #ifdef HAVE_PAINTLIB PLPixel32* pix = pixlines[int(pos[1])] + int(pos[0]); result[0] = pix->GetR(); result[1] = pix->GetG(); result[2] = pix->GetB(); #else #ifdef HAVE_LIBJPEG JSAMPLE* ppix = bitmap_data[int(pos[1])] + bpp*int(pos[0]); switch(bpp) { case 1: result[0] = result[1] = result[2] = *ppix; break; case 3: result[0] = *(ppix+0); result[1] = *(ppix+1); result[2] = *(ppix+2); break; default: result[0] = 255; result[1] = 78; result[2] = 200; // Probably a particularly horrid shade of pink break; } #else #endif #endif } void Content_Bitmap::blend(ivec3& output, const ivec3& c00, const ivec3& c10, const ivec3& c11, const ivec3& c01, double dx, double dy) const { for(int i=0; i<3; i++) { double t0 = c00[i] + (c10[i] - c00[i]) * dx; double t1 = c01[i] + (c11[i] - c01[i]) * dx; output[i] = int(t0 + (t1 - t0) * dy); } }