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

📄 pngfunc.c

📁 从sourceforge下的图像压缩源码
💻 C
字号:
/***
 * pngfunc.c
 ***
 * soucast knihovny libopen
 * 2007-04-29
 * xbarin02@stud.fit.vutbr.cz  
 ***
 * fce pro praci s PNG
 */

#include "pngfunc.h"
#include "error.h"
#include <stdlib.h>

PFrameBuff loadpng(char *fname)
{
  FILE* png_file;
  png_bytep png_sig_buff;

  if( NULL == (png_file = fopen(fname, "rb")) )
  {
    eprintf("fopen() fails!");
    return(NULL);
  }

  const png_size_t _png_sig_num_bytes = 4;

  png_sig_buff = malloc( sizeof(png_byte)*_png_sig_num_bytes );
  if( NULL == png_sig_buff)
  {
    fclose( png_file );
    eprintf("malloc() fails!");
    return(NULL);
  }

  if( fread(png_sig_buff, 1, _png_sig_num_bytes, png_file) != _png_sig_num_bytes
      || ferror(png_file) )
  {
    fclose( png_file );
    free( png_sig_buff ); 
    eprintf("fread() fails!");
    return(NULL);
  }
  
  if( png_sig_cmp( png_sig_buff, 0, _png_sig_num_bytes) )
  {
    fclose( png_file );
    free( png_sig_buff ); 
    eprintf("png_sig_cmp() fails!");
    return(NULL);
  }

  free( png_sig_buff ); 

  png_structp _png_read;
  _png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
  if(!_png_read)
  {
    fclose( png_file );
    eprintf("png_create_read_struct() fails!");
    return(NULL);
  }

  png_infop _info;
  _info = png_create_info_struct( _png_read );
  if(!_info)
  {
    fclose( png_file );
    eprintf("png_create_info_struct() fails!");
    return(NULL);
  }

  int ret = setjmp(_png_read->jmpbuf);
  if( ret )
  {
    png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL );
    fclose( png_file );
    eprintf("setjmp() fails! (%i)", ret);
    return(NULL);
  }

  png_init_io( _png_read, png_file );

  png_set_sig_bytes( _png_read, _png_sig_num_bytes );

  png_read_info( _png_read, _info );

  if(_info->bit_depth == 16)
    png_set_strip_16(_png_read);

  if(_info->color_type == PNG_COLOR_TYPE_GRAY && _info->bit_depth < 8)
    png_set_expand(_png_read);

  if(_info->color_type == PNG_COLOR_TYPE_PALETTE && _info->bit_depth < 8)
    png_set_packing(_png_read);

  if(_info->color_type == PNG_COLOR_TYPE_PALETTE )
    png_set_expand(_png_read);

  if(_info->color_type != PNG_COLOR_TYPE_PALETTE && (_info->valid & PNG_INFO_tRNS))
    png_set_expand(_png_read);

  if(_info->bit_depth < 8)
    png_set_packing(_png_read);

  if(_info->color_type == PNG_COLOR_TYPE_GRAY || _info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(_png_read);

  int _n_of_passes;
  _n_of_passes = png_set_interlace_handling(_png_read);
//  _n_of_passes = 1;

  png_read_update_info(_png_read, _info);

  uint32 w, h;
  w = _info->width;
  h = _info->height;

  png_bytepp row_pointers = malloc( sizeof(png_bytep)*_info->height );
  if( NULL == row_pointers )
  {
    png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL );
    fclose( png_file );
    eprintf("malloc() fails!");
    return(NULL);
  }

  png_uint_32 row_bytes = png_get_rowbytes( _png_read, _info );

  for( unsigned int row = 0; row < _info->height; row++ )
    if( NULL == (row_pointers[row] = malloc( sizeof(png_byte)*row_bytes )) )
    {
      for(unsigned tmp = 0; tmp < row; tmp++)
        free(row_pointers[tmp]);
      free(row_pointers);
      png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL );
      fclose( png_file );
      eprintf("malloc() fails (%u)!",row);
      return(NULL);
    }

  for( int pass = 1; pass <= _n_of_passes; pass++ )
    png_read_rows(_png_read, row_pointers, NULL, _info->height);

  PFrameBuff fbuff = malloc(sizeof(TFrameBuff));
  if( NULL == fbuff )
  {
	  png_read_end( _png_read, _info );
    for( unsigned int row = 0; row < _info->height; row++ )
      free( row_pointers[row] );
	  free( row_pointers );
    png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL );
    fclose( png_file );
    eprintf("malloc() fails!");
    return(NULL);  
  }

  fbuff->w = w;
  fbuff->h = h;
  fbuff->buff = malloc(sizeof(TPixel)*w*h);

  if( NULL == fbuff->buff )
  {
	  png_read_end( _png_read, _info );
    free(fbuff);
    for( unsigned int row = 0; row < _info->height; row++ )
      free( row_pointers[row] );
    free( row_pointers );
    png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL );
    fclose( png_file );
    eprintf("malloc() fails!");
    return(NULL);  
  }
  
	for( unsigned int row = 0, pixel = 0; row < _info->height; row++ )
  {
		for( unsigned int byte_in_row = 0; byte_in_row + (_info->channels-1) < row_bytes;
		       byte_in_row += _info->channels )
    {
			fbuff->buff[pixel].r = row_pointers[row][byte_in_row];
			fbuff->buff[pixel].g = row_pointers[row][byte_in_row + 1];
			fbuff->buff[pixel].b = row_pointers[row][byte_in_row + 2];
			pixel += 1; // next pixel in framebuffer
		}
	} 

	png_read_end( _png_read, _info );

	for( unsigned int row = 0; row < _info->height; row++ )
		free( row_pointers[row] );
	
	free( row_pointers );

	fclose(png_file); 

  png_destroy_read_struct( &_png_read, &_info, (png_infopp)NULL ); 

  return(fbuff);
}

