Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

imagedec.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/graphics/imagedec.cpp $
 * $Id: imagedec.cpp 30944 2008-02-23 22:50:18Z sev $
 */

#include "graphics/imagedec.h"

#include "common/system.h"
#include "common/file.h"

namespace Graphics {
//
// BMP Decoder
//
class BMPDecoder : public ImageDecoder {
public:
      BMPDecoder() {}
      virtual ~BMPDecoder() {}

      bool decodeable(Common::SeekableReadStream &stream);
      Surface *decodeImage(Common::SeekableReadStream &stream);

      struct BitmapHeader {
            uint16 type;
            uint32 size;
            uint16 res1;
            uint16 res2;
            uint32 imageOffset;
      };

      struct InfoHeader {
            uint32 size;
            uint32 width;
            uint32 height;
            uint16 planes;
            uint16 bitsPerPixel;
            uint32 compression;
            uint32 imageSize;
            uint32 pixelsPerMeterX;
            uint32 pixelsPerMeterY;
            uint32 colorsUsed;
            uint32 colorsImportant;
      };
};

bool BMPDecoder::decodeable(Common::SeekableReadStream &stream) {
      BitmapHeader header;
      stream.seek(0);
      header.type = stream.readUint16BE();
      header.size = stream.readUint32LE();

      // TODO: maybe improve this detection
      if (header.size == 0 || header.type != 'BM')
            return false;

      return true;
}

Surface *BMPDecoder::decodeImage(Common::SeekableReadStream &stream) {
      if (!decodeable(stream)) {
            return 0;
      }

      BitmapHeader header;
      InfoHeader info;

      stream.seek(0);
      header.type = stream.readUint16BE();
      header.size = stream.readUint32LE();
      header.res1 = stream.readUint16LE();
      header.res2 = stream.readUint16LE();
      header.imageOffset = stream.readUint32LE();

      if (header.size == 0 || header.type != 'BM') {
            stream.seek(0);
            return 0;
      }

      info.size = stream.readUint32LE();
      info.width = stream.readUint32LE();
      info.height = stream.readUint32LE();
      info.planes = stream.readUint16LE();
      info.bitsPerPixel = stream.readUint16LE();
      info.compression = stream.readUint32LE();
      info.imageSize = stream.readUint32LE();
      info.pixelsPerMeterX = stream.readUint32LE();
      info.pixelsPerMeterY = stream.readUint32LE();
      info.colorsUsed = stream.readUint32LE();
      info.colorsImportant = stream.readUint32LE();

      stream.seek(header.imageOffset);

      if (info.bitsPerPixel != 24) {
            stream.seek(0);
            return 0;
      }

      uint8 r = 0, g = 0, b = 0;
      Surface *newSurf = new Surface;
      assert(newSurf);
      newSurf->create(info.width, info.height, sizeof(OverlayColor));
      assert(newSurf->pixels);
      OverlayColor *curPixel = (OverlayColor*)newSurf->pixels + (newSurf->h-1) * newSurf->w;
      int pitchAdd = info.width % 4;
      for (int i = 0; i < newSurf->h; ++i) {
            for (int i2 = 0; i2 < newSurf->w; ++i2) {
                  b = stream.readByte();
                  g = stream.readByte();
                  r = stream.readByte();
                  *curPixel = g_system->RGBToColor(r, g, b);
                  ++curPixel;
            }
            stream.seek(pitchAdd, SEEK_CUR);
            curPixel -= newSurf->w*2;
      }

      stream.seek(0);
      return newSurf;
}

#pragma mark -

Surface *ImageDecoder::loadFile(const Common::String &name) {
      Surface *newSurf = 0;

      Common::File imageFile;
      if (imageFile.open(name)) {
            newSurf = loadFile(imageFile);
      }

      return newSurf;
}

Surface *ImageDecoder::loadFile(Common::SeekableReadStream &stream) {
      // TODO: implement support for bzipped memory

      // FIXME: this is not a very nice solution but it should work
      // for the moment, we should use a different way to get all
      // decoders
      static BMPDecoder bmpDecoder;
      static ImageDecoder *decoderList[] = {
            &bmpDecoder,                  // for uncompressed .BMP files
            0
      };

      ImageDecoder *decoder = 0;
      for (int i = 0; decoderList[i] != 0; ++i) {
            if (decoderList[i]->decodeable(stream)) {
                  decoder = decoderList[i];
                  break;
            }
      }

      if (!decoder)
            return 0;

      return decoder->decodeImage(stream);
}
} // end of namespace Graphics

Generated by  Doxygen 1.6.0   Back to index