home *** CD-ROM | disk | FTP | other *** search
/ Compressed Image File Formats / CompressedImageFileFormatsJohnMiano.iso / pc / Examples / c09 / src / jpencomp.cpp < prev   
Encoding:
C/C++ Source or Header  |  1998-12-23  |  17.5 KB  |  621 lines

  1. //
  2. // Copyright (c) 1997,1998 Colosseum Builders, Inc.
  3. // All rights reserved.
  4. //
  5. // Colosseum Builders, Inc. makes no warranty, expressed or implied
  6. // with regards to this software. It is provided as is.
  7. //
  8. // See the README.TXT file that came with this software for restrictions
  9. // on the use and redistribution of this file or send E-mail to
  10. // info@colosseumbuilders.com
  11. //
  12.  
  13. //
  14. // JPEG Encoder Library.
  15. //
  16. // Title:   JpegEncoderComponent Class Implementation
  17. //
  18. // Author: John M. Miano  miano@colosseumbuilders.com
  19. //
  20. //
  21.  
  22. #include "jpegenco.h"
  23. #include "jpencomp.h"
  24. #include "jfif.h"
  25. #include "jpencobk.h"
  26. #include "jpendu.h"
  27. #include "jpenhuff.h"
  28.  
  29. //
  30. //  Description:
  31. //
  32. //    Class Default Constructor
  33. //
  34.  
  35. JpegEncoderComponent::JpegEncoderComponent ()
  36. {
  37.  
  38.   jpeg_encoder = NULL ;
  39.   dct_coefficients = NULL ;
  40.  
  41.   du_rows = 0 ;
  42.   du_cols = 0 ;
  43.  
  44.   eob_run = 0 ;
  45.   eob_start_du_row = 0 ;
  46.   eob_start_du_col = 0 ;
  47.   eob_start_position = 0 ;
  48.  
  49.   v_frequency = 1 ;
  50.   h_frequency = 1 ;
  51.  
  52.   ac_table = NULL ;
  53.   dc_table = NULL ;
  54.  
  55.   return ;
  56. }
  57.  
  58. //
  59. //  Description:
  60. //
  61. //    Class Destructor
  62. //
  63. JpegEncoderComponent::~JpegEncoderComponent ()
  64. {
  65.   FreeDynamicStorage () ;
  66.   return ;
  67. }
  68.  
  69. //
  70. //  Description:
  71. //
  72. //    This function gets rid of all the memory allocated by the component.
  73. //    This allows the encoder to free memory after each image is written
  74. //    rather than waiting until the decoder is deleted.
  75. //
  76. void JpegEncoderComponent::FreeDynamicStorage ()
  77. {
  78.   delete [] dct_coefficients ; dct_coefficients = NULL ;
  79.   return ;
  80. }
  81.  
  82. //
  83. //  Description:
  84. //
  85. //    This function allocates the buffer used to hold DCT coefficients.
  86. //
  87. //  Parameters:
  88. //    image: The image being output
  89. //    maxhf: The maximum horizontal frequency for all components.
  90. //    maxvf: The maximum vertical frequency for all components.
  91. //
  92. void JpegEncoderComponent::CalculateDuDimensions (const BitmapImage &image,
  93.                                                   unsigned int maxhf,
  94.                                                   unsigned int maxvf)
  95. {
  96.   du_cols = (image.Width () * h_frequency + (JpegSampleWidth * maxhf - 1))
  97.           / (JpegSampleWidth * maxhf) ;
  98.   du_rows = (image.Height () * v_frequency + (JpegSampleWidth * maxvf - 1))
  99.           / (JpegSampleWidth * maxvf) ;
  100.  
  101.   v_period = maxvf / v_frequency ;
  102.   h_period = maxhf / h_frequency ;
  103.  
  104.   dct_coefficients = new JpegEncoderCoefficientBlock [du_cols * du_rows] ;
  105.   return ;
  106. }
  107.  
  108. //
  109. //  Description:
  110. //
  111. //    This function samples a component where the horizontal and
  112. //    vertical sampling frequencies are equal to the maximum values
  113. //    for all components.
  114. //
  115. //  Parameters:
  116. //    image:  The image to sample
  117. //    function:  A color conversion function
  118. //
  119.  
  120. void JpegEncoderComponent::Sample1to1Component (const BitmapImage &image,
  121.                                                 RGBTOYCBCRFUNCTION function)
  122. {
  123.   const int progressscale = 8 ;
  124.   unsigned int progress = 0 ;
  125.   unsigned int progressincrement = (100 << progressscale) / (du_rows) ;
  126.  
  127.   UBYTE1 red ;
  128.   UBYTE1 green ;
  129.   UBYTE1 blue ;
  130.  
  131.   JpegEncoderDataUnit data ;
  132.  
  133.   unsigned int index = 0 ;
  134.   for (unsigned int ii = 0 ; ii < du_rows ; ++ ii)
  135.   {
  136.     for (unsigned int jj = 0 ; jj < du_cols ; ++ jj, ++ index)
  137.     {
  138.       unsigned int row = ii * JpegSampleWidth ;
  139.       for (unsigned int dr = 0 ; dr < JpegSampleWidth ; ++ dr, ++ row)
  140.       {
  141.         unsigned int col = jj * JpegSampleWidth ;
  142.         for (unsigned int dc = 0 ; dc < JpegSampleWidth ; ++ dc, ++ col)
  143.         {
  144.           if (row < image.Height ())
  145.           {
  146.              if (col < image.Width ())
  147.              {
  148.                  image.GetRGB (row, col, red, green, blue) ;
  149.                  data [dr][dc] = function (red, green, blue) ;
  150.              }
  151.              else if (dc != 0)
  152.              {
  153.                // Extend the rightmost column
  154.                data [dr][dc] = data [dr][dc-1] ;
  155.              }
  156.              else
  157.              {
  158.                // This data unit is completely off the edge of the image.
  159.                data [dr][dc] = JpegMidpointSampleValue ;
  160.              }
  161.           }
  162.           else if (dr != 0)
  163.           {
  164.             // Extend the last row of the image.
  165.             data [dr][dc] = data [dr-1][dc] ;
  166.           }
  167.           else
  168.           {
  169.             // This data unit is completely off the edge of the image.
  170.             data [dr][dc] = JpegMidpointSampleValue ;
  171.           }
  172.         } // Data Unit Columns
  173.       } // Data Unit Rows
  174.  
  175.       data.ForwardDct (*quantization_table, dct_coefficients [index]) ;
  176.     } // Columns of Data Units
  177.     progress += progressincrement ;
  178.     jpeg_encoder->CallProgressFunction (progress >> progressscale) ;
  179.   } // Rows of Data Units
  180.   return ;
  181. }
  182.  
  183. //
  184. //  Description:
  185. //
  186. //    This function downsamples a component where the horizontal and
  187. //    vertical sampling frequencies are not equal to the maximum values
  188. //    for all components. 
  189. //
  190. //  Parameters:
  191. //    image:  The image to sample
  192. //    function:  A color conversion function
  193. //
  194. void JpegEncoderComponent::SampleNtoNComponent (const BitmapImage &image,
  195.                                                 RGBTOYCBCRFUNCTION function)
  196. {
  197.   const int progressscale = 8 ;
  198.   unsigned int progress = 0 ;
  199.   unsigned int progressincrement = (100 << progressscale) / (du_rows) ;
  200.  
  201.   JpegEncoderDataUnit data ;
  202.  
  203.   // Sample the image.
  204.   unsigned int index = 0 ;
  205.   unsigned int imagerow = 0 ;
  206.   for (unsigned int yy = 0 ;
  207.        yy < du_rows ;
  208.        ++ yy, imagerow += JpegSampleWidth * v_period)
  209.   {
  210.     unsigned int imagecol = 0 ;
  211.     for (unsigned int xx = 0 ;
  212.          xx < du_cols ;
  213.          ++ xx, ++ index, imagecol += JpegSampleWidth * h_period)
  214.     {
  215.       // Loop for each row in the data unit.
  216.       for (unsigned int outrow = 0 ; outrow < JpegSampleWidth  ; ++ outrow)
  217.       {
  218.         // Loop for each column in the data unit.
  219.         for (unsigned int outcol = 0 ; outcol < JpegSampleWidth ; ++ outcol)
  220.         {
  221.           // The nested loops handle sampling.
  222.  
  223.           int value = 0 ;   // Sum of all sample values
  224.           unsigned int count = 0 ;  // Number of sample values.
  225.           // Vertical sampling loop.
  226.           for (unsigned int srcrow = 0 ; srcrow < v_period ; ++ srcrow)
  227.           {
  228.             // Horizontal sampling loop.
  229.             unsigned int row = imagerow + srcrow + outrow * v_period ;
  230.             for (unsigned int srccol = 0 ; srccol < h_period ; ++ srccol)
  231.             {
  232.               // Extract the values from the image.
  233.               unsigned int col = imagecol + srccol + outcol * h_period ;
  234.               if (row < image.Height () && col < image.Width ())
  235.               {
  236.                 ++ count ;
  237.                 UBYTE1 red, green, blue ;
  238.                 image.GetRGB (row, col, red, green, blue) ;
  239.                 value += function (red, green, blue) ;
  240.               }
  241.             }
  242.           }
  243.           // Convert the total sample value to an average.
  244.           if (count != 0)
  245.           {
  246.              data [outrow][outcol] = (value + count - 1) / count ;
  247.           }
  248.           else
  249.           {
  250.             // If we get here that means the data unit goes past the edge of
  251.             // the input image. We attempt to duplicate the last column and if
  252.             // we can't to that we copy the last row. If the entire data unit
  253.             // is off the edge then we use zero for the value.
  254.             if (outcol != 0)
  255.               data [outrow][outcol] = data [outrow][outcol - 1] ;
  256.             else if (outrow != 0)
  257.               data [outrow][outcol] = data [outrow-1][outcol] ;
  258.             else
  259.               data [outrow][outcol] = 0 ;
  260.           }
  261.         }
  262.       }
  263.  
  264.       data.ForwardDct (*quantization_table, dct_coefficients [index]) ;
  265.     }
  266.     progress += progressincrement ;
  267.     jpeg_encoder->CallProgressFunction (progress >> progressscale) ;
  268.   }
  269.   return ;
  270. }
  271.  
  272. //
  273. //  Description:
  274. //
  275. //    This function samples the Y component for the image.
  276. //
  277. //    What we do here is determine how much memory is required
  278. //    to hold the image, what color conversion function to use
  279. //    for the component, and if downsampling is required.
  280. //
  281. //  Parameters:
  282. //    encoder:  The JPEG encoder that owns the component
  283. //    image:  The image to be sampled
  284. //    maxhf:  The maximum horizontal frequency of all components
  285. //    maxvf:  The maximum vertical frequency of all components
  286. //    
  287. void JpegEncoderComponent::SampleYComponent (JpegEncoder &encoder,
  288.                                              const BitmapImage &image,
  289.                                              unsigned int maxhf,
  290.                                              unsigned int maxvf)
  291. {
  292.   jpeg_encoder = &encoder ;
  293.   CalculateDuDimensions (image, maxhf, maxvf) ;
  294.  
  295.   if (maxhf == h_frequency && maxvf == v_frequency)
  296.   {
  297.     Sample1to1Component (image, RGBToY) ;
  298.   }
  299.   else
  300.   {
  301.     SampleNtoNComponent (image, RGBToY) ;
  302.   }
  303.  
  304.   return ;
  305. }
  306.  
  307. //
  308. //  Description:
  309. //
  310. //    This function samples the Cb component for the image.
  311. //
  312. //    What we do here is determine how much memory is required
  313. //    to hold the image, what color conversion function to use
  314. //    for the component, and if downsampling is required.
  315. //
  316. //  Parameters:
  317. //    encoder:  The JPEG encoder that owns the component
  318. //    image:  The image to be sampled
  319. //    maxhf:  The maximum horizontal frequency of all components
  320. //    maxvf:  The maximum vertical frequency of all components
  321. //    
  322. void JpegEncoderComponent::SampleCbComponent (JpegEncoder &encoder,
  323.                                               const BitmapImage &image,
  324.                                               unsigned int maxhf,
  325.                                               unsigned int maxvf)
  326. {
  327.   jpeg_encoder = &encoder ;
  328.   CalculateDuDimensions (image, maxhf, maxvf) ;
  329.  
  330.   if (maxhf == h_frequency && maxvf == v_frequency)
  331.   {
  332.     Sample1to1Component (image, RGBToCb) ;
  333.   }
  334.   else
  335.   {
  336.     SampleNtoNComponent (image, RGBToCb) ;
  337.   }
  338.  
  339.   return ;
  340. }
  341.  
  342. //
  343. //  Description:
  344. //
  345. //    This function samples the Cr component for the image.
  346. //
  347. //    What we do here is determine how much memory is required
  348. //    to hold the image, what color conversion function to use
  349. //    for the component, and if downsampling is required.
  350. //
  351. //  Parameters:
  352. //    encoder:  The JPEG encoder that owns the component
  353. //    image:  The image to be sampled
  354. //    maxhf:  The maximum horizontal frequency of all components
  355. //    maxvf:  The maximum vertical frequency of all components
  356. //    
  357.  
  358. void JpegEncoderComponent::SampleCrComponent (JpegEncoder &encoder,
  359.                                               const BitmapImage &image,
  360.                                               unsigned int maxhf,
  361.                                               unsigned int maxvf)
  362. {
  363.   jpeg_encoder = &encoder ;
  364.   CalculateDuDimensions (image, maxhf, maxvf) ;
  365.  
  366.   if (maxhf == h_frequency && maxvf == v_frequency)
  367.   {
  368.     Sample1to1Component (image, RGBToCr) ;
  369.   }
  370.   else
  371.   {
  372.     SampleNtoNComponent (image, RGBToCr) ;
  373.   }
  374.  
  375.   return ;
  376. }
  377.  
  378. //
  379. //  Description:
  380. //
  381. //    This function is use to gather Huffman statistics for DC coefficients.
  382. //    The calling sequences is idential to PrintDcData (). Only the huffvalue
  383. //    parameter is used here.
  384. //
  385. //  Parameters:
  386. //    huffvalue:  The Huffman value (not code) to process.
  387. //
  388. void JpegEncoderComponent::GatherDcData (int huffvalue, int)
  389. {
  390.   dc_table->IncrementFrequency (huffvalue) ;
  391.   return ;
  392. }
  393.  
  394. //
  395. //  Description:
  396. //
  397. //    This function is use to gather Huffman statistics for AC coefficients.
  398. //    The calling sequences is idential to PrintAcData (). Only the huffvalue
  399. //    parameter is used here.
  400. //
  401. //    If huffval==-1 then an unencoded bit string would be output by
  402. //    PrintAcData (). In that situation this function does nothing.
  403. //
  404. //  Parameters:
  405. //    huffvalue:  The Huffman value (not code) to process
  406. //
  407. void JpegEncoderComponent::GatherAcData (int huffvalue, int, int)
  408. {
  409.   if (huffvalue >= 0)
  410.   {
  411.     ac_table->IncrementFrequency (huffvalue) ;
  412.   }
  413.   return ;
  414. }
  415.  
  416. //
  417. //  Description:
  418. //
  419. //    This function is use to output Huffman-encoded data for a DC value.
  420. //
  421. //  Parameters:
  422. //    huffvalue:  The Huffman value
  423. //    bits: The additional data bits
  424. //
  425. //    8-bit DC values are in the range 0..11. The value specifies the number
  426. //    of additional bits of refining data (bits).
  427. //
  428.  
  429. void JpegEncoderComponent::PrintDcData (int huffvalue, int bits)
  430. {
  431.   UBYTE2 huffcode ;
  432.   UBYTE1 huffsize ;
  433.  
  434.   // Section F.1.2.1
  435.   dc_table->Encode (huffvalue, huffcode, huffsize) ;
  436.   jpeg_encoder->OutputBits (huffcode, huffsize) ;
  437.   if (huffvalue != 0)
  438.     jpeg_encoder->OutputBits (bits, huffvalue) ;
  439.   return ;
  440. }
  441.  
  442. //
  443. //  Description:
  444. //
  445. //    This function is use to output Huffman-encoded data for an AC value.
  446. //
  447. //  Parameters:
  448. //    huffvalue:  The Huffman value
  449. //    value: The additional data bits
  450. //    size: The number of additional data bits.
  451. //
  452. //    When huffvalue==-1 this function is also used to output unencoded bit
  453. //    strings.
  454. //
  455. void JpegEncoderComponent::PrintAcData (int huffvalue, int value, int size)
  456. {
  457.   UBYTE2 huffcode ;
  458.   UBYTE1 huffsize ;
  459.  
  460.   // Section F.1.2.2.1
  461.   if (huffvalue >= 0)
  462.   {
  463.     ac_table->Encode (huffvalue, huffcode, huffsize) ;
  464.     jpeg_encoder->OutputBits (huffcode, huffsize) ;
  465.   }
  466.   if (size != 0)
  467.     jpeg_encoder->OutputBits (value, size) ;
  468.   return ;
  469. }
  470. //
  471. //  Description:
  472. //
  473. //    This function is used for two purposes in a sequential scan:
  474. //
  475. //      o To gather statistics for generating Huffman Tables
  476. //      o To encode and output a data unit.
  477. //
  478. //    The dcfunction and acfunction arguments are determine which of these
  479. //    actions are performed. If these arguments are PrintDcData () and
  480. //    PrintAcData () the data unit is encoded and written to the output
  481. //    stream.  If the arguments are GatherDcData () and GatherAcData ()
  482. //    usage statistics are gathered.
  483. //
  484. //    While creating a separate function for each purpose may have been clearer,
  485. //    it would create maintenance problems because they would have to be kept
  486. //    in strict synchronization with each other.
  487. //
  488. //  Parameters:
  489. //    row,col: Data unit position
  490. //    dcfunction: Function for outputting DC coefficient values.
  491. //    acfunction: Function for outputting AC coefficient values.
  492. //
  493. //    This function is of the type COMPONENTPASSFUNCTION.
  494. //
  495. void JpegEncoderComponent::EncodeSequential (
  496.                             unsigned int row, unsigned int col,
  497.                             DCOUTPUTFUNCTION dcfunction,
  498.                             ACOUTPUTFUNCTION acfunction,
  499.                             unsigned int, unsigned int, unsigned int)
  500. {
  501.   JpegEncoderCoefficientBlock *du = &dct_coefficients [row * du_cols + col] ;
  502.  
  503.   // DC value calculation
  504.   // Section F.1.2.1.3
  505.   int diff = (*du) [0][0] - last_dc_value ;
  506.   last_dc_value = (*du)[0][0] ;
  507.  
  508.   // Break the DC coefficient into a category (Table F.12) and
  509.   // additional bits.
  510.   int bits ;
  511.   if (diff >= 0)
  512.   {
  513.     bits = diff ;
  514.   }
  515.   else
  516.   {
  517.     diff = -diff ;
  518.     bits = ~diff ;
  519.   }
  520.   int ssss = 0 ;  // Category
  521.   while (diff != 0)
  522.   {
  523.     ++ ssss ;
  524.     diff >>= 1 ;
  525.   }
  526.   (this->*dcfunction) (ssss, bits) ;
  527.  
  528.   // AC coefficient coding
  529.   // F.1.2.2.3 Figure F.2
  530.   int zerorun = 0 ; // Called rrrr in the specification.
  531.   for (unsigned int index = 1 ; index < JpegSampleSize ; ++ index)
  532.   {
  533.     if (du->ZigZagInput (index) != 0)
  534.     {
  535.       // 16 is the longest run of zeros that can be encoded except for the
  536.       // final EOB code.
  537.       while (zerorun >= 16)
  538.       {
  539.         // 0xF0 is the code to skip 16 zeros (Figure F.1)
  540.         (this->*acfunction) (0xF0, 0, 0) ;
  541.         zerorun -= 16 ;
  542.       }
  543.  
  544.       // Non-zero AC coefficients are encoded with
  545.       // 8-bit Huffman-encoded values of the form rrrrssss followed by
  546.       // 1..10 additional bits of data. rrrr is the number of zero values
  547.       // to skip (0..15). ssss is the category (1..10) which specifies the
  548.       // number of additional raw bits to follow. (Figure F.1)
  549.       int value = du->ZigZagInput (index) ;
  550.       int bits ;
  551.       if (value >= 0)
  552.       {
  553.         bits = value ;
  554.       }
  555.       else
  556.       {
  557.         value = -value ;
  558.         bits = ~value ;
  559.       }
  560.       int ssss = 0 ;
  561.       while (value != 0)
  562.       {
  563.         value >>= 1 ;
  564.         ++ ssss ;
  565.       }
  566.  
  567.       int rrrrssss = (zerorun << 4) | ssss ;
  568.       (this->*acfunction) (rrrrssss, bits, ssss) ;
  569.       zerorun = 0 ;
  570.     }
  571.     else
  572.     {
  573.       ++ zerorun ;
  574.     }
  575.   }
  576.   // The code 0x00 indicates all remaining AC coefficients are zero.
  577.   if (zerorun > 0)
  578.   {
  579.     (this->*acfunction) (0, 0, 0) ;
  580.   }
  581.  
  582.   return ;
  583. }
  584.  
  585. //
  586. //  Description
  587. //
  588. //    This function sets the horizontal sampling frequency for the
  589. //    component.
  590. //
  591. //  Parameters:
  592. //    value:  The new sampling frequency.
  593. //
  594. void JpegEncoderComponent::SetHorizontalFrequency (unsigned int value)
  595. {
  596.   if (value > JpegMaxSamplingFrequency || value < JpegMinSamplingFrequency)
  597.       throw EJpegValueOutOfRange () ;
  598.  
  599.   h_frequency = value ;
  600.     return ;
  601. }
  602.  
  603. //
  604. //  Description
  605. //
  606. //    This function sets the vertical sampling frequency for the
  607. //    component.
  608. //
  609. //  Parameters:
  610. //    value:  The new sampling frequency.
  611. //
  612. void JpegEncoderComponent::SetVerticalFrequency (unsigned int value)
  613. {
  614.   if (value > JpegMaxSamplingFrequency || value < JpegMinSamplingFrequency)
  615.     throw EJpegValueOutOfRange () ;
  616.  
  617.   v_frequency = value ;
  618.   return ;
  619. }
  620.  
  621.