⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpegfile.cpp

📁 医学图象处理系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////
//	JpegFile - A C++ class to allow reading and writing of
//	RGB and Grayscale JPEG images.
//	It is based on the IJG V.6 code.
//
//	This class Copyright 1997, Chris Losinger
//	This is free to use and modify provided my name is 
//	included.
//
//	See jpegfile.h for usage.
//
////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "image.h"
#include "JpegFile.h"

#include <stdio.h>

#ifdef __cplusplus
	extern "C" {
#endif // __cplusplus

#include "jpeglib.h"

#ifdef __cplusplus
	}
#endif // __cplusplus


//<setjmp.h> is used for the optional error recovery mechanism shown in
//the second part of the example.
#include <setjmp.h>

// error handler, to avoid those pesky exit(0)'s
struct my_error_mgr 
{
  struct jpeg_error_mgr pub;	/* "public" fields */
  jmp_buf setjmp_buffer;	/* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;

METHODDEF(void) my_error_exit (j_common_ptr cinfo);


//	to handle fatal errors.
//	the original JPEG code will just exit(0). can't really
//	do that in Windows....
METHODDEF(void) my_error_exit (j_common_ptr cinfo)
{
	// cinfo->err really points to a my_error_mgr struct, so coerce pointer 
	my_error_ptr myerr = (my_error_ptr) cinfo->err;

	char buffer[JMSG_LENGTH_MAX];

	// Create the message 
	(*cinfo->err->format_message) (cinfo, buffer);

	// Always display the message. 
	MessageBox(NULL,buffer,"JPEG Fatal Error",MB_ICONSTOP);


	// Return control to the setjmp point 
	longjmp(myerr->setjmp_buffer, 1);
}

//	constructor doesn't do much - there's no real class here...
JpegFile::JpegFile()
{
}

JpegFile::~JpegFile()
{
}

//	read a JPEG file
BOOL JpegFile::JpegFileToRGB(CString fileName,  BYTE** lpimg)

{
	// basic code from IJG Jpeg Code v6 example.c
	UINT width,  height, Depth;
	// This struct contains the JPEG decompression parameters and pointers to
	// working space (which is allocated as needed by the JPEG library).	
	struct jpeg_decompress_struct cinfo;
	// We use our private extension JPEG error handler.
	// Note that this struct must live as long as the main JPEG parameter
	// struct, to avoid dangling-pointer problems.
 	struct my_error_mgr jerr;
	// More stuff  
	FILE * infile = NULL;	// source file  

	JSAMPARRAY buffer;		// Output row buffer      
	int  row_stride;		// physical row width in output buffer  
	char buf[250];

	// In this example we want to open the input file before doing anything else,
	// so that the setjmp() error recovery below can assume the file is open.
	// VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
	// requires it in order to read binary files.	 
	if ((infile = fopen(fileName, "rb")) == NULL) 
	{
		sprintf(buf, "JPEG :\nCan't open %s\n", fileName);
		AfxMessageBox(buf);
		return NULL;
	}

	// 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);
	jerr.pub.error_exit = my_error_exit;

	// Establish the setjmp return context for my_error_exit to use.  
	if( setjmp(jerr.setjmp_buffer) )
	{
		// If we get here, the JPEG code has signaled an error.
		// We need to clean up the JPEG object, close the input file, and return.
		jpeg_destroy_decompress(&cinfo);
		if( infile != NULL ) fclose(infile);
		return NULL;
	}
	
    //TRACE("Size of cinfo is %d\n",sizeof(cinfo));
	//TRACE("think Size of cinfo is %d\n",sizeof(struct jpeg_compress_struct));
	// Now we can initialize the JPEG decompression object.  
	jpeg_create_decompress(&cinfo);

	// Step 2: specify data source (eg, a file) 
    // cinfo.dither_mode = JDITHER_NONE;	
	jpeg_stdio_src(&cinfo, infile);

	// Step 3: read file parameters with jpeg_read_header()
	(void) 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  

	// In this example, we don't need to change any of the defaults set by
	// jpeg_read_header(), so we do nothing here.

	// Step 5: Start decompressor 
	(void) jpeg_start_decompress(&cinfo);
	// We can ignore the return value since suspension is not possible
	// with the stdio data source.

	// 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.
	// get our buffer set to hold data
	// alloc and open our new buffer	
    cinfo.dct_method  = JDCT_IFAST;
	// how big is this thing gonna be?
	width  = cinfo.output_width;
	height = cinfo.output_height;
	Depth  = cinfo.num_components;
	
	// 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 row; 
	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.
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
		// Assume put_scanline_someplace wants a pointer and sample count. 
		// asuumer all 3-components are RGBs
		row = cinfo.output_scanline- 1;
		if (cinfo.out_color_components==3) 
		{
			RGBTRIPLE* pixptr = (RGBTRIPLE*)lpimg[row];
			BYTE *lptemp = buffer[0];
			for(UINT i= 0; i<width; i++, pixptr++)
			{
				pixptr->rgbtRed   = *lptemp++;
				pixptr->rgbtGreen = *lptemp++;
				pixptr->rgbtBlue  = *lptemp++;
			}
		}
		else if (cinfo.out_color_components==1)
		{
			memcpy(lpimg[row], buffer[0], width);
		}
	}

	// Step 7: Finish decompression
	(void) jpeg_finish_decompress(&cinfo);
	// We can ignore the return value since suspension is not possible
	// with the stdio data source.
	// Step 8: Release JPEG decompression object  
	// This is an important step since it will release a good deal of memory.
	jpeg_destroy_decompress(&cinfo);
	// After finish_decompress, we can close the input file.
	// Here we postpone it until after no more JPEG errors are possible,
	// so as to simplify the setjmp error logic above.  (Actually, I don't
	// think that jpeg_destroy can do an error exit, but why assume anything...)
	fclose(infile);
	// At this point you may want to check to see whether any corrupt-data
	// warnings occurred (test whether jerr.pub.num_warnings is nonzero).
	return true;
}

BOOL JpegFile::GetJPGDimensions(CString fileName,
								UINT &width,
								UINT &height,
								UINT &Depth)
{
	// basic code from IJG Jpeg Code v6 example.c

	// This struct contains the JPEG decompression parameters and pointers to
	// working space (which is allocated as needed by the JPEG library).
	struct jpeg_decompress_struct cinfo;
	// We use our private extension JPEG error handler.
	// Note that this struct must live as long as the main JPEG parameter
	// struct, to avoid dangling-pointer problems.
	struct my_error_mgr jerr;
	// More stuff 
	FILE * infile=NULL;
	char buf[250];

	// In this example we want to open the input file before doing anything else,
	// so that the setjmp() error recovery below can assume the file is open.
	// VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
	// requires it in order to read binary files.

	if ((infile = fopen(fileName, "rb")) == NULL) 
	{
		sprintf(buf, "JPEG :\nCan't open %s\n", fileName);
		AfxMessageBox(buf);
		return FALSE;
	}

	// 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);
	jerr.pub.error_exit = my_error_exit;


	// Establish the setjmp return context for my_error_exit to use.
	if (setjmp(jerr.setjmp_buffer)) 
	{
		// If we get here, the JPEG code has signaled an error.
		//  We need to clean up the JPEG object, close the input file, and return.
		jpeg_destroy_decompress(&cinfo);

		if (infile!=NULL) fclose(infile);
		return FALSE;
	}

	// Now we can initialize the JPEG decompression object.
	jpeg_create_decompress(&cinfo);

	// Step 2: specify data source (eg, a file)

	jpeg_stdio_src(&cinfo, infile);

	// Step 3: read file parameters with jpeg_read_header()

	(void) 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.
	// how big is this thing ?
	width  = cinfo.image_width;
	height = cinfo.image_height;
	Depth  = cinfo.num_components << 3;
	// Step 8: Release JPEG decompression object
	// This is an important step since it will release a good deal of memory.
	jpeg_destroy_decompress(&cinfo);

	// After finish_decompress, we can close the input file.
	// Here we postpone it until after no more JPEG errors are possible,
	// so as to simplify the setjmp error logic above.  (Actually, I don't
	// think that jpeg_destroy can do an error exit, but why assume anything...)
	fclose(infile);

	return TRUE;
}

BOOL JpegFile::RGBToJpegFile(CString fileName, 
							BYTE **dataBuf,
							UINT widthPix,
							UINT height,
							BOOL color, 
							int  quality)
{
	if (dataBuf==NULL || widthPix==0 || height==0) return FALSE;

	struct jpeg_compress_struct cinfo;
	// More stuff 
	FILE * outfile=NULL;			// target file 

	struct my_error_mgr jerr;

	// Step 1: allocate and initialize JPEG compression object 
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;

	// Establish the setjmp return context for my_error_exit to use. 
	if (setjmp(jerr.setjmp_buffer)) 
	{
		// If we get here, the JPEG code has signaled an error.
		// We need to clean up the JPEG object, close the input file, and return. 
		jpeg_destroy_compress(&cinfo);

		if (outfile!=NULL) fclose(outfile);
		return FALSE;
	}

	// 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. 
	if ((outfile = fopen(fileName, "wb")) == NULL) 
	{
		char buf[250];
		sprintf(buf, "JpegFile :\nCan't open %s\n", fileName);
		AfxMessageBox(buf);
		return FALSE;
	}

	jpeg_stdio_dest(&cinfo, outfile);

	// 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  = widthPix; 	// image widthPix and height, in pixels 
	cinfo.image_height = height;
	if (color) 
	{
		cinfo.input_components = 3;		// # of color components per pixel  
		cinfo.in_color_space = JCS_RGB; 	// colorspace of input image  
	}
	else
	{
		cinfo.input_components = 1;		//# of color components per pixel  
		cinfo.in_color_space = JCS_GRAYSCALE; 	// colorspace of input image 
	}

    // 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, 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.

	BYTE *outRow;
	if( color )
	{
		UINT i;
		RGBTRIPLE* pixptr;
		BYTE *lptemp;
		outRow = new BYTE[widthPix * 3];
		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.
			pixptr = (RGBTRIPLE*)dataBuf[cinfo.next_scanline];
			lptemp = outRow;
			for(i= 0; i<widthPix; i++, pixptr++)
			{
				*lptemp++ = pixptr->rgbtRed  ;
				*lptemp++ = pixptr->rgbtGreen;
				*lptemp++ = pixptr->rgbtBlue ;
			}
	
			(void) jpeg_write_scanlines(&cinfo, &outRow, 1);
		}
		if(outRow != NULL) delete []outRow;
	}
	else
	{
		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.
			outRow = dataBuf[cinfo.next_scanline];
			(void) jpeg_write_scanlines(&cinfo, &outRow, 1);
		}
	}
    // Step 6: Finish compression  
    jpeg_finish_compress(&cinfo);
    // After finish_compress, we can close the output file.  
    fclose(outfile);
    // 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 TRUE;
}

//	swap Rs and Bs

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -