コード例 #1
0
ファイル: OpenTGA.cpp プロジェクト: siyinyang/EyeRobot
  Image* OpenTGA(File* file) {
    COR_GUARD("OpenTGA");

    // read header
    byte header[18];
    if (file->read(header, 18) != 18) {
      return 0;
    }

    // decode header
    int id_length        = header[0];
    int cm_type          = header[1];
    int image_type       = header[2];
    //int cm_first         = read16_le(header + 3);
    int cm_length        = read16_le(header + 5);
    int cm_entry_size    = header[7];  // in bits
    //int x_origin         = read16_le(header + 8);
    //int y_origin         = read16_le(header + 10);
    int width            = read16_le(header + 12);
    int height           = read16_le(header + 14);
    int pixel_depth      = header[16];
    int image_descriptor = header[17];
    
    bool mirrored = (image_descriptor & (1 << 4)) != 0;  // left-to-right?
    bool flipped  = (image_descriptor & (1 << 5)) == 0;  // bottom-to-top?

    /*
     * image types
     * 0  = no image data
     * 1  = uncompressed, color-mapped
     * 2  = uncompressed, true-color
     * 3  = uncompressed, black and white
     * 9  = RLE, color-mapped
     * 10 = RLE, true-color
     * 11 = RLE, black and white
     */

    // make sure we support the image
    if (image_type != 2 || (pixel_depth != 24 && pixel_depth != 32)) {
      return 0;
    }

    // skip image id
    byte unused[255];
    if (file->read(unused, id_length) != id_length) {
      return 0;
    }

    // skip color map
    if (cm_type != 0) {
      // allocate color map
      int cm_entry_bytes = (cm_entry_size + 7) / 8;
      int cm_size = cm_entry_bytes * cm_length;
      auto_array<byte> color_map(new byte[cm_size]);
      if (file->read(color_map, cm_size) != cm_size) {
        return 0;
      }
    }

    // read image data
    PixelFormat format;
    auto_array<byte> pixels;
    if (pixel_depth == 24) {

      COR_LOG("24-bit image");

      format = PF_B8G8R8;
      int image_size = width * height * 3;
      pixels = new byte[image_size];
      if (file->read(pixels, image_size) != image_size) {
        return 0;
      }

    } else if (pixel_depth == 32) {

      COR_LOG("32-bit image");

      format = PF_B8G8R8A8;
      int image_size = width * height * 4;
      pixels = new byte[image_size];
      if (file->read(pixels, image_size) != image_size) {
        return 0;
      }

    } else {
      return 0;
    }

    // reverse each row
    if (mirrored) {
      COR_LOG("Image is mirrored");

      const int bpp = pixel_depth / 8;  // bytes per pixel
      for (int y = 0; y < height; ++y) {

	// points to the first pixel of the row
	byte* start = pixels.get() + y * width * bpp;
	// points to the last pixel of the row
	byte* end   = start + (width - 1) * bpp;

	while (start < end) {
	  for (int b = 0; b < bpp; ++b) {
	    std::swap(start[b], end[b]);
	  }
	  start += bpp;
	  end   -= bpp;
	}
      }
    }

    // reverse rows as a whole
    if (flipped) {
      COR_LOG("Image is flipped");

      const int bpp = pixel_depth / 8;  // bytes per pixel
      const int row_size = width * bpp;
      auto_array<byte> temp(new byte[row_size]);  // for the swap

      // points to the beginning of the first row
      byte* start = pixels.get();

      // points to the beginning of the last row
      byte* end   = start + (height - 1) * width * bpp;

      while (start < end) {
	memcpy(temp.get(), start,      row_size);
	memcpy(start,      end,        row_size);
	memcpy(end,        temp.get(), row_size);

	start += row_size;
	end   -= row_size;
      }
    }

    return new SimpleImage(width, height, format, pixels.release());
  }
