⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmpdecoder.cpp

📁 Jpeg编解码器的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
         pixel->green = color_table [color].rgbGreen ;
         pixel->blue = color_table [color].rgbBlue ;
      }
    }
  }
  return ;
}

void BmpDecoder::read16BitData (std::istream &strm ,
                                int height, int width,
                                BitmapImage &image,
                                unsigned long redmask, unsigned long greenmask,
                                unsigned long bluemask, unsigned long alphamask)
{
  unsigned long allbits = redmask | greenmask | bluemask | alphamask ;
  if ((allbits & redmask) != redmask || (allbits & greenmask) != greenmask
      || (allbits & bluemask) != bluemask || (allbits & alphamask) != alphamask)
  {
    throw BmpError ("Overlapping component mask") ;
  }

  UBYTE4 redsize, redoffset ;
  UBYTE4 greensize, greenoffset ;
  UBYTE4 bluesize, blueoffset ;
  UBYTE4 alphasize, alphaoffset ;

  FindMask (redmask, redoffset, redsize) ;
  FindMask (greenmask, greenoffset, greensize) ;
  FindMask (bluemask, blueoffset, bluesize) ;
  FindMask (alphamask, alphaoffset, alphasize) ;

  unsigned int physicalrowsize = (sizeof (UBYTE2) * width + 0x3) & ~0x3 ;
  Buffer<UBYTE2> buffer (physicalrowsize / sizeof (UBYTE2)) ;

  // Images with positive heights are stored bottom up. Images with
  // negative height are stored top down.
  if (height > 0)
  {
    for (unsigned int ii = 0 ; ii < height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      // The pixel rows are stored in reverse order.
      unsigned int index = (height - ii - 1) * width ;
      BitmapImage::Pixel *pixel = &image [index] ;
      for (unsigned int jj = 0 ; jj < width ; ++ jj, ++ pixel)
      {
         UBYTE2 color = LittleEndianToSystem (buffer [jj]) ;
         pixel->red   = ((color & redmask) >> (redoffset + redsize - 1)) & 0xFFU ;
         pixel->green = ((color & greenmask) >> (greenoffset + greensize - 1)) & 0xFFU ;
         pixel->blue  = ((color & bluemask) >> (blueoffset + bluesize - 1)) & 0xFFU ;
         pixel->alpha = ((color & alphamask) >> (alphaoffset + alphasize - 1)) & 0xFFU ;
      }
    }
  }
  else
  {
    BitmapImage::Pixel *pixel = &image [0] ;
    for (unsigned int ii = 0 ; ii < - height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      for (unsigned int jj = 0 ; jj < width ; ++ jj, ++ pixel)
      {
         UBYTE2 color = LittleEndianToSystem (buffer [jj]) ;
         pixel->red   = ((color & redmask) >> (redoffset + redsize - 1)) & 0xFFU ;
         pixel->green = ((color & greenmask) >> (greenoffset + greensize - 1)) & 0xFFU ;
         pixel->blue  = ((color & bluemask) >> (blueoffset + bluesize - 1)) & 0xFFU ;
         pixel->alpha = ((color & alphamask) >> (alphaoffset + alphasize - 1)) & 0xFFU ;
      }
    }
  }
  return ;
}

void BmpDecoder::read24BitData (std::istream &strm,
                                int height, int width,
                                BitmapImage &image)
{
  // This is is rowwidth rounded up to the nearest 4 bytes.
  unsigned int physicalrowsize = (3 * width + 0x3) & ~0x3 ;

  Buffer<UBYTE1> buffer (physicalrowsize) ;

  // Images with positive heights are stored bottom up. Images with
  // negative height are stored top down.
  if (height > 0)
  {
    for (unsigned int ii = 0 ; ii < height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      // The pixel rows are stored in reverse order.
      unsigned int index = (height - ii - 1) * width ;
      BitmapImage::Pixel *pixel = &image [index] ;
      for (unsigned int jj = 0, kk = 0  ; jj < width ; ++ jj, ++ pixel)
      {
         pixel->blue = buffer [kk] ; ++ kk ;
         pixel->green = buffer [kk] ; ++ kk ;
         pixel->red = buffer [kk] ; ++ kk ;
      }
    }
  }
  else
  {
    BitmapImage::Pixel *pixel = &image [0] ;
    for (unsigned int ii = 0 ; ii < - height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      for (unsigned int jj = 0, kk = 0  ; jj < width ; ++ jj, ++ pixel)
      {
         pixel->blue = buffer [kk] ; ++ kk ;
         pixel->green = buffer [kk] ; ++ kk ;
         pixel->red = buffer [kk] ; ++ kk ;
      }
    }
  }
  return ;
}
void BmpDecoder::read32BitData (std::istream &strm,
                                int height, int width,
                                BitmapImage &image,
                                unsigned long redmask,
                                unsigned long greenmask,
                                unsigned long bluemask,
                                unsigned long alphamask)
{
  unsigned long allbits = redmask | greenmask | bluemask | alphamask ;
  if ((allbits & redmask) != redmask || (allbits & greenmask) != greenmask
      || (allbits & bluemask) != bluemask || (allbits & alphamask) != alphamask)
  {
    throw BmpError ("Overlapping component mask") ;
  }

  UBYTE4 redsize, redoffset ;
  UBYTE4 greensize, greenoffset ;
  UBYTE4 bluesize, blueoffset ;
  UBYTE4 alphasize, alphaoffset ;

  FindMask (redmask, redoffset, redsize) ;
  FindMask (greenmask, greenoffset, greensize) ;
  FindMask (bluemask, blueoffset, bluesize) ;
  FindMask (alphamask, alphaoffset, alphasize) ;

  unsigned int physicalrowsize = sizeof (UBYTE4) * width ;
  Buffer<UBYTE4> buffer (width) ;

  // Images with positive heights are stored bottom up. Images with
  // negative height are stored top down.
  if (height > 0)
  {
    for (unsigned int ii = 0 ; ii < height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      // The pixel rows are stored in reverse order.
      unsigned int index = (height - ii - 1) * width ;
      BitmapImage::Pixel *pixel = &image [index] ;
      for (unsigned int jj = 0 ; jj < width ; ++ jj, ++ pixel)
      {
         UBYTE4 color = LittleEndianToSystem (buffer [jj]) ;
         pixel->red   = ((color & redmask) >> (redoffset + redsize - CHAR_BIT)) & 0xFFU ;
         pixel->green = ((color & greenmask) >> (greenoffset + greensize - CHAR_BIT)) & 0xFFU ;
         pixel->blue  = ((color & bluemask) >> (blueoffset + bluesize - CHAR_BIT)) & 0xFFU ;
         pixel->alpha = ((color & alphamask) >> (alphaoffset + alphasize - CHAR_BIT)) & 0xFFU ;
      }
    }
  }
  else
  {
    BitmapImage::Pixel *pixel = &image [0] ;
    for (unsigned int ii = 0 ; ii < - height ; ++ ii)
    {
      callProgressFunction (ii * 100 / height) ;
      strm.read (reinterpret_cast<char *>(&buffer [0]), physicalrowsize) ;
      if (strm.gcount () != physicalrowsize)
        throw BmpError ("Premature End of Stream") ;

      for (unsigned int jj = 0 ; jj < width ; ++ jj, ++ pixel)
      {
         UBYTE4 color = LittleEndianToSystem (buffer [jj]) ;
         pixel->red   = ((color & redmask) >> (redoffset + redsize - CHAR_BIT)) & 0xFFU ;
         pixel->green = ((color & greenmask) >> (greenoffset + greensize - CHAR_BIT)) & 0xFFU ;
         pixel->blue  = ((color & bluemask) >> (blueoffset + bluesize - CHAR_BIT)) & 0xFFU ;
         pixel->alpha = ((color & alphamask) >> (alphaoffset + alphasize - CHAR_BIT)) & 0xFFU ;
      }
    }
  }
  return ;

}

