# screenshot.cpp

Go to the documentation of this file.

    00001 /* $Id: screenshot.cpp 17989 2009-11-06 23:01:52Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "fileio_func.h"
    00008 #include "viewport_func.h"
    00009 #include "gfx_func.h"
    00010 #include "screenshot.h"
    00011 #include "variables.h"
    00012 #include "blitter/factory.hpp"
    00013 #include "zoom_func.h"
    00014 #include "core/alloc_func.hpp"
    00015 #include "core/endian_func.hpp"
    00016 #include "map_func.h"
    00017 #include "saveload/saveload.h"
    00018 #include "company_func.h"
    00019
    00020
    00021 char _screenshot_format_name[8];
    00022 uint _num_screenshot_formats;
    00023 uint _cur_screenshot_format;
    00024 char _screenshot_name[128];
    00025 ScreenshotType current_screenshot_type;
    00026
    00027 /* called by the ScreenShot proc to generate screenshot lines. */
    00028 typedef void ScreenshotCallback(void *userdata, void *buf, uint y, uint pitch, uint n);
    00029 typedef bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette);
    00030
    00031 struct ScreenshotFormat {
    00032   const char *name;
    00033   const char *extension;
    00034   ScreenshotHandlerProc *proc;
    00035 };
    00036
    00037 /*************************************************
    00038  **** SCREENSHOT CODE FOR WINDOWS BITMAP (.BMP)
    00039  *************************************************/
    00040 #if defined(_MSC_VER) || defined(__WATCOMC__)
    00041 #pragma pack(push, 1)
    00042 #endif
    00043
    00045 struct BitmapFileHeader {
    00046   uint16 type;
    00047   uint32 size;
    00048   uint32 reserved;
    00049   uint32 off_bits;
    00050 } GCC_PACK;
    00051 assert_compile(sizeof(BitmapFileHeader) == 14);
    00052
    00053 #if defined(_MSC_VER) || defined(__WATCOMC__)
    00054 #pragma pack(pop)
    00055 #endif
    00056
    00058 struct BitmapInfoHeader {
    00059   uint32 size;
    00060   int32 width, height;
    00061   uint16 planes, bitcount;
    00062   uint32 compression, sizeimage, xpels, ypels, clrused, clrimp;
    00063 };
    00064 assert_compile(sizeof(BitmapInfoHeader) == 40);
    00065
    00067 struct RgbQuad {
    00068   byte blue, green, red, reserved;
    00069 };
    00070 assert_compile(sizeof(RgbQuad) == 4);
    00071
    00073 struct RgbTriplet {
    00074   byte b, g, r;
    00075 };
    00076 assert_compile(sizeof(RgbTriplet) == 3);
    00077
    00089 static bool MakeBmpImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
    00090 {
    00091   uint bpp; // bytes per pixel
    00092   switch (pixelformat) {
    00093     case 8:  bpp = 1; break;
    00094     /* 32bpp mode is saved as 24bpp BMP */
    00095     case 32: bpp = 3; break;
    00096     /* Only implemented for 8bit and 32bit images so far */
    00097     default: return false;
    00098   }
    00099
    00100   FILE *f = fopen(name, "wb");
    00101   if (f == NULL) return false;
    00102
    00103   /* Each scanline must be aligned on a 32bit boundary */
    00104   uint bytewidth = Align(w * bpp, 4); // bytes per line in file
    00105
    00106   /* Size of palette. Only present for 8bpp mode */
    00107   uint pal_size = pixelformat == 8 ? sizeof(RgbQuad) * 256 : 0;
    00108
    00109   /* Setup the file header */
    00110   BitmapFileHeader bfh;
    00111   bfh.type = TO_LE16('MB');
    00112   bfh.size = TO_LE32(sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + pal_size + bytewidth * h);
    00113   bfh.reserved = 0;
    00114   bfh.off_bits = TO_LE32(sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + pal_size);
    00115
    00116   /* Setup the info header */
    00117   BitmapInfoHeader bih;
    00118   bih.size = TO_LE32(sizeof(BitmapInfoHeader));
    00119   bih.width = TO_LE32(w);
    00120   bih.height = TO_LE32(h);
    00121   bih.planes = TO_LE16(1);
    00122   bih.bitcount = TO_LE16(bpp * 8);
    00123   bih.compression = 0;
    00124   bih.sizeimage = 0;
    00125   bih.xpels = 0;
    00126   bih.ypels = 0;
    00127   bih.clrused = 0;
    00128   bih.clrimp = 0;
    00129
    00130   /* Write file header and info header */
    00131   if (fwrite(&bfh, sizeof(bfh), 1, f) != 1 || fwrite(&bih, sizeof(bih), 1, f) != 1) {
    00132     fclose(f);
    00133     return false;
    00134   }
    00135
    00136   if (pixelformat == 8) {
    00137     /* Convert the palette to the windows format */
    00138     RgbQuad rq[256];
    00139     for (uint i = 0; i < 256; i++) {
    00140       rq[i].red   = palette[i].r;
    00141       rq[i].green = palette[i].g;
    00142       rq[i].blue  = palette[i].b;
    00143       rq[i].reserved = 0;
    00144     }
    00145     /* Write the palette */
    00146     if (fwrite(rq, sizeof(rq), 1, f) != 1) {
    00147       fclose(f);
    00148       return false;
    00149     }
    00150   }
    00151
    00152   /* Try to use 64k of memory, store between 16 and 128 lines */
    00153   uint maxlines = Clamp(65536 / (w * pixelformat / 8), 16, 128); // number of lines per iteration
    00154
    00155   uint8 *buff = MallocT<uint8>(maxlines * w * pixelformat / 8); // buffer which is rendered to
    00156   uint8 *line = AllocaM(uint8, bytewidth); // one line, stored to file
    00157   memset(line, 0, bytewidth);
    00158
    00159   /* Start at the bottom, since bitmaps are stored bottom up */
    00160   do {
    00161     uint n = min(h, maxlines);
    00162     h -= n;
    00163
    00164     /* Render the pixels */
    00165     callb(userdata, buff, h, w, n);
    00166
    00167     /* Write each line */
    00168     while (n-- != 0) {
    00169       if (pixelformat == 8) {
    00170         /* Move to 'line', leave last few pixels in line zeroed */
    00171         memcpy(line, buff + n * w, w);
    00172       } else {
    00173         /* Convert from 'native' 32bpp to BMP-like 24bpp.
    00174          * Works for both big and little endian machines */
    00175         Colour *src = ((Colour *)buff) + n * w;
    00176         RgbTriplet *dst = (RgbTriplet *)line;
    00177         for (uint i = 0; i < w; i++) {
    00178           dst[i].r = src[i].r;
    00179           dst[i].g = src[i].g;
    00180           dst[i].b = src[i].b;
    00181         }
    00182       }
    00183       /* Write to file */
    00184       if (fwrite(line, bytewidth, 1, f) != 1) {
    00185         free(buff);
    00186         fclose(f);
    00187         return false;
    00188       }
    00189     }
    00190   } while (h != 0);
    00191
    00192   free(buff);
    00193   fclose(f);
    00194
    00195   return true;
    00196 }
    00197
    00198 /*********************************************************
    00199  **** SCREENSHOT CODE FOR PORTABLE NETWORK GRAPHICS (.PNG)
    00200  *********************************************************/
    00201 #if defined(WITH_PNG)
    00202 #include <png.h>
    00203
    00204 static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
    00205 {
    00206   DEBUG(misc, 0, "[libpng] error: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
    00207   longjmp(png_ptr->jmpbuf, 1);
    00208 }
    00209
    00210 static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
    00211 {
    00212   DEBUG(misc, 1, "[libpng] warning: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
    00213 }
    00214
    00215 static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
    00216 {
    00217   png_color rq[256];
    00218   FILE *f;
    00219   uint i, y, n;
    00220   uint maxlines;
    00221   uint bpp = pixelformat / 8;
    00222   png_structp png_ptr;
    00223   png_infop info_ptr;
    00224
    00225   /* only implemented for 8bit and 32bit images so far. */
    00226   if (pixelformat != 8 && pixelformat != 32) return false;
    00227
    00228   f = fopen(name, "wb");
    00229   if (f == NULL) return false;
    00230
    00231   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (char *)name, png_my_error, png_my_warning);
    00232
    00233   if (png_ptr == NULL) {
    00234     fclose(f);
    00235     return false;
    00236   }
    00237
    00238   info_ptr = png_create_info_struct(png_ptr);
    00239   if (info_ptr == NULL) {
    00240     png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    00241     fclose(f);
    00242     return false;
    00243   }
    00244
    00245   if (setjmp(png_jmpbuf(png_ptr))) {
    00246     png_destroy_write_struct(&png_ptr, &info_ptr);
    00247     fclose(f);
    00248     return false;
    00249   }
    00250
    00251   png_init_io(png_ptr, f);
    00252
    00253   png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
    00254
    00255   png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
    00256     PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    00257
    00258   if (pixelformat == 8) {
    00259     /* convert the palette to the .PNG format. */
    00260     for (i = 0; i != 256; i++) {
    00261       rq[i].red   = palette[i].r;
    00262       rq[i].green = palette[i].g;
    00263       rq[i].blue  = palette[i].b;
    00264     }
    00265
    00266     png_set_PLTE(png_ptr, info_ptr, rq, 256);
    00267   }
    00268
    00269   png_write_info(png_ptr, info_ptr);
    00270   png_set_flush(png_ptr, 512);
    00271
    00272   if (pixelformat == 32) {
    00273     png_color_8 sig_bit;
    00274
    00275     /* Save exact colour/alpha resolution */
    00276     sig_bit.alpha = 0;
    00277     sig_bit.blue  = 8;
    00278     sig_bit.green = 8;
    00279     sig_bit.red   = 8;
    00280     sig_bit.gray  = 8;
    00281     png_set_sBIT(png_ptr, info_ptr, &sig_bit);
    00282
    00283 #if TTD_ENDIAN == TTD_LITTLE_ENDIAN
    00284     png_set_bgr(png_ptr);
    00285     png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
    00286 #else
    00287     png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
    00288 #endif /* TTD_ENDIAN == TTD_LITTLE_ENDIAN */
    00289   }
    00290
    00291   /* use by default 64k temp memory */
    00292   maxlines = Clamp(65536 / w, 16, 128);
    00293
    00294   /* now generate the bitmap bits */
    00295   void *buff = CallocT<uint8>(w * maxlines * bpp); // by default generate 128 lines at a time.
    00296
    00297   y = 0;
    00298   do {
    00299     /* determine # lines to write */
    00300     n = min(h - y, maxlines);
    00301
    00302     /* render the pixels into the buffer */
    00303     callb(userdata, buff, y, w, n);
    00304     y += n;
    00305
    00306     /* write them to png */
    00307     for (i = 0; i != n; i++)
    00308       png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
    00309   } while (y != h);
    00310
    00311   png_write_end(png_ptr, info_ptr);
    00312   png_destroy_write_struct(&png_ptr, &info_ptr);
    00313
    00314   free(buff);
    00315   fclose(f);
    00316   return true;
    00317 }
    00318 #endif /* WITH_PNG */
    00319
    00320
    00321 /*************************************************
    00322  **** SCREENSHOT CODE FOR ZSOFT PAINTBRUSH (.PCX)
    00323  *************************************************/
    00324
    00325 struct PcxHeader {
    00326   byte manufacturer;
    00327   byte version;
    00328   byte rle;
    00329   byte bpp;
    00330   uint32 unused;
    00331   uint16 xmax, ymax;
    00332   uint16 hdpi, vdpi;
    00333   byte pal_small[16 * 3];
    00334   byte reserved;
    00335   byte planes;
    00336   uint16 pitch;
    00337   uint16 cpal;
    00338   uint16 width;
    00339   uint16 height;
    00340   byte filler[54];
    00341 };
    00342 assert_compile(sizeof(PcxHeader) == 128);
    00343
    00344 static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
    00345 {
    00346   FILE *f;
    00347   uint maxlines;
    00348   uint y;
    00349   PcxHeader pcx;
    00350   bool success;
    00351
    00352   if (pixelformat == 32) {
    00353     DEBUG(misc, 0, "Can't convert a 32bpp screenshot to PCX format. Please pick an other format.");
    00354     return false;
    00355   }
    00356   if (pixelformat != 8 || w == 0)
    00357     return false;
    00358
    00359   f = fopen(name, "wb");
    00360   if (f == NULL) return false;
    00361
    00362   memset(&pcx, 0, sizeof(pcx));
    00363
    00364   /* setup pcx header */
    00365   pcx.manufacturer = 10;
    00366   pcx.version = 5;
    00367   pcx.rle = 1;
    00368   pcx.bpp = 8;
    00369   pcx.xmax = TO_LE16(w - 1);
    00370   pcx.ymax = TO_LE16(h - 1);
    00371   pcx.hdpi = TO_LE16(320);
    00372   pcx.vdpi = TO_LE16(320);
    00373
    00374   pcx.planes = 1;
    00375   pcx.cpal = TO_LE16(1);
    00376   pcx.width = pcx.pitch = TO_LE16(w);
    00377   pcx.height = TO_LE16(h);
    00378
    00379   /* write pcx header */
    00380   if (fwrite(&pcx, sizeof(pcx), 1, f) != 1) {
    00381     fclose(f);
    00382     return false;
    00383   }
    00384
    00385   /* use by default 64k temp memory */
    00386   maxlines = Clamp(65536 / w, 16, 128);
    00387
    00388   /* now generate the bitmap bits */
    00389   uint8 *buff = CallocT<uint8>(w * maxlines); // by default generate 128 lines at a time.
    00390
    00391   y = 0;
    00392   do {
    00393     /* determine # lines to write */
    00394     uint n = min(h - y, maxlines);
    00395     uint i;
    00396
    00397     /* render the pixels into the buffer */
    00398     callb(userdata, buff, y, w, n);
    00399     y += n;
    00400
    00401     /* write them to pcx */
    00402     for (i = 0; i != n; i++) {
    00403       const uint8 *bufp = buff + i * w;
    00404       byte runchar = bufp[0];
    00405       uint runcount = 1;
    00406       uint j;
    00407
    00408       /* for each pixel... */
    00409       for (j = 1; j < w; j++) {
    00410         uint8 ch = bufp[j];
    00411
    00412         if (ch != runchar || runcount >= 0x3f) {
    00413           if (runcount > 1 || (runchar & 0xC0) == 0xC0)
    00414             if (fputc(0xC0 | runcount, f) == EOF) {
    00415               free(buff);
    00416               fclose(f);
    00417               return false;
    00418             }
    00419           if (fputc(runchar, f) == EOF) {
    00420             free(buff);
    00421             fclose(f);
    00422             return false;
    00423           }
    00424           runcount = 0;
    00425           runchar = ch;
    00426         }
    00427         runcount++;
    00428       }
    00429
    00430       /* write remaining bytes.. */
    00431       if (runcount > 1 || (runchar & 0xC0) == 0xC0)
    00432         if (fputc(0xC0 | runcount, f) == EOF) {
    00433           free(buff);
    00434           fclose(f);
    00435           return false;
    00436         }
    00437       if (fputc(runchar, f) == EOF) {
    00438         free(buff);
    00439         fclose(f);
    00440         return false;
    00441       }
    00442     }
    00443   } while (y != h);
    00444
    00445   free(buff);
    00446
    00447   /* write 8-bit colour palette */
    00448   if (fputc(12, f) == EOF) {
    00449     fclose(f);
    00450     return false;
    00451   }
    00452
    00453   /* Palette is word-aligned, copy it to a temporary byte array */
    00454   byte tmp[256 * 3];
    00455
    00456   for (uint i = 0; i < 256; i++) {
    00457     tmp[i * 3 + 0] = palette[i].r;
    00458     tmp[i * 3 + 1] = palette[i].g;
    00459     tmp[i * 3 + 2] = palette[i].b;
    00460   }
    00461   success = fwrite(tmp, sizeof(tmp), 1, f) == 1;
    00462
    00463   fclose(f);
    00464
    00465   return success;
    00466 }
    00467
    00468 /*************************************************
    00469  **** GENERIC SCREENSHOT CODE
    00470  *************************************************/
    00471
    00472 static const ScreenshotFormat _screenshot_formats[] = {
    00473 #if defined(WITH_PNG)
    00474   {"PNG", "png", &MakePNGImage},
    00475 #endif
    00476   {"BMP", "bmp", &MakeBmpImage},
    00477   {"PCX", "pcx", &MakePCXImage},
    00478 };
    00479
    00480 void InitializeScreenshotFormats()
    00481 {
    00482   int i, j;
    00483   for (i = 0, j = 0; i != lengthof(_screenshot_formats); i++)
    00484     if (!strcmp(_screenshot_format_name, _screenshot_formats[i].extension)) {
    00485       j = i;
    00486       break;
    00487     }
    00488   _cur_screenshot_format = j;
    00489   _num_screenshot_formats = lengthof(_screenshot_formats);
    00490   current_screenshot_type = SC_NONE;
    00491 }
    00492
    00493 const char *GetScreenshotFormatDesc(int i)
    00494 {
    00495   return _screenshot_formats[i].name;
    00496 }
    00497
    00498 void SetScreenshotFormat(int i)
    00499 {
    00500   _cur_screenshot_format = i;
    00501   strecpy(_screenshot_format_name, _screenshot_formats[i].extension, lastof(_screenshot_format_name));
    00502 }
    00503
    00504 /* screenshot generator that dumps the current video buffer */
    00505 static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
    00506 {
    00507   Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
    00508   void *src = blitter->MoveTo(_screen.dst_ptr, 0, y);
    00509   blitter->CopyImageToBuffer(src, buf, _screen.width, n, pitch);
    00510 }
    00511
    00519 static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
    00520 {
    00521   ViewPort *vp = (ViewPort *)userdata;
    00522   DrawPixelInfo dpi, *old_dpi;
    00523   int wx, left;
    00524
    00525   /* We are no longer rendering to the screen */
    00526   DrawPixelInfo old_screen = _screen;
    00527   bool old_disable_anim = _screen_disable_anim;
    00528
    00529   _screen.dst_ptr = buf;
    00530   _screen.width = pitch;
    00531   _screen.height = n;
    00532   _screen.pitch = pitch;
    00533   _screen_disable_anim = true;
    00534
    00535   old_dpi = _cur_dpi;
    00536   _cur_dpi = &dpi;
    00537
    00538   dpi.dst_ptr = buf;
    00539   dpi.height = n;
    00540   dpi.width = vp->width;
    00541   dpi.pitch = pitch;
    00542   dpi.zoom = ZOOM_LVL_WORLD_SCREENSHOT;
    00543   dpi.left = 0;
    00544   dpi.top = y;
    00545
    00546   /* Render viewport in blocks of 1600 pixels width */
    00547   left = 0;
    00548   while (vp->width - left != 0) {
    00549     wx = min(vp->width - left, 1600);
    00550     left += wx;
    00551
    00552     ViewportDoDraw(vp,
    00553       ScaleByZoom(left - wx - vp->left, vp->zoom) + vp->virtual_left,
    00554       ScaleByZoom(y - vp->top, vp->zoom) + vp->virtual_top,
    00555       ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left,
    00556       ScaleByZoom((y + n) - vp->top, vp->zoom) + vp->virtual_top
    00557     );
    00558   }
    00559
    00560   _cur_dpi = old_dpi;
    00561
    00562   /* Switch back to rendering to the screen */
    00563   _screen = old_screen;
    00564   _screen_disable_anim = old_disable_anim;
    00565 }
    00566
    00567 static char *MakeScreenshotName(const char *ext)
    00568 {
    00569   static char filename[MAX_PATH];
    00570   int serial;
    00571   size_t len;
    00572
    00573   if (_game_mode == GM_EDITOR || _game_mode == GM_MENU || _local_company == COMPANY_SPECTATOR) {
    00574     strecpy(_screenshot_name, "screenshot", lastof(_screenshot_name));
    00575   } else {
    00576     GenerateDefaultSaveName(_screenshot_name, lastof(_screenshot_name));
    00577   }
    00578
    00579   /* Add extension to screenshot file */
    00580   len = strlen(_screenshot_name);
    00581   snprintf(&_screenshot_name[len], lengthof(_screenshot_name) - len, ".%s", ext);
    00582
    00583   for (serial = 1;; serial++) {
    00584     if (snprintf(filename, lengthof(filename), "%s%s", _personal_dir, _screenshot_name) >= (int)lengthof(filename)) {
    00585       /* We need more characters than MAX_PATH -> end with error */
    00586       filename[0] = '\0';
    00587       break;
    00588     }
    00589     if (!FileExists(filename)) break;
    00590     /* If file exists try another one with same name, but just with a higher index */
    00591     snprintf(&_screenshot_name[len], lengthof(_screenshot_name) - len, "#%d.%s", serial, ext);
    00592   }
    00593
    00594   return filename;
    00595 }
    00596
    00597 void SetScreenshotType(ScreenshotType t)
    00598 {
    00599   current_screenshot_type = t;
    00600 }
    00601
    00602 bool IsScreenshotRequested()
    00603 {
    00604   return (current_screenshot_type != SC_NONE);
    00605 }
    00606
    00607 static bool MakeSmallScreenshot()
    00608 {
    00609   const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format;
    00610   return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
    00611 }
    00612
    00613 static bool MakeWorldScreenshot()
    00614 {
    00615   ViewPort vp;
    00616   const ScreenshotFormat *sf;
    00617
    00618   vp.zoom = ZOOM_LVL_WORLD_SCREENSHOT;
    00619   vp.left = 0;
    00620   vp.top = 0;
    00621   vp.virtual_left = -(int)MapMaxX() * TILE_PIXELS;
    00622   vp.virtual_top = 0;
    00623   vp.virtual_width = (MapMaxX() + MapMaxY()) * TILE_PIXELS;
    00624   vp.width = vp.virtual_width;
    00625   vp.virtual_height = (MapMaxX() + MapMaxY()) * TILE_PIXELS >> 1;
    00626   vp.height = vp.virtual_height;
    00627
    00628   sf = _screenshot_formats + _cur_screenshot_format;
    00629   return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
    00630 }
    00631
    00632 bool MakeScreenshot()
    00633 {
    00634   switch (current_screenshot_type) {
    00635     case SC_VIEWPORT:
    00636       UndrawMouseCursor();
    00637       DrawDirtyBlocks();
    00638       current_screenshot_type = SC_NONE;
    00639       return MakeSmallScreenshot();
    00640     case SC_WORLD:
    00641       current_screenshot_type = SC_NONE;
    00642       return MakeWorldScreenshot();
    00643     default: return false;
    00644   }
    00645 }