// This is a hack into octave
// based on jpgwrite.c by jpgread by Drea Thomas, The Mathworks, and the
// examples in the IJG distribution.
//
// (C) 1998 Andy Adler. This code is in the public domain
// USE THIS CODE AT YOUR OWN RISK
//
// $Id: jpgwrite.cc,v 1.3 2002/11/02 10:40:31 pkienzle Exp $
//
#include <octave/oct.h>
#include <iostream>
#ifdef __cplusplus
extern "C" {
#endif
#include "jpeglib.h"
#ifdef __cplusplus
} //extern "C"
#endif
#define GRAYIMAGES
/*
* Simple jpeg writing MEX-file.
*
* Synopsis:
* jpgwrite(filename,r,g,b,quality)
*
* Compilation:
* First, try
* mkoctfile jpgwrite.cc -ljpeg
*
* If this doesn't work, then do
*
* Calls the jpeg library which is part of
* "The Independent JPEG Group's JPEG software" collection.
*
* The jpeg library came from,
*
* ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6.tar.gz
*/
DEFUN_DLD (jpgwrite, args, ,
"JPGWRITE Write a JPEG file to disk.\n\
jpgwrite('filename',R,G,B,quality) writes the specified file\n\
using the Red, Green, and Blue intensity matrices, at the given quality.\n\
\n\
jpgwrite('filename',M,quality) writes a grey-scale image.\n\
\n\
Data must be [0 255] or the high bytes will be lost\n\
\n\
If specified, quality should be in the range 1-100 and will default to \n\
75 if not specified. 100 is best quality, 1 is best compression.\n\
\n\
See also JPGREAD")
{
octave_value_list retval;
int nargin = args.length();
FILE * outfile;
JSAMPARRAY buffer;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int quality=75; //default value
//
// We bail out if the input parameters are bad
//
if (nargin < 2 || !args(0).is_string() ) {
print_usage ("jpgwrite");
return retval;
}
//
// Open jpg file
//
std::string filename = args(0).string_value();
if ((outfile = fopen(filename.c_str(), "wb")) == NULL) {
error("Couldn't open file");
return retval;
}
//
// Set Jpeg parameters
//
if (nargin == 3) {
quality= (int) args(2).double_value();
} else if (nargin == 5) {
quality= (int) args(4).double_value();
}
//
// Initialize the jpeg library
// Read the jpg header to get info about size and color depth
//
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
//
// set parameters for compression
//
if ( nargin <= 3 ) {
//
// we're here because only one matrix of grey scale values was provided
//
Matrix avg= args(1).matrix_value();
long image_width = args(1).columns();
long image_height = args(1).rows();
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
#ifdef GRAYIMAGES
cinfo.input_components = 1;
cinfo.input_components = JCS_GRAYSCALE;
#else
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
#endif
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
//
// start compressor
//
jpeg_start_compress(&cinfo, TRUE);
//
// Allocate buffer for one scan line
//
long row_stride = image_width * cinfo.input_components ;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
//
// Now, loop thru each of the scanlines. For each, copy the image
// data from the buffer, data must be [0 255]
//
for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
for(unsigned long i=0; i<cinfo.image_width; i++) {
#ifdef GRAYIMAGES
buffer[0][i] = (unsigned char) avg(j,i);
#else
buffer[0][i*3+0] = (unsigned char) avg(j,i);
buffer[0][i*3+1] = (unsigned char) avg(j,i);
buffer[0][i*3+2] = (unsigned char) avg(j,i);
#endif
}
jpeg_write_scanlines(&cinfo, buffer,1);
}
} // if nargin <= 3
else {
//
// we're here because red green and blue matrices were provided
// we assume that they're the same size
//
Matrix red = args(1).matrix_value();
Matrix green= args(2).matrix_value();
Matrix blue = args(3).matrix_value();
long image_width = args(1).columns();
long image_height = args(1).rows();
if ( args(2).columns() != image_width ||
args(3).columns() != image_width ||
args(2).rows() != image_height ||
args(3).rows() != image_height ) {
error("R,G,B matrix sizes aren't the same");
return retval;
}
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE );
//
// start compressor
//
jpeg_start_compress(&cinfo, TRUE);
//
// Allocate buffer for one scan line
//
long row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
//
// Now, loop thru each of the scanlines. For each, copy the image
// data from the buffer, data must be [0 255]
//
for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
for(unsigned long i=0; i<cinfo.image_width; i++) {
buffer[0][i*3+0] = (unsigned char) red(j,i);
buffer[0][i*3+1] = (unsigned char) green(j,i);
buffer[0][i*3+2] = (unsigned char) blue(j,i);
}
jpeg_write_scanlines(&cinfo, buffer,1);
}
} // else nargin > 3
//
// Clean up
//
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
return retval;
}
syntax highlighted by Code2HTML, v. 0.9.1