瀏覽代碼

add non-functional jpeg2000 skeleton

cxgeorge 24 年之前
父節點
當前提交
01496b8e3d

+ 15 - 3
panda/src/pnmimagetypes/Sources.pp

@@ -1,6 +1,8 @@
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m
+
 #define USE_JPEG yes
+#define USE_JPEG2000 yes
 
 #begin lib_target
   #define TARGET pnmimagetypes
@@ -26,15 +28,25 @@
      pnmFileTypeTGA.cxx pnmFileTypeYUV.cxx
      
   #define IF_JPEG_INCLUDED_SOURCES \
-    pnmFileTypeJPG.cxx \
-    pnmFileTypeJPGReader.cxx pnmFileTypeJPGWriter.cxx
+    pnmFileTypeJPG2000.cxx \
+    pnmFileTypeJPG2000Reader.cxx pnmFileTypeJPG2000Writer.cxx
     
   #define IF_JPEG_SOURCES \
-    pnmFileTypeJPG.h 
+    pnmFileTypeJPG2000.h 
     
   #define IF_JPEG_COMBINED_SOURCES \    
     $[TARGET]_composite3.cxx        
 
+  #define IF_JPEG2000_INCLUDED_SOURCES \
+    pnmFileTypeJPG2000.cxx \
+    pnmFileTypeJPG2000Reader.cxx pnmFileTypeJPG2000Writer.cxx
+    
+  #define IF_JPEG2000_SOURCES \
+    pnmFileTypeJPG2000.h 
+    
+  #define IF_JPEG2000_COMBINED_SOURCES \    
+    $[TARGET]_composite4.cxx
+
   #define INSTALL_HEADERS \
     config_pnmimagetypes.h
 

+ 10 - 0
panda/src/pnmimagetypes/config_pnmimagetypes.cxx

@@ -49,6 +49,7 @@ NotifyCategoryDef(pnmimage_img, pnmimage_cat);
 NotifyCategoryDef(pnmimage_soft, pnmimage_cat);
 NotifyCategoryDef(pnmimage_bmp, pnmimage_cat);
 NotifyCategoryDef(pnmimage_jpg, pnmimage_cat);
+NotifyCategoryDef(pnmimage_jpg2000, pnmimage_cat);
 
 int sgi_storage_type = STORAGE_RLE;
 const string sgi_imagename = config_pnmimagetypes.GetString("sgi-imagename", "");
@@ -133,6 +134,9 @@ init_libpnmimagetypes() {
 #ifdef HAVE_JPEG
   PNMFileTypeJPG::init_type();
 #endif
+#ifdef HAVE_JPEG2000
+  PNMFileTypeJPG2000::init_type();
+#endif
 
   string sgi_storage_type_str =
     config_pnmimagetypes.GetString("sgi-storage-type", "rle");
@@ -174,6 +178,9 @@ init_libpnmimagetypes() {
 #ifdef HAVE_JPEG
   tr->register_type(new PNMFileTypeJPG);
 #endif
+#ifdef HAVE_JPEG2000
+  tr->register_type(new PNMFileTypeJPG2000);
+#endif
 
   // Also register with the Bam reader.
   PNMFileTypePNM::register_with_read_factory();
@@ -189,4 +196,7 @@ init_libpnmimagetypes() {
 #ifdef HAVE_JPEG
   PNMFileTypeJPG::register_with_read_factory();
 #endif
+#ifdef HAVE_JPEG2000
+  PNMFileTypeJPG2000::register_with_read_factory();
+#endif
 }

+ 1 - 0
panda/src/pnmimagetypes/config_pnmimagetypes.h

@@ -33,6 +33,7 @@ NotifyCategoryDecl(pnmimage_img, EXPCL_PANDA, EXPTP_PANDA);
 NotifyCategoryDecl(pnmimage_soft, EXPCL_PANDA, EXPTP_PANDA);
 NotifyCategoryDecl(pnmimage_bmp, EXPCL_PANDA, EXPTP_PANDA);
 NotifyCategoryDecl(pnmimage_jpg, EXPCL_PANDA, EXPTP_PANDA);
+NotifyCategoryDecl(pnmimage_jpg2000, EXPCL_PANDA, EXPTP_PANDA);
 
 extern int sgi_storage_type;
 extern const string sgi_imagename;

+ 166 - 0
panda/src/pnmimagetypes/pnmFileTypeJPG2000.cxx

@@ -0,0 +1,166 @@
+// Filename: pnmFileTypeJPG2000.cxx
+// Created by:  mike (19Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pnmFileTypeJPG2000.h"
+#include "config_pnmimagetypes.h"
+
+#include <pnmFileTypeRegistry.h>
+#include <bamReader.h>
+
+static const char * const extensions_JPG2000[] = {
+  "JP2","JPC"
+};
+static const int num_extensions_JPG2000 = sizeof(extensions_JPG2000) / sizeof(const char *);
+
+TypeHandle PNMFileTypeJPG2000::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PNMFileTypeJPG2000::
+PNMFileTypeJPG2000() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::get_name
+//       Access: Public, Virtual
+//  Description: Returns a few words describing the file type.
+////////////////////////////////////////////////////////////////////
+string PNMFileTypeJPG2000::
+get_name() const {
+  return "JPEG_2000";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::get_num_extensions
+//       Access: Public, Virtual
+//  Description: Returns the number of different possible filename
+//               extensions_JPG2000 associated with this particular file type.
+////////////////////////////////////////////////////////////////////
+int PNMFileTypeJPG2000::
+get_num_extensions() const {
+  return num_extensions_JPG2000;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::get_extension
+//       Access: Public, Virtual
+//  Description: Returns the nth possible filename extension
+//               associated with this particular file type, without a
+//               leading dot.
+////////////////////////////////////////////////////////////////////
+string PNMFileTypeJPG2000::
+get_extension(int n) const {
+  nassertr(n >= 0 && n < num_extensions_JPG2000, string());
+  return extensions_JPG2000[n];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::get_suggested_extension
+//       Access: Public, Virtual
+//  Description: Returns a suitable filename extension (without a
+//               leading dot) to suggest for files of this type, or
+//               empty string if no suggestions are available.
+////////////////////////////////////////////////////////////////////
+string PNMFileTypeJPG2000::
+get_suggested_extension() const {
+  return "JP2";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::has_magic_number
+//       Access: Public, Virtual
+//  Description: Returns true if this particular file type uses a
+//               magic number to identify it, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool PNMFileTypeJPG2000::
+has_magic_number() const {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::matches_magic_number
+//       Access: Public, Virtual
+//  Description: Returns true if the indicated "magic number" byte
+//               stream (the initial few bytes read from the file)
+//               matches this particular file type, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool PNMFileTypeJPG2000::
+matches_magic_number(const string &magic_number) const {
+  nassertr(magic_number.size() >= 2, false);
+  return ((char)magic_number[0] == (char)0xff &&
+          (char)magic_number[1] == (char)0xd8);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::make_reader
+//       Access: Public, Virtual
+//  Description: Allocates and returns a new PNMReader suitable for
+//               reading from this file type, if possible.  If reading
+//               from this file type is not supported, returns NULL.
+////////////////////////////////////////////////////////////////////
+PNMReader *PNMFileTypeJPG2000::
+make_reader(FILE *file, bool owns_file, const string &magic_number) {
+  init_pnm();
+  return new Reader(this, file, owns_file, magic_number);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::make_writer
+//       Access: Public, Virtual
+//  Description: Allocates and returns a new PNMWriter suitable for
+//               reading from this file type, if possible.  If writing
+//               files of this type is not supported, returns NULL.
+////////////////////////////////////////////////////////////////////
+PNMWriter *PNMFileTypeJPG2000::
+make_writer(FILE *file, bool owns_file) {
+  init_pnm();
+  return new Writer(this, file, owns_file);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::register_with_read_factory
+//       Access: Public, Static
+//  Description: Registers the current object as something that can be
+//               read from a Bam file.
+////////////////////////////////////////////////////////////////////
+void PNMFileTypeJPG2000::
+register_with_read_factory() {
+  BamReader::get_factory()->
+    register_factory(get_class_type(), make_PNMFileTypeJPG2000);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::make_PNMFileTypeJPG2000
+//       Access: Protected, Static
+//  Description: This method is called by the BamReader when an object
+//               of this type is encountered in a Bam file; it should
+//               allocate and return a new object with all the data
+//               read.
+//
+//               In the case of the PNMFileType objects, since these
+//               objects are all shared, we just pull the object from
+//               the registry.
+////////////////////////////////////////////////////////////////////
+TypedWritable *PNMFileTypeJPG2000::
+make_PNMFileTypeJPG2000(const FactoryParams &params) {
+  return PNMFileTypeRegistry::get_ptr()->get_type_by_handle(get_class_type());
+}

+ 133 - 0
panda/src/pnmimagetypes/pnmFileTypeJPG2000.h

@@ -0,0 +1,133 @@
+// Filename: pnmFileTypeJPG2000.h
+// Created by:  mike (17Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PNMFILETYPEJPG2000_H
+#define PNMFILETYPEJPG2000_H
+
+#include <pandabase.h>
+
+#include <pnmFileType.h>
+#include <pnmReader.h>
+#include <pnmWriter.h>
+
+#if defined(_WIN32)
+#include <windows.h>  // we need to include this before jpeglib.
+#endif
+
+#include <jasper/jasper.h>
+
+/*
+extern "C" {
+#include <jpeglib.h>
+#include <setjmp.h>
+}
+*/
+
+////////////////////////////////////////////////////////////////////
+//       Class : PNMFileTypeJPG2000
+// Description : For reading and writing Jpeg files.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA PNMFileTypeJPG2000 : public PNMFileType {
+public:
+  PNMFileTypeJPG2000();
+
+  virtual string get_name() const;
+
+  virtual int get_num_extensions() const;
+  virtual string get_extension(int n) const;
+  virtual string get_suggested_extension() const;
+
+  virtual bool has_magic_number() const;
+  virtual bool matches_magic_number(const string &magic_number) const;
+
+  virtual PNMReader *make_reader(FILE *file, bool owns_file = true,
+                                 const string &magic_number = string());
+  virtual PNMWriter *make_writer(FILE *file, bool owns_file = true);
+
+public:
+  class Reader : public PNMReader {
+  public:
+    Reader(PNMFileType *type, FILE *file, bool owns_file, string magic_number);
+    ~Reader(void);
+
+    virtual int read_data(xel *array, xelval *alpha);
+
+  private:
+/*
+    // struct jpeg_decompress_struct _cinfo;
+    jas_image_t *image;
+    jas_stream_t *in;
+    jas_stream_t *out;
+*/  
+
+
+    struct my_error_mgr {
+      struct jpeg_error_mgr pub;
+      jmp_buf setjmp_buffer;
+    };
+    typedef struct my_error_mgr *_my_error_ptr;
+    struct my_error_mgr _jerr;
+    unsigned long       pos;
+
+    unsigned long offBits;
+
+    unsigned short  cBitCount;
+    int             indexed;
+    int             classv;
+
+    pixval R[256];      /* reds */
+    pixval G[256];      /* greens */
+    pixval B[256];      /* blues */
+  };
+
+  class Writer : public PNMWriter {
+  public:
+    Writer(PNMFileType *type, FILE *file, bool owns_file);
+
+    virtual int write_data(xel *array, xelval *alpha);
+  };
+
+
+  // The TypedWritable interface follows.
+public:
+  static void register_with_read_factory();
+
+protected:
+  static TypedWritable *make_PNMFileTypeJPG2000(const FactoryParams &params);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    PNMFileType::init_type();
+    register_type(_type_handle, "PNMFileTypeJPG2000",
+                  PNMFileType::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+
+

+ 166 - 0
panda/src/pnmimagetypes/pnmFileTypeJPG2000Reader.cxx

@@ -0,0 +1,166 @@
+// Filename: pnmFileTypeJPGReader.cxx
+// Created by:  mike (19Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pnmFileTypeJPG2000.h"
+#include "config_pnmimagetypes.h"
+#include <typedef.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Reader::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PNMFileTypeJPG2000::Reader::
+Reader(PNMFileType *type, FILE *file, bool owns_file, string magic_number) :
+  PNMReader(type, file, owns_file)
+{
+  // Put the magic number bytes back into the file
+  fseek(file, 0, SEEK_SET);
+
+  /* Step 1: allocate and initialize JPEG decompression object */
+
+  /* We set up the normal JPEG error routines, then override error_exit. */
+  _cinfo.err = jpeg_std_error(&_jerr.pub);
+
+  /* Now we can initialize the JPEG decompression object. */
+  jpeg_create_decompress(&_cinfo);
+
+  /* Step 2: specify data source (eg, a file) */
+
+  jpeg_stdio_src(&_cinfo, file);
+
+  /* Step 3: read file parameters with jpeg_read_header() */
+
+  jpeg_read_header(&_cinfo, TRUE);
+  /* We can ignore the return value from jpeg_read_header since
+   *   (a) suspension is not possible with the stdio data source, and
+   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
+   * See libjpeg.doc for more info.
+   */
+
+  /* Step 4: set parameters for decompression */
+  _cinfo.scale_num = jpeg_scale_num;
+  _cinfo.scale_denom = jpeg_scale_denom;
+
+  /* Step 5: Start decompressor */
+
+  jpeg_start_decompress(&_cinfo);
+  /* We can ignore the return value since suspension is not possible
+   * with the stdio data source.
+   */
+
+  _num_channels = _cinfo.output_components;
+  _x_size = (int)_cinfo.output_width;
+  _y_size = (int)_cinfo.output_height;
+  _maxval = MAXJSAMPLE;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Reader::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PNMFileTypeJPG2000::Reader::
+~Reader(void) {
+  jpeg_destroy_decompress(&_cinfo);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Reader::read_data
+//       Access: Public, Virtual
+//  Description: Reads in an entire image all at once, storing it in
+//               the pre-allocated _x_size * _y_size array and alpha
+//               pointers.  (If the image type has no alpha channel,
+//               alpha is ignored.)  Returns the number of rows
+//               correctly read.
+//
+//               Derived classes need not override this if they
+//               instead provide supports_read_row() and read_row(),
+//               below.
+////////////////////////////////////////////////////////////////////
+int PNMFileTypeJPG2000::Reader::
+read_data(xel *array, xelval *) {
+  JSAMPARRAY buffer;            /* Output row buffer */
+  int row_stride;               /* physical row width in output buffer */
+
+  nassertr(_cinfo.output_components == 1 || _cinfo.output_components == 3, 0);
+
+  /* We may need to do some setup of our own at this point before reading
+   * the data.  After jpeg_start_decompress() we have the correct scaled
+   * output image dimensions available, as well as the output colormap
+   * if we asked for color quantization.
+   * In this example, we need to make an output work buffer of the right size.
+   */
+  /* JSAMPLEs per row in output buffer */
+  row_stride = _cinfo.output_width * _cinfo.output_components;
+  /* Make a one-row-high sample array that will go away when done with image */
+
+  buffer = (*_cinfo.mem->alloc_sarray)
+                ((j_common_ptr) &_cinfo, JPOOL_IMAGE, row_stride, 1);
+
+  /* Step 6: while (scan lines remain to be read) */
+  /*           jpeg_read_scanlines(...); */
+
+  /* Here we use the library's state variable cinfo.output_scanline as the
+   * loop counter, so that we don't have to keep track ourselves.
+   */
+  int x = 0;
+  while (_cinfo.output_scanline < _cinfo.output_height) {
+    /* jpeg_read_scanlines expects an array of pointers to scanlines.
+     * Here the array is only one element long, but you could ask for
+     * more than one scanline at a time if that's more convenient.
+     */
+    jpeg_read_scanlines(&_cinfo, buffer, 1);
+    /* Assume put_scanline_someplace wants a pointer and sample count. */
+    //put_scanline_someplace(buffer[0], row_stride);
+    JSAMPROW bufptr = buffer[0];
+    for (int i = 0; i < row_stride; i += _cinfo.output_components) {
+      if (_cinfo.output_components == 1) {
+        xelval val = (xelval)bufptr[i];
+        nassertr(x < _x_size * _y_size, 0);
+        PNM_ASSIGN1(array[x], val);
+      } else {
+        xelval red, grn, blu;
+        red = (xelval)bufptr[i];
+        grn = (xelval)bufptr[i+1];
+        blu = (xelval)bufptr[i+2];
+        nassertr(x < _x_size * _y_size, 0);
+        PPM_ASSIGN(array[x], red, grn, blu);
+      }
+      x++;
+    }
+  }
+
+  /* Step 7: Finish decompression */
+
+  jpeg_finish_decompress(&_cinfo);
+
+  /* We can ignore the return value since suspension is not possible
+   * with the stdio data source.
+   */
+
+  /* At this point you may want to check to see whether any corrupt-data
+   * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
+   */
+  if (_jerr.pub.num_warnings) {
+    pnmimage_jpg_cat.warning()
+      << "Jpeg data may be corrupt" << endl;
+  }
+
+  return _y_size;
+}

+ 186 - 0
panda/src/pnmimagetypes/pnmFileTypeJPG2000Writer.cxx

@@ -0,0 +1,186 @@
+// Filename: pnmFileTypeJPGWriter.cxx
+// Created by:  mike (19Jun00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pnmFileTypeJPG2000.h"
+#include "config_pnmimagetypes.h"
+
+#include <pnmImage.h>
+#include <pnmWriter.h>
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Writer::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PNMFileTypeJPG2000::Writer::
+Writer(PNMFileType *type, FILE *file, bool owns_file) :
+  PNMWriter(type, file, owns_file)
+{
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PNMFileTypeJPG2000::Writer::write_data
+//       Access: Public, Virtual
+//  Description: Writes out an entire image all at once, including the
+//               header, based on the image data stored in the given
+//               _x_size * _y_size array and alpha pointers.  (If the
+//               image type has no alpha channel, alpha is ignored.)
+//               Returns the number of rows correctly written.
+//
+//               It is the user's responsibility to fill in the header
+//               data via calls to set_x_size(), set_num_channels(),
+//               etc., or copy_header_from(), before calling
+//               write_data().
+//
+//               It is important to delete the PNMWriter class after
+//               successfully writing the data.  Failing to do this
+//               may result in some data not getting flushed!
+//
+//               Derived classes need not override this if they
+//               instead provide supports_streaming() and write_row(),
+//               below.
+////////////////////////////////////////////////////////////////////
+int PNMFileTypeJPG2000::Writer::
+write_data(xel *array, xelval *) {
+  if (_y_size<=0 || _x_size<=0) {
+    return 0;
+  }
+
+  /* This struct contains the JPEG compression parameters and pointers to
+   * working space (which is allocated as needed by the JPEG library).
+   * It is possible to have several such structures, representing multiple
+   * compression/decompression processes, in existence at once.  We refer
+   * to any one struct (and its associated working data) as a "JPEG object".
+   */
+  struct jpeg_compress_struct cinfo;
+  /* This struct represents a JPEG error handler.  It is declared separately
+   * because applications often want to supply a specialized error handler
+   * (see the second half of this file for an example).  But here we just
+   * take the easy way out and use the standard error handler, which will
+   * print a message on stderr and call exit() if compression fails.
+   * Note that this struct must live as long as the main JPEG parameter
+   * struct, to avoid dangling-pointer problems.
+   */
+  struct jpeg_error_mgr jerr;
+  /* More stuff */
+  JSAMPROW row_pointer[1];      /* pointer to JSAMPLE row[s] */
+  int row_stride;               /* physical row width in image buffer */
+
+  /* Step 1: allocate and initialize JPEG compression object */
+
+  /* We have to set up the error handler first, in case the initialization
+   * step fails.  (Unlikely, but it could happen if you are out of memory.)
+   * This routine fills in the contents of struct jerr, and returns jerr's
+   * address which we place into the link field in cinfo.
+   */
+  cinfo.err = jpeg_std_error(&jerr);
+
+  /* Now we can initialize the JPEG compression object. */
+  jpeg_create_compress(&cinfo);
+
+  /* Step 2: specify data destination (eg, a file) */
+  /* Note: steps 2 and 3 can be done in either order. */
+
+  /* Here we use the library-supplied code to send compressed data to a
+   * stdio stream.  You can also write your own code to do something else.
+   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+   * requires it in order to write binary files.
+   */
+  jpeg_stdio_dest(&cinfo, _file);
+
+  /* Step 3: set parameters for compression */
+
+  /* First we supply a description of the input image.
+   * Four fields of the cinfo struct must be filled in:
+   */
+  cinfo.image_width = _x_size;      /* image width and height, in pixels */
+  cinfo.image_height = _y_size;
+  if (is_grayscale()) {
+    cinfo.input_components = 1;
+    cinfo.in_color_space = JCS_GRAYSCALE;
+  } else {
+    cinfo.input_components = 3;
+    cinfo.in_color_space = JCS_RGB;
+  }
+  /* Now use the library's routine to set default compression parameters.
+   * (You must set at least cinfo.in_color_space before calling this,
+   * since the defaults depend on the source color space.)
+   */
+  jpeg_set_defaults(&cinfo);
+  /* Now you can set any non-default parameters you wish to.
+   * Here we just illustrate the use of quality (quantization table) scaling:
+   */
+  jpeg_set_quality(&cinfo, jpeg_quality, TRUE /* limit to baseline-JPEG values */);
+
+  /* Step 4: Start compressor */
+
+  /* TRUE ensures that we will write a complete interchange-JPEG file.
+   * Pass TRUE unless you are very sure of what you're doing.
+   */
+  jpeg_start_compress(&cinfo, TRUE);
+
+  /* Step 5: while (scan lines remain to be written) */
+  /*           jpeg_write_scanlines(...); */
+
+  /* Here we use the library's state variable cinfo.next_scanline as the
+   * loop counter, so that we don't have to keep track ourselves.
+   * To keep things simple, we pass one scanline per call; you can pass
+   * more if you wish, though.
+   */
+  row_stride = _x_size * cinfo.input_components; /* JSAMPLEs per row in image_buffer */
+
+  int x = 0;
+  JSAMPROW row = new JSAMPLE[row_stride];
+  while (cinfo.next_scanline < cinfo.image_height) {
+    /* jpeg_write_scanlines expects an array of pointers to scanlines.
+     * Here the array is only one element long, but you could pass
+     * more than one scanline at a time if that's more convenient.
+     */
+    for (int i = 0; i < row_stride; i += cinfo.input_components) {
+      if (cinfo.input_components == 1) {
+        row[i] = (JSAMPLE)(MAXJSAMPLE * PPM_GETB(array[x])/_maxval);
+      } else {
+        row[i] = (JSAMPLE)(MAXJSAMPLE * PPM_GETR(array[x])/_maxval);
+        row[i+1] = (JSAMPLE)(MAXJSAMPLE * PPM_GETG(array[x])/_maxval);
+        row[i+2] = (JSAMPLE)(MAXJSAMPLE * PPM_GETB(array[x])/_maxval);
+      }
+      x++;
+    }
+    //row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+    //(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+    row_pointer[0] = row;
+    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+  }
+  delete row;
+
+  /* Step 6: Finish compression */
+
+  jpeg_finish_compress(&cinfo);
+
+  /* Step 7: release JPEG compression object */
+
+  /* This is an important step since it will release a good deal of memory. */
+  jpeg_destroy_compress(&cinfo);
+
+  return _y_size;
+}

+ 5 - 0
panda/src/pnmimagetypes/pnmimagetypes_composite4.cxx

@@ -0,0 +1,5 @@
+
+#include "pnmFileTypeJPG2000.cxx"
+#include "pnmFileTypeJPG2000Reader.cxx"
+#include "pnmFileTypeJPG2000Writer.cxx"
+