int savepng(char *fname, PFrameBuff fbuff)
{
  png_structp _png_read;
  png_infop _info;

	_png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if(!_png_read)
  {
    eprintf("png_create_read_struct() fails!");
    return(-1);
  }

	_info = png_create_info_struct( _png_read );
  if(!_info)
  {
    eprintf("png_create_info_struct() fails!");
    return(-1);
  }

	_info->height = fbuff->h;
	_info->width = fbuff->w;
	_info->channels = 3;
	_info->rowbytes = _info->channels*fbuff->w;
	_info->color_type = PNG_COLOR_TYPE_RGB;
	_info->bit_depth = 8;
	_info->interlace_type = PNG_INTERLACE_NONE;
	_info->filter_type = PNG_FILTER_TYPE_BASE;
	_info->compression_type = PNG_COMPRESSION_TYPE_BASE;
	_info->pixel_depth = 8;
	_info->srgb_intent = 0;
	int _n_of_passes = 1; 

  FILE* png_file;
  if( NULL == (png_file = fopen(fname, "wb")) )
  {
    eprintf("fopen() fails!");
    return(-1);
	}

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if( NULL == png_ptr )
  {
		fclose(png_file);
		eprintf("png_create_write_struct() fails!");
		return(-1);
	} 

	if ( setjmp(png_jmpbuf(png_ptr)))
  {
		png_destroy_write_struct(&png_ptr, NULL);
		fclose( png_file );
		eprintf("setjmp(png_jmpbuf()) fails!");
		return(-1);
	}

	png_init_io(png_ptr, png_file);

  png_write_info( png_ptr, _info );
  
  png_bytepp row_pointers = malloc( sizeof(png_bytep)*_info->height );
  if( NULL == row_pointers )
  {
		png_destroy_write_struct(&png_ptr, NULL);
		fclose( png_file );
		eprintf("malloc() fails!");
		return(-1);
  }

  png_uint_32 row_bytes = _info->channels*_info->width;

	for( unsigned int row = 0; row < _info->height; row++ )
		if( NULL == (row_pointers[row] = malloc( sizeof(png_byte)*row_bytes )) )
    {
      for(unsigned tmp=0; tmp<row; tmp++)
        free(row_pointers[tmp]);
      free(row_pointers);
  		png_destroy_write_struct(&png_ptr, NULL);
	  	fclose( png_file );
      eprintf("malloc() fails!");
      return(-1);
    }

	for( unsigned int row = 0, pixel = 0; row < _info->height; row++)
  {
		for( unsigned int byte_in_row = 0; byte_in_row + (_info->channels-1) < row_bytes;
		      byte_in_row += _info->channels)
    {
			row_pointers[row][byte_in_row]     = fbuff->buff[pixel].r;
			row_pointers[row][byte_in_row + 1] = fbuff->buff[pixel].g;
			row_pointers[row][byte_in_row + 2] = fbuff->buff[pixel].b;
			pixel += 1; // next pixel in framebuffer
		}
	}

	for( int pass = 1; pass <= _n_of_passes; pass++ )
		png_write_rows(png_ptr, row_pointers, _info->height);

	png_write_end(png_ptr, _info );
	
	png_destroy_write_struct( &png_ptr, NULL );

	for( unsigned int row = 0; row < _info->height; row++ )
		free(row_pointers[row]);

	free(row_pointers);

	fclose(png_file);

  png_destroy_read_struct(&_png_read, &_info, (png_infopp)NULL );

  return(0);
}

⌨️ 快捷键说明

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