unsigned int BmpDecoder::readOs2ColorTable (std::istream &strm,
                                    unsigned int colorcount)
{
  for (unsigned int ii = 0 ; ii < colorcount ; ++ ii)
  {
    RGBTRIPLE color ;
    strm.read (reinterpret_cast<char *>(&color), sizeof (color)) ;
    color_table [ii].rgbRed   = color.rgbtRed ;
    color_table [ii].rgbBlue  = color.rgbtBlue ;
    color_table [ii].rgbGreen = color.rgbtGreen ;
  }
  return colorcount * sizeof (RGBTRIPLE) ;
}

unsigned int BmpDecoder::readColorTable (std::istream &strm,
                                          unsigned int colorcount)
{
  unsigned int bytes = sizeof (RGBQUAD) * colorcount ;
  strm.read (reinterpret_cast<char *>(&color_table [0]), bytes) ;
  return bytes ;
}

void BmpDecoder::readRle4 (std::istream &strm , int height, int width, BitmapImage &image)
{
  if (height < 0)
    throw BmpError ("Negative height not allowed in an RLE image") ;

  // The mechanism here is the same as for BI_RLE8 with two
  // exceptions. Here we are dealing with 4-bit nibbles rather
  // than whole bytes. This results in some extra work. In
  // addition, the coding of runs includes two color values.

  unsigned int row =  - (height + 1) ;
  BitmapImage::Pixel *pixel = &image [row * width] ;
  unsigned int col = 0 ;
  bool done = false ;
  while (! strm.eof () && ! done)
  {
    callProgressFunction ((height - row - 1) * 100 / height) ;

    struct
    {
      UBYTE1 count ;
      UBYTE1 command ;
    } opcode ;

    strm.read (reinterpret_cast<char *>(&opcode), sizeof (opcode)) ;
    if (opcode.count == 0)
    {
      switch (opcode.command)
      {
      case 0:    // Advance to next pixel row
        -- row ;
        pixel = &image [row * width] ;
        col = 0 ;
        break ;
      case 1:    // Image complete
        done = true ;
        break ;
      case 2:   // Move to relative location the image.
        {
          UBYTE1 dx ;
          UBYTE1 dy ;
          strm.read (reinterpret_cast<char *>(&dx), sizeof (dx)) ;
          strm.read (reinterpret_cast<char *>(&dy), sizeof (dy)) ;
          col += dx ;
          row -= dy ;
          pixel = &image [row * width] ;
        }
        break ;
      default:
        {
          UBYTE1 data ;
   		    UBYTE1 hi ;
          UBYTE1 lo ;
          if (row >= height || col + opcode.command > width)
            throw BmpError ("Corrupt Data") ;
          for (unsigned int ii = 0 ; ii < opcode.command ; ++ ii)
          {
            if ((ii & 1) == 0)
            {
              strm.read (reinterpret_cast<char *>(&data), sizeof (data)) ;
              lo = data & 0xF ;
              hi = (data & 0xF0) >> 4 ;
            }
            if ((ii & 1) == 0)
            {
              pixel [col].red = color_table [hi].rgbRed ;
              pixel [col].green = color_table [hi].rgbGreen ;
              pixel [col].blue = color_table [hi].rgbBlue ;
            }
            else
            {
              pixel [col].red = color_table [lo].rgbRed ;
              pixel [col].green = color_table [lo].rgbGreen ;
              pixel [col].blue = color_table [lo].rgbBlue ;
            }
            ++ col ;
          }
          // If the number of bytes used in this instruction
          // is odd then there is a padding byte.
          switch (opcode.command & 0x3)
          {
          case 1: case 2:
            strm.read (reinterpret_cast<char *>(&data), sizeof (data)) ;
            break ;
          }
        }
        break ;
      }
    }
    else
    {
      // Process a run of the same color value pairs.
      UBYTE1 hi = opcode.command >> 4 ;
      UBYTE1 lo = opcode.command & 0xF ;
      if (row >= height || col + opcode.count > width)
        throw BmpError ("Corrupt Data") ;

      for (unsigned int ii = 0 ; ii < opcode.count ; ++ ii)
      {
        if ((ii & 1) == 0)
        {
          pixel [col].red = color_table [hi].rgbRed ;
          pixel [col].green = color_table [hi].rgbGreen ;
          pixel [col].blue = color_table [hi].rgbBlue ;
        }
        else
        {
          pixel [col].red = color_table [lo].rgbRed ;
          pixel [col].green = color_table [lo].rgbGreen ;
          pixel [col].blue = color_table [lo].rgbBlue ;
        }
        ++ col ;
      }
    }
  }
  if (! done)
    throw BmpError ("Corrupt Data") ;
  return ;
}

