/***************************************************************************#
# jpegenc: library to encode a jpeg frame from various input palette.       #
# jpegenc works for embedded device without libjpeg                         #
#.                                                                          #
# 		Copyright (C) 2005 Michel Xhaard                            #
#                                                                           #
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #
#  CREDIT:								    #
# Original code from Nitin Gupta India (?)					    #
#                                                                           #
#***************************************************************************/ 
  
  
#include "jdatatype.h"
#include "encoder.h"
#include "marker.h"
  
// Header for JPEG Encoder
static UINT16 markerdata[] = { 
    // dht
    0xFFC4, 0x1A2, 0x00, 
    // luminance dc (2 - 16) + 1
    0x0105, 0x0101, 0x00101, 0x0101, 0x0000, 0x00000, 00000, 00000, 
    // luminance dc (2 - 12) + 1
    0x0102, 0x0304, 0x0506, 0x0708, 0x090A, 0x0B01, 
    // chrominance dc (1 - 16)
    0x0003, 0x0101, 0x0101, 0x0101, 0x0101, 0x0100, 0x0000, 0x0000, 
    // chrominance dc (1 - 12)
    0x0001, 0x00203, 0x0405, 0x0607, 0x0809, 0x00A0B, 
    // luminance ac 1 + (1 - 15)
    0x1000, 0x0201, 0x0303, 0x0204, 0x0305, 0x0504, 0x0400, 0x0001, 
    // luminance ac 1 + (1 - 162) + 1
    0x7D01, 0x0203, 0x0004, 0x1105, 0x1221, 0x3141, 0x0613, 0x5161, 0x0722,
    0x7114, 0x3281, 0x91A1, 0x0823, 0x42B1, 0xC115, 0x52D1, 0xF024, 0x3362,
    0x7282, 0x090A, 0x1617, 0x1819, 0x1A25, 0x2627, 0x2829, 0x2A34, 0x3536,
    0x3738, 0x393A, 0x4344, 0x4546, 0x4748, 0x494A, 0x5354, 0x5556, 0x5758,
    0x595A, 0x6364, 0x6566, 0x6768, 0x696A, 0x7374, 0x7576, 0x7778, 0x797A,
    0x8384, 0x8586, 0x8788, 0x898A, 0x9293, 0x9495, 0x9697, 0x9899, 0x9AA2,
    0xA3A4, 0xA5A6, 0xA7A8, 0xA9AA, 0xB2B3, 0xB4B5, 0xB6B7, 0xB8B9, 0xBAC2,
    0xC3C4, 0xC5C6, 0xC7C8, 0xC9CA, 0xD2D3, 0xD4D5, 0xD6D7, 0xD8D9, 0xDAE1,
    0xE2E3, 0xE4E5, 0xE6E7, 0xE8E9, 0xEAF1, 0xF2F3, 0xF4F5, 0xF6F7, 0xF8F9,
    0xFA11, 
    // chrominance ac (1 - 16)
    0x0002, 0x0102, 0x0404, 0x0304, 0x0705, 0x0404, 0x0001, 0x0277, 
    // chrominance ac (1 - 162)
  0x0001, 0x0203, 0x1104, 0x0521, 0x3106, 0x1241, 0x5107, 0x6171, 0x1322,
    0x3281, 0x0814, 0x4291, 0xA1B1, 0xC109, 0x2333, 0x52F0, 0x1562, 0x72D1,
    0x0A16, 0x2434, 0xE125, 0xF117, 0x1819, 0x1A26, 0x2728, 0x292A, 0x3536,
    0x3738, 0x393A, 0x4344, 0x4546, 0x4748, 0x494A, 0x5354, 0x5556, 0x5758,
    0x595A, 0x6364, 0x6566, 0x6768, 0x696A, 0x7374, 0x7576, 0x7778, 0x797A,
    0x8283, 0x8485, 0x8687, 0x8889, 0x8A92, 0x9394, 0x9596, 0x9798, 0x999A,
    0xA2A3, 0xA4A5, 0xA6A7, 0xA8A9, 0xAAB2, 0xB3B4, 0xB5B6, 0xB7B8, 0xB9BA,
    0xC2C3, 0xC4C5, 0xC6C7, 0xC8C9, 0xCAD2, 0xD3D4, 0xD5D6, 0xD7D8, 0xD9DA,
    0xE2E3, 0xE4E5, 0xE6E7, 0xE8E9, 0xEAF2, 0xF3F4, 0xF5F6, 0xF7F8, 0xF9FA 
};

