Logo Search packages:      
Sourcecode: libjpeg-turbo version File versions  Download package

bmp.c

/*
 * Copyright (C)2011 D. R. Commander.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name of the libjpeg-turbo Project nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>
#include <setjmp.h>
#include <errno.h>
#include "cdjpeg.h"
#include <jpeglib.h>
#include <jpegint.h>
#include "tjutil.h"
#include "bmp.h"


/* This duplicates the functionality of the VirtualGL bitmap library using
   the components from cjpeg and djpeg */


/* Error handling (based on example in example.c) */

static char errStr[JMSG_LENGTH_MAX]="No error";

00048 struct my_error_mgr
{
      struct jpeg_error_mgr pub;
      jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;

static void my_error_exit(j_common_ptr cinfo)
{
      my_error_ptr myerr=(my_error_ptr)cinfo->err;
      (*cinfo->err->output_message)(cinfo);
      longjmp(myerr->setjmp_buffer, 1);
}

/* Based on output_message() in jerror.c */

static void my_output_message(j_common_ptr cinfo)
{
      (*cinfo->err->format_message)(cinfo, errStr);
}

#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
      retval=-1;  goto bailout;}
#define _throwunix(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m,  \
      strerror(errno));  retval=-1;  goto bailout;}


static void pixelconvert(unsigned char *srcbuf, int srcpf, int srcbottomup,
      unsigned char *dstbuf, int dstpf, int dstbottomup, int w, int h)
{
      unsigned char *srcptr=srcbuf, *srcptr2;
      int srcps=tjPixelSize[srcpf];
      int srcstride=srcbottomup? -w*srcps:w*srcps;
      unsigned char *dstptr=dstbuf, *dstptr2;
      int dstps=tjPixelSize[dstpf];
      int dststride=dstbottomup? -w*dstps:w*dstps;
      int row, col;

      if(srcbottomup) srcptr=&srcbuf[w*srcps*(h-1)];
      if(dstbottomup) dstptr=&dstbuf[w*dstps*(h-1)];
      for(row=0; row<h; row++, srcptr+=srcstride, dstptr+=dststride)
      {
            for(col=0, srcptr2=srcptr, dstptr2=dstptr; col<w; col++, srcptr2+=srcps,
                  dstptr2+=dstps)
            {
                  dstptr2[tjRedOffset[dstpf]]=srcptr2[tjRedOffset[srcpf]];
                  dstptr2[tjGreenOffset[dstpf]]=srcptr2[tjGreenOffset[srcpf]];
                  dstptr2[tjBlueOffset[dstpf]]=srcptr2[tjBlueOffset[srcpf]];
            }
      }
}


int loadbmp(char *filename, unsigned char **buf, int *w, int *h, 
      int dstpf, int bottomup)
{
      int retval=0, dstps, srcpf, tempc;
      struct jpeg_compress_struct cinfo;
      struct my_error_mgr jerr;
      cjpeg_source_ptr src;
      FILE *file=NULL;

      if(!filename || !buf || !w || !h || dstpf<0 || dstpf>=TJ_NUMPF)
            _throw("loadbmp(): Invalid argument");

      if((file=fopen(filename, "rb"))==NULL)
            _throwunix("loadbmp(): Cannot open input file");

      cinfo.err=jpeg_std_error(&jerr.pub);
      jerr.pub.error_exit=my_error_exit;
      jerr.pub.output_message=my_output_message;

      if(setjmp(jerr.setjmp_buffer))
      {
            /* If we get here, the JPEG code has signaled an error. */
            retval=-1;  goto bailout;
      }

      jpeg_create_compress(&cinfo);
      if((tempc=getc(file))<0 || ungetc(tempc, file)==EOF)
            _throwunix("loadbmp(): Could not read input file")
      else if(tempc==EOF) _throw("loadbmp(): Input file contains no data");

      if(tempc=='B')
      {
            if((src=jinit_read_bmp(&cinfo))==NULL)
                  _throw("loadbmp(): Could not initialize bitmap loader");
      }
      else if(tempc=='P')
      {
            if((src=jinit_read_ppm(&cinfo))==NULL)
                  _throw("loadbmp(): Could not initialize bitmap loader");
      }
      else _throw("loadbmp(): Unsupported file type");

      src->input_file=file;
      (*src->start_input)(&cinfo, src);
      (*cinfo.mem->realize_virt_arrays)((j_common_ptr)&cinfo);

      *w=cinfo.image_width;  *h=cinfo.image_height;

      if(cinfo.input_components==1 && cinfo.in_color_space==JCS_RGB)
            srcpf=TJPF_GRAY;
      else srcpf=TJPF_RGB;

      dstps=tjPixelSize[dstpf];
      if((*buf=(unsigned char *)malloc((*w)*(*h)*dstps))==NULL)
            _throw("loadbmp(): Memory allocation failure");

      while(cinfo.next_scanline<cinfo.image_height)
      {
            int i, nlines=(*src->get_pixel_rows)(&cinfo, src);
            for(i=0; i<nlines; i++)
            {
                  unsigned char *outbuf;  int row;
                  row=cinfo.next_scanline+i;
                  if(bottomup) outbuf=&(*buf)[((*h)-row-1)*(*w)*dstps];
                  else outbuf=&(*buf)[row*(*w)*dstps];
                  pixelconvert(src->buffer[i], srcpf, 0, outbuf, dstpf, bottomup, *w,
                        nlines);
            }
            cinfo.next_scanline+=nlines;
  }

      (*src->finish_input)(&cinfo, src);

      bailout:
      jpeg_destroy_compress(&cinfo);
      if(file) fclose(file);
      if(retval<0 && buf && *buf) {free(*buf);  *buf=NULL;}
      return retval;
}