void BmpDecoder::readRle8 (std::istream &strm , int height, int width, BitmapImage &image)
{
  if (height < 0)
    throw BmpError ("Negative height not allowed in an RLE image") ;

  unsigned int row = - (height + 1) ;  // Current row
  unsigned int col = 0 ;           // Current column
  BitmapImage::Pixel *pixel = &image [row * width] ;
  bool done = false ;

  while (! strm.eof () && ! done)
  {
    callProgressFunction ((height - row - 1) * 100 / height) ;

    // Structure for reading RLE commands.
    struct
    {
      UBYTE1 count ;
      UBYTE1 command ;
    } opcode ;

    strm.read (reinterpret_cast<char *>(&opcode), sizeof (opcode)) ;
    if (opcode.count == 0)
    {
      // A byte count of zero means that this is a special
      // instruction.
      switch (opcode.command)
      {
      case 0: // 0 => Move to next row
        -- row ;
        col = 0 ;
        pixel = &image [row * width] ;
        break ;
      case 1: // 1 => Image is finished
        done = true ;
        break ;
      case 2: // 2 => Move to a new relative position.
        {
          // Read the relative position.
          UBYTE1 dx ;
          UBYTE1 dy ;
          strm.read (reinterpret_cast<char *>(&dx), sizeof (dx)) ;
          strm.read (reinterpret_cast<char *>(&dy), sizeof (dy)) ;
          col += dx ;
          row -= dy ;
          pixel = &image [row * width] ;
        }
        break ;
      default:
        {
          // Store absolute data. The command code is the
          // number of absolute bytes to store.
          if (row >= height || col + opcode.command > width)
              throw BmpError ("Corrupt Data") ;
          UBYTE1 data ;
          for (unsigned int ii = 0 ; ii < opcode.command ; ++ ii)
          {
            strm.read (reinterpret_cast<char *>(&data), sizeof (data)) ;
            pixel [col].red = color_table [data].rgbRed ;
            pixel [col].green = color_table [data].rgbGreen ;
            pixel [col].blue = color_table [data].rgbBlue ;
            ++ col ;
          }
          // An odd number of bytes is followed by a pad byte.
          if ((opcode.command & 1) != 0)
            strm.read (reinterpret_cast<char *>(&data), sizeof (data)) ;
        }
        break ;
      }
    }
    else
    {
      // Store a run of the same color value.
      if (row >= height || col + opcode.count > width)
        throw BmpError ("Corrupt Data") ;
      for (unsigned int ii = 0 ; ii < opcode.count ; ++ ii)
      {
        pixel [col].red = color_table [opcode.command].rgbRed ;
        pixel [col].green = color_table [opcode.command].rgbGreen ;
        pixel [col].blue = color_table [opcode.command].rgbBlue ;
        ++ col ;
      }
    }
  }
  if (! done)
    throw BmpError ("Corrupt Data") ;

  return ;
}

} // End Namespace Colosseum

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -