KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kis_jpeg_converter.cc 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*
  2. * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. */
  19. #include "kis_jpeg_converter.h"
  20. #include <stdio.h>
  21. extern "C" {
  22. #include <iccjpeg.h>
  23. }
  24. #include <tqfile.h>
  25. #include <kapplication.h>
  26. #include <kmessagebox.h>
  27. #include <klocale.h>
  28. #include <KoDocumentInfo.h>
  29. #include <tdeio/netaccess.h>
  30. #include <kis_abstract_colorspace.h>
  31. #include <kis_colorspace_factory_registry.h>
  32. #include <kis_doc.h>
  33. #include <kis_image.h>
  34. #include <kis_iterators_pixel.h>
  35. #include <kis_paint_layer.h>
  36. #include <kis_group_layer.h>
  37. #include <kis_meta_registry.h>
  38. #include <kis_profile.h>
  39. #include <kis_exif_io.h>
  40. extern "C" {
  41. #include <libexif/exif-loader.h>
  42. #include <libexif/exif-utils.h>
  43. }
  44. #define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */
  45. #define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */
  46. #define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */
  47. #define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
  48. namespace {
  49. J_COLOR_SPACE getColorTypeforColorSpace( KisColorSpace * cs)
  50. {
  51. if ( cs->id() == KisID("GRAYA") || cs->id() == KisID("GRAYA16") )
  52. {
  53. return JCS_GRAYSCALE;
  54. }
  55. if ( cs->id() == KisID("RGBA") || cs->id() == KisID("RGBA16") )
  56. {
  57. return JCS_RGB;
  58. }
  59. if ( cs->id() == KisID("CMYK") || cs->id() == KisID("CMYK16") )
  60. {
  61. return JCS_CMYK;
  62. }
  63. KMessageBox::error(0, i18n("Cannot export images in %1.\n").arg(cs->id().name()) ) ;
  64. return JCS_UNKNOWN;
  65. }
  66. TQString getColorSpaceForColorType(J_COLOR_SPACE color_type) {
  67. kdDebug(41008) << "color_type = " << color_type << endl;
  68. if(color_type == JCS_GRAYSCALE)
  69. {
  70. return "GRAYA";
  71. } else if(color_type == JCS_RGB) {
  72. return "RGBA";
  73. } else if(color_type == JCS_CMYK) {
  74. return "CMYK";
  75. }
  76. return "";
  77. }
  78. }
  79. KisJPEGConverter::KisJPEGConverter(KisDoc *doc, KisUndoAdapter *adapter)
  80. {
  81. m_doc = doc;
  82. m_adapter = adapter;
  83. m_job = 0;
  84. m_stop = false;
  85. }
  86. KisJPEGConverter::~KisJPEGConverter()
  87. {
  88. }
  89. KisImageBuilder_Result KisJPEGConverter::decode(const KURL& uri)
  90. {
  91. struct jpeg_decompress_struct cinfo;
  92. struct jpeg_error_mgr jerr;
  93. cinfo.err = jpeg_std_error(&jerr);
  94. jpeg_create_decompress(&cinfo);
  95. // open the file
  96. FILE *fp = fopen(TQFile::encodeName(uri.path()), "rb");
  97. if (!fp)
  98. {
  99. return (KisImageBuilder_RESULT_NOT_EXIST);
  100. }
  101. jpeg_stdio_src(&cinfo, fp);
  102. jpeg_save_markers (&cinfo, JPEG_COM, 0xFFFF);
  103. /* Save APP0..APP15 markers */
  104. for (int m = 0; m < 16; m++)
  105. jpeg_save_markers (&cinfo, JPEG_APP0 + m, 0xFFFF);
  106. // setup_read_icc_profile(&cinfo);
  107. // read header
  108. jpeg_read_header(&cinfo, true);
  109. // start reading
  110. jpeg_start_decompress(&cinfo);
  111. // Get the colorspace
  112. TQString csName = getColorSpaceForColorType(cinfo.out_color_space);
  113. if(csName.isEmpty()) {
  114. kdDebug(41008) << "unsupported colorspace : " << cinfo.out_color_space << endl;
  115. jpeg_destroy_decompress(&cinfo);
  116. fclose(fp);
  117. return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
  118. }
  119. uchar* profile_data;
  120. uint profile_len;
  121. KisProfile* profile = 0;
  122. TQByteArray profile_rawdata;
  123. if( read_icc_profile (&cinfo, &profile_data, &profile_len))
  124. {
  125. profile_rawdata.resize(profile_len);
  126. memcpy(profile_rawdata.data(), profile_data, profile_len);
  127. cmsHPROFILE hProfile = cmsOpenProfileFromMem(profile_data, (DWORD)profile_len);
  128. if (hProfile != (cmsHPROFILE) NULL) {
  129. profile = new KisProfile( profile_rawdata);
  130. TQ_CHECK_PTR(profile);
  131. kdDebug(41008) << "profile name: " << profile->productName() << " profile description: " << profile->productDescription() << " information sur le produit: " << profile->productInfo() << endl;
  132. if(!profile->isSuitableForOutput())
  133. {
  134. kdDebug(41008) << "the profile is not suitable for output and therefore cannot be used in chalk, we need to convert the image to a standard profile" << endl; // TODO: in ko2 popup a selection menu to inform the user
  135. }
  136. }
  137. }
  138. // Retrieve a pointer to the colorspace
  139. KisColorSpace* cs;
  140. if (profile && profile->isSuitableForOutput())
  141. {
  142. kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n";
  143. cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
  144. }
  145. else
  146. cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),"");
  147. if(cs == 0)
  148. {
  149. kdDebug(41008) << "unknown colorspace" << endl;
  150. jpeg_destroy_decompress(&cinfo);
  151. fclose(fp);
  152. return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
  153. }
  154. // Create the cmsTransform if needed
  155. cmsHTRANSFORM transform = 0;
  156. if(profile && !profile->isSuitableForOutput())
  157. {
  158. transform = cmsCreateTransform(profile->profile(), cs->colorSpaceType(),
  159. cs->getProfile()->profile() , cs->colorSpaceType(),
  160. INTENT_PERCEPTUAL, 0);
  161. }
  162. // Creating the KisImageSP
  163. if( ! m_img) {
  164. m_img = new KisImage(m_doc->undoAdapter(), cinfo.image_width, cinfo.image_height, cs, "built image");
  165. TQ_CHECK_PTR(m_img);
  166. if(profile && !profile->isSuitableForOutput())
  167. {
  168. m_img -> addAnnotation( new KisAnnotation( profile->productName(), "", profile_rawdata) );
  169. }
  170. }
  171. KisPaintLayerSP layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), TQ_UINT8_MAX);
  172. // Read exif information if any
  173. // Read data
  174. JSAMPROW row_pointer = new JSAMPLE[cinfo.image_width *cinfo.num_components];
  175. for (; cinfo.output_scanline < cinfo.image_height;) {
  176. KisHLineIterator it = layer->paintDevice()->createHLineIterator(0, cinfo.output_scanline, cinfo.image_width, true);
  177. jpeg_read_scanlines(&cinfo, &row_pointer, 1);
  178. TQ_UINT8 *src = row_pointer;
  179. switch(cinfo.out_color_space)
  180. {
  181. case JCS_GRAYSCALE:
  182. while (!it.isDone()) {
  183. TQ_UINT8 *d = it.rawData();
  184. d[0] = *(src++);
  185. if(transform) cmsDoTransform(transform, d, d, 1);
  186. d[1] = TQ_UINT8_MAX;
  187. ++it;
  188. }
  189. break;
  190. case JCS_RGB:
  191. while (!it.isDone()) {
  192. TQ_UINT8 *d = it.rawData();
  193. d[2] = *(src++);
  194. d[1] = *(src++);
  195. d[0] = *(src++);
  196. if(transform) cmsDoTransform(transform, d, d, 1);
  197. d[3] = TQ_UINT8_MAX;
  198. ++it;
  199. }
  200. break;
  201. case JCS_CMYK:
  202. while (!it.isDone()) {
  203. TQ_UINT8 *d = it.rawData();
  204. d[0] = TQ_UINT8_MAX - *(src++);
  205. d[1] = TQ_UINT8_MAX - *(src++);
  206. d[2] = TQ_UINT8_MAX - *(src++);
  207. d[3] = TQ_UINT8_MAX - *(src++);
  208. if(transform) cmsDoTransform(transform, d, d, 1);
  209. d[4] = TQ_UINT8_MAX;
  210. ++it;
  211. }
  212. break;
  213. default:
  214. return KisImageBuilder_RESULT_UNSUPPORTED;
  215. }
  216. }
  217. m_img->addLayer(layer.data(), m_img->rootLayer(), 0);
  218. // Read exif informations
  219. kdDebug(41008) << "Looking for exif information" << endl;
  220. for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != NULL; marker = marker->next) {
  221. kdDebug(41008) << "Marker is " << marker->marker << endl;
  222. if (marker->marker != (JOCTET) (JPEG_APP0 + 1) ||
  223. marker->data_length < 14)
  224. continue; /* Exif data is in an APP1 marker of at least 14 octets */
  225. if (GETJOCTET (marker->data[0]) != (JOCTET) 0x45 ||
  226. GETJOCTET (marker->data[1]) != (JOCTET) 0x78 ||
  227. GETJOCTET (marker->data[2]) != (JOCTET) 0x69 ||
  228. GETJOCTET (marker->data[3]) != (JOCTET) 0x66 ||
  229. GETJOCTET (marker->data[4]) != (JOCTET) 0x00 ||
  230. GETJOCTET (marker->data[5]) != (JOCTET) 0x00)
  231. continue; /* no Exif header */
  232. kdDebug(41008) << "Found exif information of length : "<< marker->data_length << endl;
  233. KisExifIO exifIO(layer->paintDevice()->exifInfo());
  234. exifIO.readExifFromMem( marker->data , marker->data_length );
  235. // Interpret orientation tag
  236. ExifValue v;
  237. if( layer->paintDevice()->exifInfo()->getValue("Orientation", v) && v.type() == ExifValue::EXIF_TYPE_SHORT)
  238. {
  239. switch(v.asShort(0)) //
  240. {
  241. case 2:
  242. layer->paintDevice()->mirrorY();
  243. break;
  244. case 3:
  245. image()->rotate(M_PI, 0);
  246. break;
  247. case 4:
  248. layer->paintDevice()->mirrorX();
  249. break;
  250. case 5:
  251. image()->rotate(M_PI/2, 0);
  252. layer->paintDevice()->mirrorY();
  253. break;
  254. case 6:
  255. image()->rotate(M_PI/2, 0);
  256. break;
  257. case 7:
  258. image()->rotate(M_PI/2, 0);
  259. layer->paintDevice()->mirrorX();
  260. break;
  261. case 8:
  262. image()->rotate(-M_PI/2 + 2*M_PI, 0);
  263. break;
  264. default:
  265. break;
  266. }
  267. v.setValue(0, (TQ_UINT16)1);
  268. layer->paintDevice()->exifInfo()->setValue("Orientation", v);
  269. }
  270. break;
  271. }
  272. // Finish decompression
  273. jpeg_finish_decompress(&cinfo);
  274. jpeg_destroy_decompress(&cinfo);
  275. fclose(fp);
  276. delete []row_pointer;
  277. return KisImageBuilder_RESULT_OK;
  278. }
  279. KisImageBuilder_Result KisJPEGConverter::buildImage(const KURL& uri)
  280. {
  281. if (uri.isEmpty())
  282. return KisImageBuilder_RESULT_NO_URI;
  283. if (!TDEIO::NetAccess::exists(uri, false, tqApp -> mainWidget())) {
  284. return KisImageBuilder_RESULT_NOT_EXIST;
  285. }
  286. // We're not set up to handle asynchronous loading at the moment.
  287. KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
  288. TQString tmpFile;
  289. if (TDEIO::NetAccess::download(uri, tmpFile, tqApp -> mainWidget())) {
  290. KURL uriTF;
  291. uriTF.setPath( tmpFile );
  292. result = decode(uriTF);
  293. TDEIO::NetAccess::removeTempFile(tmpFile);
  294. }
  295. return result;
  296. }
  297. KisImageSP KisJPEGConverter::image()
  298. {
  299. return m_img;
  300. }
  301. KisImageBuilder_Result KisJPEGConverter::buildFile(const KURL& uri, KisPaintLayerSP layer, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisJPEGOptions options, KisExifInfo* exifInfo)
  302. {
  303. if (!layer)
  304. return KisImageBuilder_RESULT_INVALID_ARG;
  305. KisImageSP img = layer -> image();
  306. if (!img)
  307. return KisImageBuilder_RESULT_EMPTY;
  308. if (uri.isEmpty())
  309. return KisImageBuilder_RESULT_NO_URI;
  310. if (!uri.isLocalFile())
  311. return KisImageBuilder_RESULT_NOT_LOCAL;
  312. // Open file for writing
  313. FILE *fp = fopen(TQFile::encodeName(uri.path()), "wb");
  314. if (!fp)
  315. {
  316. return (KisImageBuilder_RESULT_FAILURE);
  317. }
  318. uint height = img->height();
  319. uint width = img->width();
  320. // Initialize structure
  321. struct jpeg_compress_struct cinfo;
  322. jpeg_create_compress(&cinfo);
  323. // Initialize error output
  324. struct jpeg_error_mgr jerr;
  325. cinfo.err = jpeg_std_error(&jerr);
  326. // Initialize output stream
  327. jpeg_stdio_dest(&cinfo, fp);
  328. cinfo.image_width = width; // image width and height, in pixels
  329. cinfo.image_height = height;
  330. cinfo.input_components = img->colorSpace()->nColorChannels(); // number of color channels per pixel */
  331. J_COLOR_SPACE color_type = getColorTypeforColorSpace(img->colorSpace());
  332. if(color_type == JCS_UNKNOWN)
  333. {
  334. TDEIO::del(uri);
  335. return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
  336. }
  337. cinfo.in_color_space = color_type; // colorspace of input image
  338. // Set default compression parameters
  339. jpeg_set_defaults(&cinfo);
  340. // Customize them
  341. jpeg_set_quality(&cinfo, options.quality, true);
  342. if(options.progressive)
  343. {
  344. jpeg_simple_progression (&cinfo);
  345. }
  346. // Start compression
  347. jpeg_start_compress(&cinfo, true);
  348. // Save exif information if any available
  349. if(exifInfo)
  350. {
  351. kdDebug(41008) << "Trying to save exif information" << endl;
  352. KisExifIO exifIO(exifInfo);
  353. unsigned char* exif_data;
  354. unsigned int exif_size;
  355. exifIO.saveExifToMem( &exif_data, &exif_size);
  356. kdDebug(41008) << "Exif informations size is " << exif_size << endl;
  357. if (exif_size < MAX_DATA_BYTES_IN_MARKER)
  358. {
  359. jpeg_write_marker(&cinfo, JPEG_APP0 + 1, exif_data, exif_size);
  360. } else {
  361. kdDebug(41008) << "exif informations couldn't be saved." << endl;
  362. }
  363. }
  364. // Save annotation
  365. vKisAnnotationSP_it it = annotationsStart;
  366. while(it != annotationsEnd) {
  367. if (!(*it) || (*it) -> type() == TQString()) {
  368. kdDebug(41008) << "Warning: empty annotation" << endl;
  369. ++it;
  370. continue;
  371. }
  372. kdDebug(41008) << "Trying to store annotation of type " << (*it) -> type() << " of size " << (*it) -> annotation() . size() << endl;
  373. if ((*it) -> type().startsWith("chalk_attribute:")) { // Attribute
  374. // FIXME
  375. kdDebug(41008) << "can't save this annotation : " << (*it) -> type() << endl;
  376. } else { // Profile
  377. //char* name = new char[(*it)->type().length()+1];
  378. write_icc_profile(& cinfo, (uchar*)(*it)->annotation().data(), (*it)->annotation().size());
  379. }
  380. ++it;
  381. }
  382. // Write data information
  383. JSAMPROW row_pointer = new JSAMPLE[width*cinfo.input_components];
  384. int color_nb_bits = 8 * layer->paintDevice()->pixelSize() / layer->paintDevice()->nChannels();
  385. for (; cinfo.next_scanline < height;) {
  386. KisHLineIterator it = layer->paintDevice()->createHLineIterator(0, cinfo.next_scanline, width, false);
  387. TQ_UINT8 *dst = row_pointer;
  388. switch(color_type)
  389. {
  390. case JCS_GRAYSCALE:
  391. if(color_nb_bits == 16)
  392. {
  393. while (!it.isDone()) {
  394. const TQ_UINT16 *d = reinterpret_cast<const TQ_UINT16 *>(it.rawData());
  395. *(dst++) = d[0] / TQ_UINT8_MAX;
  396. ++it;
  397. }
  398. } else {
  399. while (!it.isDone()) {
  400. const TQ_UINT8 *d = it.rawData();
  401. *(dst++) = d[0];
  402. ++it;
  403. }
  404. }
  405. break;
  406. case JCS_RGB:
  407. if(color_nb_bits == 16)
  408. {
  409. while (!it.isDone()) {
  410. const TQ_UINT16 *d = reinterpret_cast<const TQ_UINT16 *>(it.rawData());
  411. *(dst++) = d[2] / TQ_UINT8_MAX;
  412. *(dst++) = d[1] / TQ_UINT8_MAX;
  413. *(dst++) = d[0] / TQ_UINT8_MAX;
  414. ++it;
  415. }
  416. } else {
  417. while (!it.isDone()) {
  418. const TQ_UINT8 *d = it.rawData();
  419. *(dst++) = d[2];
  420. *(dst++) = d[1];
  421. *(dst++) = d[0];
  422. ++it;
  423. }
  424. }
  425. break;
  426. case JCS_CMYK:
  427. if(color_nb_bits == 16)
  428. {
  429. while (!it.isDone()) {
  430. const TQ_UINT16 *d = reinterpret_cast<const TQ_UINT16 *>(it.rawData());
  431. *(dst++) = TQ_UINT8_MAX - d[0] / TQ_UINT8_MAX;
  432. *(dst++) = TQ_UINT8_MAX - d[1] / TQ_UINT8_MAX;
  433. *(dst++) = TQ_UINT8_MAX - d[2] / TQ_UINT8_MAX;
  434. *(dst++) = TQ_UINT8_MAX - d[3] / TQ_UINT8_MAX;
  435. ++it;
  436. }
  437. } else {
  438. while (!it.isDone()) {
  439. const TQ_UINT8 *d = it.rawData();
  440. *(dst++) = TQ_UINT8_MAX - d[0];
  441. *(dst++) = TQ_UINT8_MAX - d[1];
  442. *(dst++) = TQ_UINT8_MAX - d[2];
  443. *(dst++) = TQ_UINT8_MAX - d[3];
  444. ++it;
  445. }
  446. }
  447. break;
  448. default:
  449. TDEIO::del(uri);
  450. return KisImageBuilder_RESULT_UNSUPPORTED;
  451. }
  452. jpeg_write_scanlines(&cinfo, &row_pointer, 1);
  453. }
  454. // Writting is over
  455. jpeg_finish_compress(&cinfo);
  456. fclose(fp);
  457. delete [] row_pointer;
  458. // Free memory
  459. jpeg_destroy_compress(&cinfo);
  460. return KisImageBuilder_RESULT_OK;
  461. }
  462. void KisJPEGConverter::cancel()
  463. {
  464. m_stop = true;
  465. }
  466. #include "kis_jpeg_converter.moc"