Logo Search packages:      
Sourcecode: yafray version File versions

jpeg.cc

/****************************************************************************
 *
 *                jpeg.cc: JPEG Texture implementation
 *      This is part of the yafray package
 *      Copyright (C) 2002 Alejandro Conty Estevez
 *
 *      This library is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU Lesser General Public
 *      License as published by the Free Software Foundation; either
 *      version 2.1 of the License, or (at your option) any later version.
 *
 *      This library 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
 *      Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public
 *      License along with this library; if not, write to the Free Software
 *      Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_JPEG

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;

extern "C"
{
#include <setjmp.h>
#include <jpeglib.h>
}
#include "texture.h"


__BEGIN_YAFRAY
//****************************************************************************

// error handling for JPEGS,
// this is done so we don't exit even in case of error

METHODDEF(void) _jpeg_errmsg(j_common_ptr cinfo)
{
#ifdef __DEBUG__
  char buffer[JMSG_LENGTH_MAX];
  (*cinfo->err->format_message)(cinfo, buffer);
  cout << "JPEG Library Error: " << buffer << endl;
#endif
}

struct my_jpeg_error_mgr {
  struct jpeg_error_mgr pub;  // public fields
  jmp_buf setjmp_buffer;      // for return to caller
};

// JPEG error handler
typedef struct my_jpeg_error_mgr *error_ptr;


void my_jpeg_error_exit(j_common_ptr cinfo)
{
  error_ptr myerr = (error_ptr)cinfo->err;
  (*cinfo->err->output_message)(cinfo);
  longjmp(myerr->setjmp_buffer, 1);
}

//****************************************************************************

gBuf_t<unsigned char, 4> * load_jpeg(const char *name)
{
      struct jpeg_decompress_struct cinfo;
      struct my_jpeg_error_mgr jerr;
      FILE *input;
      gBuf_t<unsigned char, 4> *image;
      unsigned char *p;
      unsigned char **arr;

      input = fopen(name,"rb");
      if (input==NULL) {
            cout << "File " << name << " not found\n";
            return NULL;
      }
      //cout << "Loading jpeg file from " << name << "...\n";

      cinfo.err = jpeg_std_error(&jerr.pub);
      cinfo.err->output_message = _jpeg_errmsg;
      jerr.pub.error_exit = my_jpeg_error_exit;

      if (setjmp(jerr.setjmp_buffer)) {
            jpeg_destroy_decompress(&cinfo);
            fclose(input);
            return NULL;
      }

      jpeg_create_decompress(&cinfo);
      jpeg_stdio_src(&cinfo,input);
      jpeg_read_header(&cinfo,TRUE);
      bool isgray = (cinfo.out_color_space==JCS_GRAYSCALE);

      jpeg_start_decompress(&cinfo);

#ifdef __DEBUG__
      cout << "Loading image " << cinfo.output_width << " x " << cinfo.output_height << endl;
      cout << "color depth is " << cinfo.output_components*8 << " bits.\n";
#endif

      if ((cinfo.output_components!=3) && (!isgray))
      {
            cout << "Unsupported color depth: " << cinfo.output_components << endl;
            jpeg_finish_decompress(&cinfo);
            jpeg_destroy_decompress(&cinfo);
            return NULL;
      }

      image = new gBuf_t<unsigned char, 4>(cinfo.output_width, cinfo.output_height);
      if (image==NULL)
      {
            cout << "Error allocating memory\n";
            exit(1);
      }

      p = (*image)(0,0);

      //colBuf now has alpha component, so have to allocate temporary scanline buffer for color jpeg as well
      unsigned char* gbuf=NULL;
      if (isgray)
            gbuf = new unsigned char[cinfo.image_width];
      else
            gbuf = new unsigned char[cinfo.image_width*3];
      if (gbuf==NULL) {
            cout << "Error allocating memory for temporary scanline buffer\n";
            exit(1);
      }

      while (cinfo.output_scanline < cinfo.output_height) {
            arr = &gbuf;
            jpeg_read_scanlines(&cinfo, arr, 1);
            if (isgray) {
                  for (unsigned int x=0;x<cinfo.image_width;x++) {
                        *p++ = gbuf[x];
                        *p++ = gbuf[x];
                        *p++ = gbuf[x];
                        *p++ = 255;
                  }
            }
            else {
                  for (unsigned int x=0;x<cinfo.image_width*3;x+=3) {
                        *p++ = gbuf[x];
                        *p++ = gbuf[x+1];
                        *p++ = gbuf[x+2];
                        *p++ = 255;
                  }
            }
      }
      delete[] gbuf;

      jpeg_finish_decompress(&cinfo);
      jpeg_destroy_decompress(&cinfo);
      fclose(input);
      return image;
}

__END_YAFRAY

#endif

Generated by  Doxygen 1.6.0   Back to index