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

📄 jpgencoder.~cpp

📁 Jpeg编解码器的源代码
💻 ~CPP
📖 第 1 页 / 共 5 页
字号:
//
// JPEG编码库
//
// 标题: JpegEncoder类实现
//
// 修改:
//
//   10-January-1999 Changed to use predefined quantization tables
//                   rather than tables scaled from the ones in the
//                   JPEG standard.
//
#include <math.h>
#include <string>
#include <cerrno>
#include "jpgencoder.h"
#include "bitmapimage.h"
#include "jfif.h"
#include "jpgencoderquantization.h"
#include "jpghuffmanencoder.h"       
#include "jpgoutputstream.h"  
#include "jpgoutputfilestream.h"
#include "jpgqtbls.h"

using namespace std ;
using namespace ColosseumPrivate ;

//量化表(亮度)
const unsigned int luminance_quantization_tables [][JPEGSAMPLESIZE] =
{
QTABLEWORST,
QTABLEDODQ1,
QTABLEDODQ2,
QTABLENIMAQ1,
QTABLEJPEGL1,
QTABLENIMAQ2,
QTABLEJPEGL2,
QTABLENIMAQ3,
QTABLEDODQ3,
QTABLEDODQ4,
QTABLENIMAQ4,
QTABLEBEST
} ;
//量化表(色度)
const unsigned int chrominance_quantization_tables [][JPEGSAMPLESIZE] =
{
QTABLEWORST,
QTABLENIMADOWNSAMPLE,
QTABLEJPEGC1,
QTABLEJPEGC2,
QTABLEBEST
} ;

namespace Colosseum
{
//
//  描述:
//
//    类缺省构造函数
//
JpegEncoder::JpegEncoder ()
{
  initialize () ;
  return ;
}

//
//  描述:
//
//    类复制构造函数
//
JpegEncoder::JpegEncoder (const JpegEncoder &source)
{
  initialize () ;
  doCopy (source) ;
  return ;
}

//
//  描述:
//
//    类析构函数
//
JpegEncoder::~JpegEncoder ()
{
  delete [] ac_tables ; ac_tables = 0 ;
  delete [] dc_tables ; dc_tables = 0 ;
  delete [] quantization_tables ;
  quantization_tables = 0 ;
  return ;
}
//
//  描述:
//
//    类赋值操作符
//
JpegEncoder &JpegEncoder::operator=(const JpegEncoder &source)
{
  if (&source != this)
    doCopy (source) ;
  return *this ;
}
//
//  描述:
//
//    Class copy function. This function gets called from the
//    copy constructor and assignment operator.  The only thing
//    we copy are the use settable parameters.
//
void JpegEncoder::doCopy (const JpegEncoder &source)
{
  //可设定的参数
  gray_scale = source.gray_scale ;
  rows_per_restart = source.rows_per_restart ;
  comment_string = source.comment_string ;
  image_quality = source.image_quality ;
  progressive_mode = source.progressive_mode ;
  //扫描线的复制
  for (unsigned int ii = 0 ; ii < MAXSCANS ; ++ ii)
    image_scans [ii] = source.image_scans [ii] ;

  BitmapImageCoder::operator=(source) ;
  //量化表的复制
  memcpy (quantization_table_assignments,
          source.quantization_table_assignments,      
          sizeof (quantization_table_assignments)) ;
  memcpy (quantization_tables,
          source.quantization_tables,
          sizeof (quantization_tables)) ;
  return ;
}
//
//  描述:
//
//    将一幅图像写到 the output stream.
//
//  Parameters:
//    strm:   The output stream to write the image to. This most be opened in
//            binary mode
//    image:  The image to output.
//
void JpegEncoder::writeImage (JpegOutputStream &outputstream, const BitmapImage &image)
{
  //图像的三个成分
  image_components [YCOMPONENT].setOutputStream (outputstream) ;
  image_components [CBCOMPONENT].setOutputStream (outputstream) ;
  image_components [CRCOMPONENT].setOutputStream (outputstream) ;

  //使用
  for (unsigned int ii = 0 ; ii < JPEGMAXQUANTIZATIONTABLES ; ++ ii)
    quantization_tables [ii].isUsed (false) ;

  if (gray_scale)
  {
    quantization_tables [quantization_table_assignments [YCOMPONENT]].isUsed (true) ;
  }
  else
  {
    quantization_tables [quantization_table_assignments [YCOMPONENT]].isUsed (true) ;
    quantization_tables [quantization_table_assignments [CBCOMPONENT]].isUsed (true) ;
    quantization_tables [quantization_table_assignments [CRCOMPONENT]].isUsed (true) ;
  }
  //?
  BILLSELLSPOOP
  for (unsigned int ii = 0 ; ii < JPEGMAXQUANTIZATIONTABLES ; ++ ii)
  {
    if (quantization_tables [ii].isUsed ())
    {
      quantization_tables [ii].buildScaledTables () ;
    }
  }
  ENDBILLSELLSPOOP
  //高、宽
  frame_height = image.getHeight () ;
  frame_width = image.getWidth () ;

  // Find the MCU size and maximum sampling frequencies.
  calculateMcuDimensions () ;

  // Validate Parameters. If there is an error this function will throw
  // an exception.
  validateParameters () ;

  countPassesForProgressReporting () ;

  // Write the image header.
  outputMarker (outputstream, SOI) ;
  outputMarker (outputstream, APP0) ;
  outputJfifHeader (outputstream) ;

  if (comment_string != "")
    printComment (outputstream, comment_string) ;

  printComment (outputstream, "Created using the Colosseum Builders JPEG library") ;

  if (progressive_mode)
    printProgressiveFrame (outputstream, image) ;
  else
    printSequentialFrame (outputstream, image) ;

  outputMarker (outputstream, EOI) ;

  // Make sure that we are not holding on to any memory we do not
  // need any more.
  image_components [YCOMPONENT].freeDynamicStorage () ;
  image_components [CBCOMPONENT].freeDynamicStorage () ;
  image_components [CRCOMPONENT].freeDynamicStorage () ;

  return ;
}
//
//  描述:
//
//    Class Initialization function. This function is intended to be
//    called from constructors.
//
void JpegEncoder::initialize ()
{
  //Huffma表初始化
  dc_tables = new JpegHuffmanEncoder [2] ;
  ac_tables = new JpegHuffmanEncoder [2] ;
  //量化表初始化
  quantization_tables = new JpegEncoderQuantizationTable [JPEGMAXQUANTIZATIONTABLES] ;
  //扫描
  memset (image_scans, 0, sizeof (image_scans)) ;
  image_scans [0].component_mask = (1<<YCOMPONENT)
                                 |(1<<CBCOMPONENT)
                                 |(1<<CRCOMPONENT) ;
  //属性初始化
  progressive_mode = false ;
  setQuality (75) ;
  progress_function = 0 ;
  progress_data = 0 ;
  restart_interval = 0 ;
  rows_per_restart = 0 ;
  gray_scale = false ;

  for (unsigned int ii = 0 ; ii < MAXCOMPONENTS ; ++ ii)
  {
    image_components [ii].setHorizontalFrequency (1) ;
    image_components [ii].setVerticalFrequency (1) ;
  }
  quantization_table_assignments [YCOMPONENT] = 0 ;
  quantization_table_assignments [CBCOMPONENT] = 1 ;
  quantization_table_assignments [CRCOMPONENT] = 1 ;


  image_components [YCOMPONENT].setHuffmanTables (dc_tables [0],
                                                  ac_tables [0]) ;
  image_components [CBCOMPONENT].setHuffmanTables (dc_tables [1],
                                                   ac_tables [1]) ;
  image_components [CRCOMPONENT].setHuffmanTables (dc_tables [1],
                                                   ac_tables [1]) ;

  image_components [YCOMPONENT].setQuantizationTable (
      quantization_tables [quantization_table_assignments [YCOMPONENT]]) ; ;
  image_components [CBCOMPONENT].setQuantizationTable (
      quantization_tables [quantization_table_assignments [CBCOMPONENT]]) ; ;
  image_components [CRCOMPONENT].setQuantizationTable (
      quantization_tables [quantization_table_assignments [CRCOMPONENT]]) ; ;

  return ;
}

//  描述:
//  This function writes a marker to the output stream.
//
//  Parameters:
//    marker: The marker to be written to the output stream
//
void JpegEncoder::outputMarker (JpegOutputStream &outputstream, 
                                ColosseumPrivate::JpegMarker marker)
{
  outputstream.writeByte (SOB) ;
  outputstream.writeByte (marker) ;
  return ;
}

//
//  描述:
//
//    This function validates the user-set output parameters. If an error is
//    detected an EJpegBadOutputParameter exception is thrown.
//

void JpegEncoder::validateParameters ()
{
  const int ALL = (1<<YCOMPONENT)|(1<<CBCOMPONENT)|(1<<CRCOMPONENT) ;
  // Ensure we do not have fractional sampling of pixels.
  if (! gray_scale)
  {
    if (image_components [YCOMPONENT].getHorizontalFrequency () == 3
        || image_components [CBCOMPONENT].getHorizontalFrequency () == 3
        || image_components [CRCOMPONENT].getHorizontalFrequency () == 3)
    {
      if (image_components [YCOMPONENT].getHorizontalFrequency () == 2
          || image_components [YCOMPONENT].getHorizontalFrequency () == 4
          || image_components [CBCOMPONENT].getHorizontalFrequency () == 2
          || image_components [CBCOMPONENT].getHorizontalFrequency () == 4
          || image_components [CRCOMPONENT].getHorizontalFrequency () == 2
          || image_components [CRCOMPONENT].getHorizontalFrequency () == 4)
      {
        throw JpegError ("Fractional Horizontal Sampling") ;
      }
    }

    if (image_components [YCOMPONENT].getVerticalFrequency () == 3
        || image_components [CBCOMPONENT].getVerticalFrequency () == 3
        || image_components [CRCOMPONENT].getVerticalFrequency () == 3)
    {
      if (image_components [YCOMPONENT].getVerticalFrequency () == 2
          || image_components [YCOMPONENT].getVerticalFrequency () == 4
          || image_components [CBCOMPONENT].getVerticalFrequency () == 2
          || image_components [CBCOMPONENT].getVerticalFrequency () == 4
          || image_components [CRCOMPONENT].getVerticalFrequency () == 2
          || image_components [CRCOMPONENT].getVerticalFrequency () == 4)
      {
        throw JpegError ("Fractional Vertical Sampling") ;
      }
    }
  }

  if (progressive_mode)
  {
    // For a progressive scan the following rules apply
    //
    // o The spectral selection start can be zero if and only if
    // the spectral selection end is zero.
    //
    // o For each component the zero spectral selection start must occur
    // before any other.
    //
    // o If the spectral selection start is not zero there may only be
    // one component in a scan.
    //
    // o The entire spectral range must be specified for each component.
    //
    // o There can be no overlapping spectral ranges in scans.
    //
    int lasty = -1 ;
    int lastcb = -1 ;
    int lastcr = -1 ;

    if (gray_scale)
    {
      // For a grayscale image the Cb and Cr components are not used.
      lastcb = 63 ;
      lastcr = 63 ;
    }

    for (scan_count = 0 ; scan_count < MAXSCANS ; ++ scan_count)
    {
      if (lasty == 63 && lastcb == 63 && lastcr == 63)
        break ;

      if (image_scans [scan_count].component_mask == 0)
        throw JpegError ("Scan contains no components") ;

      if (image_scans [scan_count].successive_approximation
          > JPEGMAXSUCCESSIVAPPROXIMATION)
      {
        throw JpegError ("Successive Approximation too large") ;
      }

      image_scans [scan_count].successive_approximation_low =
        image_scans [scan_count].successive_approximation ;
      image_scans [scan_count].successive_approximation_high = 0 ;

      // Y Component Validation
      if ((image_scans [scan_count].component_mask & (1<<YCOMPONENT)) != 0)
      {
        if (image_scans [scan_count].spectral_selection_end == 0)
        {
          if (lasty != -1)
            throw JpegError ("Duplicate Y Component Scan") ;

          image_scans [scan_count].spectral_selection_start = 0 ;
          lasty = 0 ;
        }
        else
        {
          if (image_scans [scan_count].component_mask != (1<<YCOMPONENT))
            throw JpegError ("Multiple Components in AC Scan") ;

          if (image_scans [scan_count].spectral_selection_end != 0
              && lasty == -1)
          {
            throw JpegError (
                     "AC Scan specified before DC scan for Y Component") ;
          }

          if (image_scans [scan_count].spectral_selection_end <= lasty)
            throw JpegError ("Duplicate or overlapping spectral selection for Y Component") ;

          image_scans [scan_count].spectral_selection_start = lasty + 1 ;
          lasty = image_scans [scan_count].spectral_selection_end ;
        }
      }

      if (! gray_scale)

⌨️ 快捷键说明

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