UINT8 * write_markers (UINT8 * output_ptr, UINT32 image_format,
			 UINT32 image_width, UINT32 image_height) 
{
  UINT16 i, header_length;
  UINT8 number_of_components;
  
    // Start of image marker
    *output_ptr++ = 0xFF;
  *output_ptr++ = 0xD8;
  
    // Quantization table marker
    *output_ptr++ = 0xFF;
  *output_ptr++ = 0xDB;
  
    // Quantization table length
    *output_ptr++ = 0x00;
  *output_ptr++ = 0x84;
  
    // Pq, Tq
    *output_ptr++ = 0x00;
  
    // Lqt table
    for (i = 0; i < 64; i++)
    *output_ptr++ = Lqt[i];
  
    // Pq, Tq
    *output_ptr++ = 0x01;
  
    // Cqt table
    for (i = 0; i < 64; i++)
    *output_ptr++ = Cqt[i];
  
    // huffman table(DHT)
    for (i = 0; i < 210; i++)
    
    {
      *output_ptr++ = (UINT8) (markerdata[i] >> 8);
      *output_ptr++ = (UINT8) markerdata[i];
    }
  if (image_format == FOUR_ZERO_ZERO)
    number_of_components = 1;
  
  else
    number_of_components = 3;
  
    // Frame header(SOF)
    
    // Start of frame marker
    *output_ptr++ = 0xFF;
  *output_ptr++ = 0xC0;
  header_length = (UINT16) (8 + 3 * number_of_components);
  
    // Frame header length  
    *output_ptr++ = (UINT8) (header_length >> 8);
  *output_ptr++ = (UINT8) header_length;
  
    // Precision (P)
    *output_ptr++ = 0x08;
  
    // image height
    *output_ptr++ = (UINT8) (image_height >> 8);
  *output_ptr++ = (UINT8) image_height;
  
    // image width
    *output_ptr++ = (UINT8) (image_width >> 8);
  *output_ptr++ = (UINT8) image_width;
  
    // Nf
    *output_ptr++ = number_of_components;
  if (image_format == FOUR_ZERO_ZERO)
    
    {
      *output_ptr++ = 0x01;
      *output_ptr++ = 0x11;
      *output_ptr++ = 0x00;
    }
  
  else
    
    {
      *output_ptr++ = 0x01;
      if (image_format == FOUR_TWO_ZERO)
	*output_ptr++ = 0x22;
      
      else if (image_format == FOUR_TWO_TWO)
	*output_ptr++ = 0x21;
      
      else
	*output_ptr++ = 0x11;
      *output_ptr++ = 0x00;
      *output_ptr++ = 0x02;
      *output_ptr++ = 0x11;
      *output_ptr++ = 0x01;
      *output_ptr++ = 0x03;
      *output_ptr++ = 0x11;
      *output_ptr++ = 0x01;
    }
  
    // Scan header(SOF)
    
    // Start of scan marker
    *output_ptr++ = 0xFF;
  *output_ptr++ = 0xDA;
  header_length = (UINT16) (6 + (number_of_components << 1));
  
    // Scan header length
    *output_ptr++ = (UINT8) (header_length >> 8);
  *output_ptr++ = (UINT8) header_length;
  
    // Ns
    *output_ptr++ = number_of_components;
  if (image_format == FOUR_ZERO_ZERO)
    
    {
      *output_ptr++ = 0x01;
      *output_ptr++ = 0x00;
    }
  
  else
    
    {
      *output_ptr++ = 0x01;
      *output_ptr++ = 0x00;
      *output_ptr++ = 0x02;
      *output_ptr++ = 0x11;
      *output_ptr++ = 0x03;
      *output_ptr++ = 0x11;
    }
  *output_ptr++ = 0x00;
  *output_ptr++ = 0x3F;
  *output_ptr++ = 0x00;
  return output_ptr;
}


