ImageFile.tcc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. #include <core/image/ImageFile.h>
  2. #include <core/image/ImageT.h>
  3. #include <core/image/ColorImageT.h>
  4. #include <core/image/Convert.h>
  5. #include <core/basics/stringutils.h>
  6. #include <iostream>
  7. #ifdef NICE_USELIB_LIBMAGICK
  8. #include <Magick++.h>
  9. #endif
  10. #ifdef NICE_USELIB_JPG
  11. // a little hack to handle the incompatible INT32 definitions in qt3 and libjpeg
  12. #define INT32 INT32_ALTERNATIVE
  13. extern "C" {
  14. #include <jpeglib.h>
  15. }
  16. #undef INT32
  17. #endif
  18. namespace NICE {
  19. template<class P> class ColorImageT;
  20. #ifdef NICE_USELIB_LIBMAGICK
  21. template<>
  22. void ImageFile::readerMagick ( GrayColorImageCommonImplementationT<unsigned char> *image );
  23. template<>
  24. void ImageFile::writerMagick ( const GrayColorImageCommonImplementationT<unsigned char> *image ) const;
  25. #endif
  26. template<class P>
  27. void ImageFile::reader ( GrayColorImageCommonImplementationT<P> *image )
  28. {
  29. switch ( fileType() )
  30. {
  31. #ifdef NICE_USELIB_PNG
  32. case ImageFile::PNG:
  33. readerPNG ( image );
  34. break;
  35. #endif // NICE_USELIB_PNG
  36. #ifdef NICE_USELIB_JPG
  37. case ImageFile::JPG:
  38. readerJPG ( image );
  39. break;
  40. #endif // NICE_USELIB_JPG
  41. case ImageFile::PPM_RAW:
  42. case ImageFile::PGM_RAW:
  43. readerPXM ( image );
  44. break;
  45. default:
  46. #ifdef NICE_USELIB_LIBMAGICK
  47. try {
  48. readerMagick ( image );
  49. } catch ( Magick::ErrorBlob & error ) {
  50. fthrow ( ImageException, std::string ( "Format not yet implemented. (libMagick++ error: " ) + std::string ( error.what() ) + std::string ( ")" ) );
  51. }
  52. #else
  53. fthrow ( ImageException, "Format not yet implemented. (try using libMagick++)" );
  54. #endif
  55. }
  56. }
  57. template<class P>
  58. void ImageFile::writer ( const GrayColorImageCommonImplementationT<P> *image ) const
  59. {
  60. switch ( fileType() )
  61. {
  62. case ImageFile::PNG:
  63. #ifdef NICE_USELIB_PNG
  64. writerPNG ( image );
  65. #else
  66. #ifdef NICE_USELIB_LIBMAGICK
  67. try {
  68. writerMagick ( image );
  69. } catch ( Magick::Exception ) {
  70. fthrow ( ImageException, "Format not yet implemented." );
  71. }
  72. #else
  73. fthrow ( ImageException, "Format not yet implemented. (try using libMagick)" );
  74. #endif
  75. #endif
  76. break;
  77. case ImageFile::JPG:
  78. #ifdef NICE_USELIB_JPG
  79. writerJPG ( image );
  80. #else
  81. fthrow ( ImageException, "JPEG format not supported." );
  82. #endif
  83. break;
  84. case ImageFile::PPM_RAW:
  85. if ( image->channels() == 3 )
  86. {
  87. writerPXM ( image );
  88. }
  89. else
  90. {
  91. ColorImageT<P> *rgb = grayToRGB ( *reinterpret_cast<const ImageT<P>*> ( image ) );
  92. writerPXM ( rgb );
  93. delete rgb;
  94. }
  95. break;
  96. case ImageFile::PGM_RAW:
  97. if ( image->channels() == 1 )
  98. writerPXM ( image );
  99. else {
  100. ImageT<P> *gray = rgbToGray ( *reinterpret_cast<const ColorImageT<P>*> ( image ) );
  101. writerPXM ( gray );
  102. delete gray;
  103. }
  104. break;
  105. default:
  106. #ifdef NICE_USELIB_LIBMAGICK
  107. try {
  108. writerMagick ( image );
  109. } catch ( Magick::Exception ) {
  110. fthrow ( ImageException, "Format not yet implemented." );
  111. }
  112. #else
  113. fthrow ( ImageException, "Format not yet implemented. (try using libMagick)" );
  114. #endif
  115. }
  116. }
  117. template <class P>
  118. void ImageFile::readerPXM ( GrayColorImageCommonImplementationT<P> *image )
  119. {
  120. using namespace std;
  121. // open the file
  122. ifstream file ( filename.c_str(), ios::binary );
  123. // error handling
  124. if ( !file.good() )
  125. {
  126. fthrow ( ImageException, string ( "readPXM: Cannot open " ) + filename );
  127. }
  128. if ( datapos == 0 )
  129. getPXMHeader();
  130. if ( fileheader.width != image->widthInline() || fileheader.height != image->heightInline() ) {
  131. image->resize ( fileheader.width, fileheader.height );
  132. }
  133. file.seekg ( datapos );
  134. int srcbytedepth = fileheader.bitdepth / 8;
  135. if ( srcbytedepth == image->bytedepth() ) { // same bit depth
  136. if ( fileformat == PPM_RAW || fileformat == PGM_RAW )
  137. {
  138. // simple case just write into image
  139. if ( fileheader.channel == image->channels() )
  140. {
  141. for ( int y = 0; y < fileheader.height; y++ )
  142. {
  143. file.read ( reinterpret_cast<char*>
  144. ( image->getPixelPointerY ( y ) ), fileheader.width*fileheader.channel*srcbytedepth );
  145. }
  146. }
  147. // it is a gray image but should be converted to a rgb image
  148. else if ( fileheader.channel == 1 )
  149. {
  150. for ( int y = 0; y < fileheader.height; y++ ) {
  151. P line[fileheader.width];
  152. file.read ( reinterpret_cast<char *> ( line ), fileheader.width );
  153. P *target = image->getPixelPointerY ( y );
  154. P *src = line;
  155. for ( int x = 0; x < fileheader.width; x++, src++ ) {
  156. for ( int i = 0;i < image->channels();i++, target++ )
  157. *target = *src;
  158. }
  159. }
  160. }
  161. // it is a rgb image that should be converted to a gray image
  162. else if ( fileheader.channel == 3 && image->channels() == 1 )
  163. {
  164. ColorImageT<P> rgb ( fileheader.width, fileheader.height );
  165. for ( int y = 0; y < fileheader.height; y++ )
  166. {
  167. file.read ( reinterpret_cast<char*>
  168. ( rgb.getPixelPointerY ( y ) ), fileheader.width*fileheader.channel*srcbytedepth );
  169. }
  170. rgbToGray ( rgb, dynamic_cast<ImageT<P> *> ( image ) );
  171. }
  172. else
  173. {
  174. fthrow ( ImageException, "Format (channels) not yet implemented." );
  175. }
  176. } else {
  177. fthrow ( ImageException, "Format not yet implemented." );
  178. }
  179. }
  180. // different bitdephs
  181. else
  182. {
  183. if ( fileformat == PPM_RAW || fileformat == PGM_RAW ) {
  184. if ( fileheader.channel == 1 || ( fileheader.channel == 3 && image->channels() == 3 ) ) { // have to cast
  185. for ( int y = 0; y < fileheader.height; y++ ) {
  186. Ipp8u line[fileheader.width*fileheader.channel*srcbytedepth];
  187. file.read ( reinterpret_cast<char *> ( line ), fileheader.width*fileheader.channel*srcbytedepth );
  188. P *target = image->getPixelPointerY ( y );
  189. Ipp8u *src = line;
  190. if ( srcbytedepth == 1 ) {
  191. for ( int x = 0; x < fileheader.width; x++ ) {
  192. for ( int i = 0;i < fileheader.channel;i++, src++, target++ )
  193. *target = static_cast<P> ( *src );
  194. }
  195. } else {
  196. for ( int x = 0; x < fileheader.width; x++ ) {
  197. for ( int i = 0;i < fileheader.channel;i++, src += srcbytedepth, target++ )
  198. * target = static_cast<P> ( *reinterpret_cast<Ipp16u *> ( src ) );
  199. }
  200. }
  201. }
  202. } else if ( fileheader.channel == 3 && image->channels() == 1 ) { // have to cast and to convert
  203. ColorImageT<P> rgb ( fileheader.width, fileheader.height );
  204. for ( int y = 0; y < fileheader.height; y++ ) {
  205. Ipp8u line[fileheader.width*fileheader.channel*srcbytedepth];
  206. file.read ( reinterpret_cast<char *> ( line ), fileheader.width*fileheader.channel*srcbytedepth );
  207. P *target = rgb.getPixelPointerY ( y );
  208. Ipp8u *src = line;
  209. if ( srcbytedepth == 1 ) {
  210. for ( int x = 0; x < fileheader.width; x++ ) {
  211. for ( int i = 0;i < fileheader.channel;i++, src++, target++ )
  212. *target = static_cast<P> ( *src );
  213. }
  214. } else {
  215. for ( int x = 0; x < fileheader.width; x++ ) {
  216. for ( int i = 0;i < fileheader.channel;i++, src += srcbytedepth, target++ )
  217. * target = static_cast<P> ( *reinterpret_cast<Ipp16u *> ( src ) );
  218. }
  219. }
  220. }
  221. rgbToGray ( rgb, dynamic_cast<ImageT<P> *> ( image ) );
  222. } else {
  223. fthrow ( ImageException, "Format (channels) not yet implemented." );
  224. }
  225. } else {
  226. fthrow ( ImageException, "Format not yet implemented." );
  227. }
  228. }
  229. }
  230. #ifdef NICE_USELIB_LIBMAGICK
  231. template<class P>
  232. void ImageFile::readerMagick ( GrayColorImageCommonImplementationT<P> *image )
  233. {
  234. fthrow ( ImageException, "Format not yet implemented (only available for standard images)." );
  235. }
  236. template<class P>
  237. void ImageFile::writerMagick ( const GrayColorImageCommonImplementationT<P> *image ) const
  238. {
  239. fthrow ( ImageException, "Format not yet implemented (only available for standard images)." );
  240. }
  241. #endif
  242. template <class P>
  243. void ImageFile::writerPXM ( const GrayColorImageCommonImplementationT<P> *image ) const {
  244. using namespace std;
  245. ofstream file ( filename.c_str(), ios::binary );
  246. if ( image->channels() == 1 )
  247. file << "P5" << endl;
  248. else if ( image->channels() == 3 )
  249. file << "P6" << endl;
  250. else {
  251. string msg = "Cannot write a ";
  252. msg += itostr ( image->channels() );
  253. msg += "-channel format. This is not yet implemented.";
  254. fthrow ( ImageException, msg );
  255. }
  256. file << image->widthInline() << " " << image->heightInline() << endl;
  257. file << static_cast<int> ( std::pow ( 2.0, image->bitdepth() ) - 1 ) << endl;
  258. for ( int y = 0; y < image->heightInline(); y++ ) {
  259. file.write ( reinterpret_cast<const char *> ( image->getPixelPointerY ( y ) ), image->widthInline() *image->channels() *image->bytedepth() );
  260. }
  261. file.close();
  262. }
  263. #ifdef NICE_USELIB_PNG
  264. template<class P>
  265. void ImageFile::readerPNG ( GrayColorImageCommonImplementationT<P> *image )
  266. {
  267. FILE* pFile;
  268. // open image file
  269. if ( ( pFile = fopen ( filename.c_str(), "rb" ) ) == NULL ) {
  270. fthrow ( ImageException, "ImageFile::readerPNG: Cannot open " + filename );
  271. }
  272. // read header
  273. const int headersize = 8; // 8 is the maximum size that can be checked
  274. png_byte header[headersize];
  275. fread ( header, 1, headersize, pFile );
  276. if ( png_sig_cmp ( header, 0, headersize ) ) {
  277. fclose ( pFile );
  278. fthrow ( ImageException, "Image is not a PNG file." );
  279. }
  280. /* initialize stuff */
  281. png_structp png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
  282. if ( !png_ptr ) {
  283. fclose ( pFile );
  284. fthrow ( ImageException, "png_create_read_struct failed" );
  285. }
  286. png_infop info_ptr = png_create_info_struct ( png_ptr );
  287. if ( !info_ptr ) {
  288. fclose ( pFile );
  289. fthrow ( ImageException, "png_create_info_struct failed" );
  290. }
  291. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  292. fclose ( pFile );
  293. fthrow ( ImageException, "Error during init_io" );
  294. }
  295. png_init_io ( png_ptr, pFile );
  296. png_set_sig_bytes ( png_ptr, headersize );
  297. png_read_info ( png_ptr, info_ptr );
  298. int width = info_ptr->width;
  299. int height = info_ptr->height;
  300. png_byte color_type = info_ptr->color_type;
  301. png_byte bit_depth = info_ptr->bit_depth;
  302. // resize image if necessary
  303. if ( width != image->widthInline() || height != image->heightInline() ) {
  304. image->resize ( width, height );
  305. }
  306. //int number_of_passes = png_set_interlace_handling(png_ptr);
  307. /** expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
  308. transparency chunks to full alpha channel; strip 16-bit-per-sample
  309. images to 8 bits per sample; and convert grayscale to RGB[A] */
  310. if ( color_type == PNG_COLOR_TYPE_PALETTE )
  311. png_set_expand ( png_ptr );
  312. if ( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
  313. png_set_expand ( png_ptr );
  314. if ( png_get_valid ( png_ptr, info_ptr, PNG_INFO_tRNS ) )
  315. png_set_expand ( png_ptr );
  316. if ( image->bitdepth() == 8 && bit_depth == 16 ) {
  317. png_set_strip_16 ( png_ptr );
  318. }
  319. if ( image->bitdepth() == 16 && bit_depth == 8 ) {
  320. fthrow ( ImageException, "convertion from 16 to 8 bit not implemented." );
  321. }
  322. switch ( image->channels() ) {
  323. case 1:
  324. if ( color_type == PNG_COLOR_TYPE_RGBA ||
  325. color_type == PNG_COLOR_TYPE_RGB ) {
  326. png_set_rgb_to_gray_fixed ( png_ptr, 1, -1, -1 );
  327. }
  328. if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
  329. png_set_strip_alpha ( png_ptr );
  330. break;
  331. case 3:
  332. if ( color_type == PNG_COLOR_TYPE_RGBA )
  333. png_set_strip_alpha ( png_ptr );
  334. if ( color_type == PNG_COLOR_TYPE_GRAY ||
  335. color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
  336. png_set_gray_to_rgb ( png_ptr );
  337. break;
  338. case 4:
  339. break;
  340. default:
  341. fthrow ( ImageException, "No or invalid color image->channels()" );
  342. break;
  343. }
  344. png_read_update_info ( png_ptr, info_ptr );
  345. // read file
  346. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  347. fclose ( pFile );
  348. fthrow ( ImageException, "Error during read_image" );
  349. }
  350. png_bytep * row_pointers = new png_bytep[height];
  351. for ( int y = 0; y < height; y++ )
  352. row_pointers[y] = reinterpret_cast<png_bytep> ( image->getPixelPointerY ( y ) );
  353. png_read_image ( png_ptr, row_pointers );
  354. delete [] row_pointers;
  355. png_destroy_read_struct ( &png_ptr, &info_ptr, NULL );
  356. fclose ( pFile );
  357. }
  358. template<>
  359. void ImageFile::readerPNG ( GrayColorImageCommonImplementationT<Ipp32f> *image );
  360. template<class P>
  361. void ImageFile::writerPNG ( const GrayColorImageCommonImplementationT<P> *image ) const
  362. {
  363. FILE *pfile;
  364. // open image file
  365. if ( ( pfile = fopen ( filename.c_str(), "wb" ) ) == NULL )
  366. fthrow ( ImageException, "ImageFile::writerPNG: Cannot write " + filename );
  367. png_structp png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, png_voidp_NULL,
  368. png_error_ptr_NULL, png_error_ptr_NULL );
  369. if ( !png_ptr ) {
  370. fclose ( pfile );
  371. fthrow ( ImageException, "png_create_write_struct failed" );
  372. }
  373. png_infop info_ptr = png_create_info_struct ( png_ptr );
  374. if ( !info_ptr ) {
  375. png_destroy_write_struct ( &png_ptr, ( png_infopp ) NULL );
  376. fclose ( pfile );
  377. fthrow ( ImageException, "png_create_info_struct failed" );
  378. }
  379. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  380. png_destroy_write_struct ( &png_ptr, &info_ptr );
  381. fclose ( pfile );
  382. fthrow ( ImageException, "Error during write_image" );
  383. }
  384. png_init_io ( png_ptr, pfile );
  385. png_infop png_info_ptr = png_create_info_struct ( png_ptr );
  386. int bit_depth = image->bitdepth();
  387. int color_type;
  388. switch ( image->channels() ) {
  389. case 1:
  390. color_type = PNG_COLOR_TYPE_GRAY;
  391. break;
  392. case 2:
  393. color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  394. break;
  395. case 3:
  396. color_type = PNG_COLOR_TYPE_RGB;
  397. break;
  398. case 4:
  399. color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  400. break;
  401. default:
  402. fthrow ( ImageException, "No or invalid color channels" );
  403. break;
  404. }
  405. int interlace_type = PNG_INTERLACE_NONE;
  406. png_set_IHDR ( png_ptr, png_info_ptr, image->widthInline(), image->heightInline(),
  407. bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
  408. /* turn on or off filtering, and/or choose
  409. specific filters. You can use either a single
  410. PNG_FILTER_VALUE_NAME or the logical OR of one
  411. or more PNG_FILTER_NAME masks. */
  412. png_set_filter ( png_ptr, 0, PNG_FILTER_AVG );
  413. /* set the zlib compression level */
  414. png_set_compression_level ( png_ptr, Z_BEST_COMPRESSION );
  415. //png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
  416. /* set other zlib parameters */
  417. /* png_set_compression_mem_level(png_ptr, 8);
  418. png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
  419. png_set_compression_window_bits(png_ptr, 15);
  420. png_set_compression_buffer_size(png_ptr, 8192);
  421. png_set_compression_method(png_ptr, 8); */
  422. png_write_info ( png_ptr, png_info_ptr );
  423. for ( int y = 0; y < image->heightInline(); y++ ) {
  424. //const P *prow=image->getPixelPointerY(y);
  425. png_byte row[image->widthInline() *image->channels() *image->bytedepth() ];
  426. memcpy ( row, image->getPixelPointerY ( y ), image->widthInline() *image->channels() *image->bytedepth() );
  427. png_write_row ( png_ptr, row );
  428. }
  429. png_write_end ( png_ptr, info_ptr );
  430. png_destroy_write_struct ( &png_ptr, &info_ptr );
  431. fclose ( pfile );
  432. }
  433. #endif
  434. #ifdef NICE_USELIB_JPG
  435. template<class P>
  436. void ImageFile::readerJPG ( GrayColorImageCommonImplementationT<P> *image )
  437. {
  438. struct jpeg_decompress_struct cinfo;
  439. struct jpeg_error_mgr jerr;
  440. FILE* pFile;
  441. if ( ( pFile = fopen ( filename.c_str(), "rb" ) ) == NULL )
  442. fthrow ( ImageException, "ImageFile::readerJPG: Cannot open " + filename );
  443. cinfo.err = jpeg_std_error ( &jerr );
  444. jpeg_create_decompress ( &cinfo );
  445. jpeg_stdio_src ( &cinfo, pFile );
  446. jpeg_read_header ( &cinfo, FALSE );
  447. if ( image->channels() != 1 && image->channels() != 3 )
  448. fthrow ( ImageException, "Format not yet supported" );
  449. cinfo.out_color_space = image->channels() == 1 ? JCS_GRAYSCALE : JCS_RGB;
  450. jpeg_start_decompress ( &cinfo );
  451. int row_stride = cinfo.output_width * cinfo.output_components;
  452. JSAMPARRAY buffer = ( *cinfo.mem->alloc_sarray ) ( ( j_common_ptr ) & cinfo, JPOOL_IMAGE, row_stride, 1 );
  453. // resize image if necessary
  454. int width = cinfo.output_width;
  455. int height = cinfo.output_height;
  456. if ( width != image->widthInline() || height != image->heightInline() )
  457. image->resize ( width, height );
  458. // Bilddaten zeilenweise einlesen
  459. for ( int y = 0; y < height; ++y ) {
  460. if ( !jpeg_read_scanlines ( &cinfo, buffer, 1 ) )
  461. fthrow ( ImageException, "ImageFile::readerJPG: Some Error occured while reading " + filename );
  462. if ( sizeof ( P ) == sizeof ( Ipp8u ) )
  463. memcpy ( image->getPixelPointerY ( y ), buffer[0], width*image->channels() );
  464. else {
  465. const Ipp8u* pSrc = buffer[0];
  466. P* pDst = image->getPixelPointerY ( y );
  467. for ( int x = 0; x < width*image->channels(); ++x, ++pSrc, ++pDst )
  468. if ( *pSrc < std::numeric_limits<P>::min() )
  469. *pDst = std::numeric_limits<P>::min();
  470. else if ( *pSrc > std::numeric_limits<P>::max() )
  471. *pDst = std::numeric_limits<P>::max();
  472. else
  473. *pDst = static_cast<Ipp8u> ( *pSrc );
  474. }
  475. }
  476. jpeg_finish_decompress ( &cinfo );
  477. jpeg_destroy_decompress ( &cinfo );
  478. fclose ( pFile );
  479. }
  480. template<class P>
  481. void ImageFile::writerJPG ( const GrayColorImageCommonImplementationT<P> *image, const int quality ) const
  482. {
  483. FILE *pfile;
  484. if ( ( pfile = fopen ( filename.c_str(), "wb" ) ) == NULL )
  485. fthrow ( ImageException, "ImageFile::writerJPG: Cannot write " + filename );
  486. struct jpeg_compress_struct cinfo;
  487. struct jpeg_error_mgr jerr;
  488. cinfo.err = jpeg_std_error ( &jerr );
  489. jpeg_create_compress ( &cinfo );
  490. jpeg_stdio_dest ( &cinfo, pfile );
  491. cinfo.image_width = image->widthInline();
  492. cinfo.image_height = image->heightInline();
  493. cinfo.input_components = image->channels();
  494. if ( image->channels() != 1 && image->channels() != 3 )
  495. fthrow ( ImageException, "Format not yet supported" );
  496. cinfo.in_color_space = image->channels() == 1 ? JCS_GRAYSCALE : JCS_RGB;
  497. jpeg_set_defaults ( &cinfo );
  498. jpeg_set_quality ( &cinfo, quality, TRUE );
  499. jpeg_start_compress ( &cinfo, TRUE );
  500. int width = cinfo.image_width;
  501. int height = cinfo.image_height;
  502. JSAMPROW row_pointer[1];
  503. row_pointer[0] = new Ipp8u[width*image->channels() ];
  504. for ( int y = 0; y < height; ++y ) {
  505. if ( sizeof ( P ) == sizeof ( Ipp8u ) )
  506. memcpy ( row_pointer[0], image->getPixelPointerY ( y ), width*image->channels() );
  507. else {
  508. const P* pSrc = image->getPixelPointerY ( y );
  509. Ipp8u* pDst = row_pointer[0];
  510. for ( int x = 0; x < width*image->channels(); ++x, ++pSrc, ++pDst )
  511. if ( *pSrc < std::numeric_limits<Ipp8u>::min() )
  512. *pDst = std::numeric_limits<Ipp8u>::min();
  513. else if ( *pSrc > std::numeric_limits<Ipp8u>::max() )
  514. *pDst = std::numeric_limits<Ipp8u>::max();
  515. else
  516. *pDst = static_cast<Ipp8u> ( *pSrc );
  517. }
  518. jpeg_write_scanlines ( &cinfo, row_pointer, 1 );
  519. }
  520. jpeg_finish_compress ( &cinfo );
  521. fclose ( pfile );
  522. jpeg_destroy_compress ( &cinfo );
  523. }
  524. #endif
  525. }