int savebmp(char *filename, unsigned char *buf, int w, int h, int srcpf,
      int bottomup)
{
      int retval=0, srcps, dstpf;
      struct jpeg_decompress_struct dinfo;
      struct my_error_mgr jerr;
      djpeg_dest_ptr dst;
      FILE *file=NULL;
      char *ptr=NULL;

      if(!filename || !buf || w<1 || h<1 || srcpf<0 || srcpf>=TJ_NUMPF)
            _throw("savebmp(): Invalid argument");

      if((file=fopen(filename, "wb"))==NULL)
            _throwunix("savebmp(): Cannot open output file");

      dinfo.err=jpeg_std_error(&jerr.pub);
      jerr.pub.error_exit=my_error_exit;
      jerr.pub.output_message=my_output_message;

      if(setjmp(jerr.setjmp_buffer))
      {
            /* If we get here, the JPEG code has signaled an error. */
            retval=-1;  goto bailout;
      }

      jpeg_create_decompress(&dinfo);
      if(srcpf==TJPF_GRAY)
      {
            dinfo.out_color_components=dinfo.output_components=1;
            dinfo.out_color_space=JCS_GRAYSCALE;
      }
      else
      {
            dinfo.out_color_components=dinfo.output_components=3;
            dinfo.out_color_space=JCS_RGB;
      }
      dinfo.image_width=w;  dinfo.image_height=h;
      dinfo.global_state=DSTATE_READY;
      dinfo.scale_num=dinfo.scale_denom=1;

      ptr=strrchr(filename, '.');
      if(ptr && !strcasecmp(ptr, ".bmp"))
      {
            if((dst=jinit_write_bmp(&dinfo, 0))==NULL)
                  _throw("savebmp(): Could not initialize bitmap writer");
      }
      else
      {
            if((dst=jinit_write_ppm(&dinfo))==NULL)
                  _throw("savebmp(): Could not initialize PPM writer");
      }

  dst->output_file=file;
      (*dst->start_output)(&dinfo, dst);
      (*dinfo.mem->realize_virt_arrays)((j_common_ptr)&dinfo);

      if(srcpf==TJPF_GRAY) dstpf=srcpf;
      else dstpf=TJPF_RGB;
      srcps=tjPixelSize[srcpf];

      while(dinfo.output_scanline<dinfo.output_height)
      {
            int i, nlines=dst->buffer_height;
            for(i=0; i<nlines; i++)
            {
                  unsigned char *inbuf;  int row;
                  row=dinfo.output_scanline+i;
                  if(bottomup) inbuf=&buf[(h-row-1)*w*srcps];
                  else inbuf=&buf[row*w*srcps];
                  pixelconvert(inbuf, srcpf, bottomup, dst->buffer[i], dstpf, 0, w,
                        nlines);
            }
            (*dst->put_pixel_rows)(&dinfo, dst, nlines);
            dinfo.output_scanline+=nlines;
  }

      (*dst->finish_output)(&dinfo, dst);

      bailout:
      jpeg_destroy_decompress(&dinfo);
      if(file) fclose(file);
      return retval;
}

const char *bmpgeterr(void)
{
      return errStr;
}

Generated by  Doxygen 1.6.0   Back to index