コード例 #2
0
ファイル: _bmp.cpp プロジェクト: DavidBrear/imread
std::auto_ptr<Image> BMPFormat::read(byte_source* src, ImageFactory* factory, const options_map&) {
    char magick[2];
    if (src->read(reinterpret_cast<byte*>(magick), 2) != 2) {
        throw CannotReadError("imread.bmp: File is empty");
    }
    if (magick[0] != 'B' || magick[1] != 'M') {
        throw CannotReadError("imread.bmp: Magick number not matched (this might not be a BMP file)");
    }
    const uint32_t size = read32_le(*src);
    (void)size;
    (void)read16_le(*src);
    (void)read16_le(*src);
    const uint32_t offset = read32_le(*src);
    const uint32_t header_size = read32_le(*src);
    (void)header_size;
    const uint32_t width = read32_le(*src);
    const uint32_t height = read32_le(*src);
    const uint16_t planes = read16_le(*src);
    if (planes != 1){
        throw NotImplementedError("imread.bmp: planes should be 1");
    }
    const uint16_t bitsppixel = read16_le(*src);
    const uint32_t compression = read32_le(*src);
    if (compression != 0) {
        throw NotImplementedError("imread.bmp: Only uncompressed bitmaps are supported");
    }
    const uint32_t imsize = read32_le(*src);
    (void)imsize;
    const uint32_t hres = read32_le(*src);
    (void)hres;
    const uint32_t vres = read32_le(*src);
    (void)vres;
    const uint32_t n_colours = read32_le(*src);
    const uint32_t importantcolours = read32_le(*src);
    (void)importantcolours;

    if (bitsppixel != 8 && bitsppixel != 16 && bitsppixel != 24) {
        std::ostringstream out;
        out << "imread.bmp: Bits per pixel is " << bitsppixel << ". Only 8, 16, or 24 supported.";
        throw CannotReadError(out.str());
    }
    const int depth = (bitsppixel == 16 ? -1 : 3);
    const int nbits = (bitsppixel == 16 ? 16 : 8);
    std::auto_ptr<Image> output(factory->create(nbits, height, width, depth));

    std::vector<byte> color_table;
    if (bitsppixel <= 8) {
        const uint32_t table_size = (n_colours == 0 ? pow2(bitsppixel) : n_colours);
        color_table.resize(table_size*4);
        src->read_check(&color_table[0], table_size*4);
    }

    src->seek_absolute(offset);
    const int bytes_per_row = width * (bitsppixel/8);
    const int padding = (4 - (bytes_per_row % 4)) % 4;
    byte buf[4];
    for (unsigned int r = 0; r != height; ++r) {
        byte* rowp = output->rowp_as<byte>(height-r-1);
        src->read_check(rowp, bytes_per_row);

        if (bitsppixel == 24) flippixels(rowp, width);
        else if (!color_table.empty()) color_expand(color_table, rowp, width);

        if (src->read(buf, padding) != unsigned(padding) && r != (height - 1)) {
            throw CannotReadError("File ended prematurely");
        }
    }
    return output;
}
コード例 #3
0
ファイル: OpenBMP.cpp プロジェクト: Aetherdyne/glintercept
  bool ReadInfoHeader(File* file, Header& h) {

    const int HEADER_READ_SIZE = 24;

    // read the only part of the header we need
    byte header[HEADER_READ_SIZE];
    if (file->read(header, HEADER_READ_SIZE) != HEADER_READ_SIZE) {
      return false;
    }

    int size = read32_le(header + 0);
    int width;
    int height;
    int planes;
    int bpp;
    int compression;
    int image_size;

    if (size < 40) {  // assume OS/2 bitmap
      if (size < 12) {
        return false;
      }

      h.os2 = true;
      width  = read16_le(header + 4);
      height = read16_le(header + 6);
      planes = read16_le(header + 8);
      bpp    = read16_le(header + 10);
      compression = 0;
      image_size = 0;
      
    } else {

      h.os2 = false;
      width       = read32_le(header + 4);
      height      = read32_le(header + 8);
      planes      = read16_le(header + 12);
      bpp         = read16_le(header + 14);
      compression = read32_le(header + 16);
      image_size  = read32_le(header + 20);

    }
    
    // sanity check the info header
    if (planes != 1) {
      return false;
    }

    // adjust image_size
    // (if compression == 0 or 3, manually calculate image size)
    int line_size = 0;
    if (compression == 0 || compression == 3) {
      line_size = (width * bpp + 7) / 8;
      line_size = (line_size + 3) / 4 * 4;  // 32-bit-aligned
      image_size = line_size * height;
    }

    h.width       = width;
    h.height      = height;
    h.bpp         = bpp;
    h.compression = compression;
    h.pitch       = line_size;
    h.image_size  = image_size;

    // jump forward (backward in the OS/2 case :) to the palette data
    file->seek(size - HEADER_READ_SIZE, File::CURRENT);

    return true;
  }