ImageFile.tcc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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 = new P[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. delete [] line;
  159. }
  160. }
  161. }
  162. // it is a rgb image that should be converted to a gray image
  163. else if ( fileheader.channel == 3 && image->channels() == 1 )
  164. {
  165. ColorImageT<P> rgb ( fileheader.width, fileheader.height );
  166. for ( int y = 0; y < fileheader.height; y++ )
  167. {
  168. file.read ( reinterpret_cast<char*>
  169. ( rgb.getPixelPointerY ( y ) ), fileheader.width*fileheader.channel*srcbytedepth );
  170. }
  171. rgbToGray ( rgb, dynamic_cast<ImageT<P> *> ( image ) );
  172. }
  173. else
  174. {
  175. fthrow ( ImageException, "Format (channels) not yet implemented." );
  176. }
  177. } else {
  178. fthrow ( ImageException, "Format not yet implemented." );
  179. }
  180. }
  181. // different bitdephs
  182. else
  183. {
  184. if ( fileformat == PPM_RAW || fileformat == PGM_RAW ) {
  185. if ( fileheader.channel == 1 || ( fileheader.channel == 3 && image->channels() == 3 ) ) { // have to cast
  186. for ( int y = 0; y < fileheader.height; y++ ) {
  187. Ipp8u *line = new Ipp8u[fileheader.width*fileheader.channel*srcbytedepth];
  188. file.read ( reinterpret_cast<char *> ( line ), fileheader.width*fileheader.channel*srcbytedepth );
  189. P *target = image->getPixelPointerY ( y );
  190. Ipp8u *src = line;
  191. if ( srcbytedepth == 1 ) {
  192. for ( int x = 0; x < fileheader.width; x++ ) {
  193. for ( int i = 0;i < fileheader.channel;i++, src++, target++ )
  194. *target = static_cast<P> ( *src );
  195. }
  196. } else {
  197. for ( int x = 0; x < fileheader.width; x++ ) {
  198. for ( int i = 0;i < fileheader.channel;i++, src += srcbytedepth, target++ )
  199. * target = static_cast<P> ( *reinterpret_cast<Ipp16u *> ( src ) );
  200. }
  201. }
  202. delete [] line;
  203. }
  204. } else if ( fileheader.channel == 3 && image->channels() == 1 ) { // have to cast and to convert
  205. ColorImageT<P> rgb ( fileheader.width, fileheader.height );
  206. for ( int y = 0; y < fileheader.height; y++ ) {
  207. Ipp8u *line = new Ipp8u[fileheader.width*fileheader.channel*srcbytedepth];
  208. file.read ( reinterpret_cast<char *> ( line ), fileheader.width*fileheader.channel*srcbytedepth );
  209. P *target = rgb.getPixelPointerY ( y );
  210. Ipp8u *src = line;
  211. if ( srcbytedepth == 1 ) {
  212. for ( int x = 0; x < fileheader.width; x++ ) {
  213. for ( int i = 0;i < fileheader.channel;i++, src++, target++ )
  214. *target = static_cast<P> ( *src );
  215. }
  216. } else {
  217. for ( int x = 0; x < fileheader.width; x++ ) {
  218. for ( int i = 0;i < fileheader.channel;i++, src += srcbytedepth, target++ )
  219. * target = static_cast<P> ( *reinterpret_cast<Ipp16u *> ( src ) );
  220. }
  221. }
  222. delete [] line;
  223. }
  224. rgbToGray ( rgb, dynamic_cast<ImageT<P> *> ( image ) );
  225. } else {
  226. fthrow ( ImageException, "Format (channels) not yet implemented." );
  227. }
  228. } else {
  229. fthrow ( ImageException, "Format not yet implemented." );
  230. }
  231. }
  232. }
  233. #ifdef NICE_USELIB_LIBMAGICK
  234. template<class P>
  235. void ImageFile::readerMagick ( GrayColorImageCommonImplementationT<P> *image )
  236. {
  237. fthrow ( ImageException, "Format not yet implemented (only available for standard images)." );
  238. }
  239. template<class P>
  240. void ImageFile::writerMagick ( const GrayColorImageCommonImplementationT<P> *image ) const
  241. {
  242. fthrow ( ImageException, "Format not yet implemented (only available for standard images)." );
  243. }
  244. #endif
  245. template <class P>
  246. void ImageFile::writerPXM ( const GrayColorImageCommonImplementationT<P> *image ) const {
  247. using namespace std;
  248. ofstream file ( filename.c_str(), ios::binary );
  249. if ( image->channels() == 1 )
  250. file << "P5" << endl;
  251. else if ( image->channels() == 3 )
  252. file << "P6" << endl;
  253. else {
  254. string msg = "Cannot write a ";
  255. msg += itostr ( image->channels() );
  256. msg += "-channel format. This is not yet implemented.";
  257. fthrow ( ImageException, msg );
  258. }
  259. file << image->widthInline() << " " << image->heightInline() << endl;
  260. file << static_cast<int> ( std::pow ( 2.0, image->bitdepth() ) - 1 ) << endl;
  261. for ( int y = 0; y < image->heightInline(); y++ ) {
  262. file.write ( reinterpret_cast<const char *> ( image->getPixelPointerY ( y ) ), image->widthInline() *image->channels() *image->bytedepth() );
  263. }
  264. file.close();
  265. }
  266. #ifdef NICE_USELIB_PNG
  267. template<class P>
  268. void ImageFile::readerPNG ( GrayColorImageCommonImplementationT<P> *image )
  269. {
  270. FILE* pFile;
  271. // open image file
  272. if ( ( pFile = fopen ( filename.c_str(), "rb" ) ) == NULL ) {
  273. fthrow ( ImageException, "ImageFile::readerPNG: Cannot open " + filename );
  274. }
  275. // read header
  276. const int headersize = 8; // 8 is the maximum size that can be checked
  277. png_byte header[headersize];
  278. fread ( header, 1, headersize, pFile );
  279. if ( png_sig_cmp ( header, 0, headersize ) ) {
  280. fclose ( pFile );
  281. fthrow ( ImageException, "Image is not a PNG file." );
  282. }
  283. /* initialize stuff */
  284. png_structp png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
  285. if ( !png_ptr ) {
  286. fclose ( pFile );
  287. fthrow ( ImageException, "png_create_read_struct failed" );
  288. }
  289. png_infop info_ptr = png_create_info_struct ( png_ptr );
  290. if ( !info_ptr ) {
  291. fclose ( pFile );
  292. fthrow ( ImageException, "png_create_info_struct failed" );
  293. }
  294. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  295. fclose ( pFile );
  296. fthrow ( ImageException, "Error during init_io" );
  297. }
  298. png_init_io ( png_ptr, pFile );
  299. png_set_sig_bytes ( png_ptr, headersize );
  300. png_read_info ( png_ptr, info_ptr );
  301. int width = png_get_image_width(png_ptr, info_ptr);
  302. int height = png_get_image_height(png_ptr, info_ptr);
  303. png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  304. png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  305. // resize image if necessary
  306. if ( width != image->widthInline() || height != image->heightInline() ) {
  307. image->resize ( width, height );
  308. }
  309. //int number_of_passes = png_set_interlace_handling(png_ptr);
  310. /** expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
  311. transparency chunks to full alpha channel; strip 16-bit-per-sample
  312. images to 8 bits per sample; and convert grayscale to RGB[A] */
  313. if ( color_type == PNG_COLOR_TYPE_PALETTE )
  314. png_set_expand ( png_ptr );
  315. if ( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
  316. png_set_expand ( png_ptr );
  317. if ( png_get_valid ( png_ptr, info_ptr, PNG_INFO_tRNS ) )
  318. png_set_expand ( png_ptr );
  319. if ( image->bitdepth() == 8 && bit_depth == 16 ) {
  320. png_set_strip_16 ( png_ptr );
  321. }
  322. if ( image->bitdepth() == 16 && bit_depth == 8 ) {
  323. fthrow ( ImageException, "convertion from 16 to 8 bit not implemented." );
  324. }
  325. switch ( image->channels() ) {
  326. case 1:
  327. if ( color_type == PNG_COLOR_TYPE_RGBA ||
  328. color_type == PNG_COLOR_TYPE_RGB ) {
  329. png_set_rgb_to_gray_fixed ( png_ptr, 1, -1, -1 );
  330. }
  331. if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
  332. png_set_strip_alpha ( png_ptr );
  333. break;
  334. case 3:
  335. if ( color_type == PNG_COLOR_TYPE_RGBA )
  336. png_set_strip_alpha ( png_ptr );
  337. if ( color_type == PNG_COLOR_TYPE_GRAY ||
  338. color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
  339. png_set_gray_to_rgb ( png_ptr );
  340. break;
  341. case 4:
  342. break;
  343. default:
  344. fthrow ( ImageException, "No or invalid color image->channels()" );
  345. break;
  346. }
  347. png_read_update_info ( png_ptr, info_ptr );
  348. // read file
  349. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  350. fclose ( pFile );
  351. fthrow ( ImageException, "Error during read_image" );
  352. }
  353. png_bytep * row_pointers = new png_bytep[height];
  354. for ( int y = 0; y < height; y++ )
  355. row_pointers[y] = reinterpret_cast<png_bytep> ( image->getPixelPointerY ( y ) );
  356. png_read_image ( png_ptr, row_pointers );
  357. delete [] row_pointers;
  358. png_destroy_read_struct ( &png_ptr, &info_ptr, NULL );
  359. fclose ( pFile );
  360. }
  361. template<>
  362. void ImageFile::readerPNG ( GrayColorImageCommonImplementationT<Ipp32f> *image );
  363. template<class P>
  364. void ImageFile::writerPNG ( const GrayColorImageCommonImplementationT<P> *image ) const
  365. {
  366. FILE *pfile;
  367. // open image file
  368. if ( ( pfile = fopen ( filename.c_str(), "wb" ) ) == NULL )
  369. fthrow ( ImageException, "ImageFile::writerPNG: Cannot write " + filename );
  370. png_structp png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, NULL,
  371. NULL, NULL );
  372. if ( !png_ptr ) {
  373. fclose ( pfile );
  374. fthrow ( ImageException, "png_create_write_struct failed" );
  375. }
  376. png_infop info_ptr = png_create_info_struct ( png_ptr );
  377. if ( !info_ptr ) {
  378. png_destroy_write_struct ( &png_ptr, ( png_infopp ) NULL );
  379. fclose ( pfile );
  380. fthrow ( ImageException, "png_create_info_struct failed" );
  381. }
  382. if ( setjmp ( png_jmpbuf ( png_ptr ) ) ) {
  383. png_destroy_write_struct ( &png_ptr, &info_ptr );
  384. fclose ( pfile );
  385. fthrow ( ImageException, "Error during write_image" );
  386. }
  387. png_init_io ( png_ptr, pfile );
  388. png_infop png_info_ptr = png_create_info_struct ( png_ptr );
  389. int bit_depth = image->bitdepth();
  390. int color_type;
  391. switch ( image->channels() ) {
  392. case 1:
  393. color_type = PNG_COLOR_TYPE_GRAY;
  394. break;
  395. case 2:
  396. color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  397. break;
  398. case 3:
  399. color_type = PNG_COLOR_TYPE_RGB;
  400. break;
  401. case 4:
  402. color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  403. break;
  404. default:
  405. fthrow ( ImageException, "No or invalid color channels" );
  406. break;
  407. }
  408. int interlace_type = PNG_INTERLACE_NONE;
  409. png_set_IHDR ( png_ptr, png_info_ptr, image->widthInline(), image->heightInline(),
  410. bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
  411. /* turn on or off filtering, and/or choose
  412. specific filters. You can use either a single
  413. PNG_FILTER_VALUE_NAME or the logical OR of one
  414. or more PNG_FILTER_NAME masks. */
  415. png_set_filter ( png_ptr, 0, PNG_FILTER_AVG );
  416. /* set the zlib compression level */
  417. //png_set_compression_level ( png_ptr, Z_BEST_COMPRESSION );
  418. //png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
  419. /* set other zlib parameters */
  420. /* png_set_compression_mem_level(png_ptr, 8);
  421. png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
  422. png_set_compression_window_bits(png_ptr, 15);
  423. png_set_compression_buffer_size(png_ptr, 8192);
  424. png_set_compression_method(png_ptr, 8); */
  425. png_write_info ( png_ptr, png_info_ptr );
  426. for ( int y = 0; y < image->heightInline(); y++ ) {
  427. //const P *prow=image->getPixelPointerY(y);
  428. png_byte row[image->widthInline() *image->channels() *image->bytedepth() ];
  429. memcpy ( row, image->getPixelPointerY ( y ), image->widthInline() *image->channels() *image->bytedepth() );
  430. png_write_row ( png_ptr, row );
  431. }
  432. png_write_end ( png_ptr, info_ptr );
  433. png_destroy_write_struct ( &png_ptr, &info_ptr );
  434. fclose ( pfile );
  435. }
  436. #endif
  437. #ifdef NICE_USELIB_JPG
  438. template<class P>
  439. void ImageFile::readerJPG ( GrayColorImageCommonImplementationT<P> *image )
  440. {
  441. struct jpeg_decompress_struct cinfo;
  442. struct jpeg_error_mgr jerr;
  443. FILE* pFile;
  444. if ( ( pFile = fopen ( filename.c_str(), "rb" ) ) == NULL )
  445. fthrow ( ImageException, "ImageFile::readerJPG: Cannot open " + filename );
  446. cinfo.err = jpeg_std_error ( &jerr );
  447. jpeg_create_decompress ( &cinfo );
  448. jpeg_stdio_src ( &cinfo, pFile );
  449. jpeg_read_header ( &cinfo, FALSE );
  450. if ( image->channels() != 1 && image->channels() != 3 )
  451. fthrow ( ImageException, "Format not yet supported" );
  452. cinfo.out_color_space = image->channels() == 1 ? JCS_GRAYSCALE : JCS_RGB;
  453. jpeg_start_decompress ( &cinfo );
  454. int row_stride = cinfo.output_width * cinfo.output_components;
  455. JSAMPARRAY buffer = ( *cinfo.mem->alloc_sarray ) ( ( j_common_ptr ) & cinfo, JPOOL_IMAGE, row_stride, 1 );
  456. // resize image if necessary
  457. int width = cinfo.output_width;
  458. int height = cinfo.output_height;
  459. if ( width != image->widthInline() || height != image->heightInline() )
  460. image->resize ( width, height );
  461. // Bilddaten zeilenweise einlesen
  462. for ( int y = 0; y < height; ++y ) {
  463. if ( !jpeg_read_scanlines ( &cinfo, buffer, 1 ) )
  464. fthrow ( ImageException, "ImageFile::readerJPG: Some Error occured while reading " + filename );
  465. if ( sizeof ( P ) == sizeof ( Ipp8u ) )
  466. memcpy ( image->getPixelPointerY ( y ), buffer[0], width*image->channels() );
  467. else {
  468. const Ipp8u* pSrc = buffer[0];
  469. P* pDst = image->getPixelPointerY ( y );
  470. for ( int x = 0; x < width*image->channels(); ++x, ++pSrc, ++pDst )
  471. if ( *pSrc < std::numeric_limits<P>::min() )
  472. *pDst = std::numeric_limits<P>::min();
  473. else if ( *pSrc > std::numeric_limits<P>::max() )
  474. *pDst = std::numeric_limits<P>::max();
  475. else
  476. *pDst = static_cast<Ipp8u> ( *pSrc );
  477. }
  478. }
  479. jpeg_finish_decompress ( &cinfo );
  480. jpeg_destroy_decompress ( &cinfo );
  481. fclose ( pFile );
  482. }
  483. template<class P>
  484. void ImageFile::writerJPG ( const GrayColorImageCommonImplementationT<P> *image, const int quality ) const
  485. {
  486. FILE *pfile;
  487. if ( ( pfile = fopen ( filename.c_str(), "wb" ) ) == NULL )
  488. fthrow ( ImageException, "ImageFile::writerJPG: Cannot write " + filename );
  489. struct jpeg_compress_struct cinfo;
  490. struct jpeg_error_mgr jerr;
  491. cinfo.err = jpeg_std_error ( &jerr );
  492. jpeg_create_compress ( &cinfo );
  493. jpeg_stdio_dest ( &cinfo, pfile );
  494. cinfo.image_width = image->widthInline();
  495. cinfo.image_height = image->heightInline();
  496. cinfo.input_components = image->channels();
  497. if ( image->channels() != 1 && image->channels() != 3 )
  498. fthrow ( ImageException, "Format not yet supported" );
  499. cinfo.in_color_space = image->channels() == 1 ? JCS_GRAYSCALE : JCS_RGB;
  500. jpeg_set_defaults ( &cinfo );
  501. jpeg_set_quality ( &cinfo, quality, TRUE );
  502. jpeg_start_compress ( &cinfo, TRUE );
  503. int width = cinfo.image_width;
  504. int height = cinfo.image_height;
  505. JSAMPROW row_pointer[1];
  506. row_pointer[0] = new Ipp8u[width*image->channels() ];
  507. for ( int y = 0; y < height; ++y ) {
  508. if ( sizeof ( P ) == sizeof ( Ipp8u ) )
  509. memcpy ( row_pointer[0], image->getPixelPointerY ( y ), width*image->channels() );
  510. else {
  511. const P* pSrc = image->getPixelPointerY ( y );
  512. Ipp8u* pDst = row_pointer[0];
  513. for ( int x = 0; x < width*image->channels(); ++x, ++pSrc, ++pDst )
  514. if ( *pSrc < std::numeric_limits<Ipp8u>::min() )
  515. *pDst = std::numeric_limits<Ipp8u>::min();
  516. else if ( *pSrc > std::numeric_limits<Ipp8u>::max() )
  517. *pDst = std::numeric_limits<Ipp8u>::max();
  518. else
  519. *pDst = static_cast<Ipp8u> ( *pSrc );
  520. }
  521. jpeg_write_scanlines ( &cinfo, row_pointer, 1 );
  522. }
  523. jpeg_finish_compress ( &cinfo );
  524. fclose ( pfile );
  525. jpeg_destroy_compress ( &cinfo );
  526. }
  527. #endif
  528. }