Writer.t 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. # Before "make install", this script should be runnable with "make test".
  2. # After "make install" it should work as "perl t/Writer.t".
  3. BEGIN { $| = 1; print "1..56\n"; $Image::ExifTool::noConfig = 1; }
  4. END {print "not ok 1\n" unless $loaded;}
  5. # test 1: Load the module(s)
  6. use Image::ExifTool 'ImageInfo';
  7. $loaded = 1;
  8. print "ok 1\n";
  9. ######################### End of black magic.
  10. use t::TestLib;
  11. my $testname = 'Writer';
  12. my $testnum = 1;
  13. my $testfile;
  14. # tests 2/3: Test writing new comment to JPEG file and removing it again
  15. {
  16. ++$testnum;
  17. my $exifTool = new Image::ExifTool;
  18. my $testfile1 = "t/${testname}_${testnum}_failed.jpg";
  19. -e $testfile1 and unlink $testfile1;
  20. $exifTool->SetNewValue('Comment','New comment in JPG file');
  21. writeInfo($exifTool, 't/images/Canon.jpg', $testfile1);
  22. my $info = ImageInfo($testfile1);
  23. print 'not ' unless check($info, $testname, $testnum);
  24. print "ok $testnum\n";
  25. ++$testnum;
  26. my $testfile2 = "t/${testname}_${testnum}_failed.jpg";
  27. -e $testfile2 and unlink $testfile2;
  28. $exifTool->SetNewValue('Comment');
  29. writeInfo($exifTool, $testfile1, $testfile2);
  30. if (binaryCompare($testfile2, 't/images/Canon.jpg')) {
  31. unlink $testfile1;
  32. unlink $testfile2;
  33. } else {
  34. print 'not ';
  35. }
  36. print "ok $testnum\n";
  37. }
  38. # tests 4/5: Test editing a TIFF in memory then changing it back again
  39. {
  40. ++$testnum;
  41. my $exifTool = new Image::ExifTool;
  42. $exifTool->Options(Duplicates => 1, Unknown => 1);
  43. my $newtiff;
  44. $exifTool->SetNewValue(Headline => 'A different headline');
  45. $exifTool->SetNewValue(ImageDescription => 'Modified TIFF');
  46. $exifTool->SetNewValue(Keywords => 'another keyword', AddValue => 1);
  47. $exifTool->SetNewValue('xmp:SupplementalCategories' => 'new XMP info');
  48. writeInfo($exifTool, 't/images/ExifTool.tif', \$newtiff);
  49. my $info = $exifTool->ImageInfo(\$newtiff);
  50. unless (check($exifTool, $info, $testname, $testnum)) {
  51. $testfile = "t/${testname}_${testnum}_failed.tif";
  52. open(TESTFILE,">$testfile");
  53. binmode(TESTFILE);
  54. print TESTFILE $newtiff;
  55. close(TESTFILE);
  56. print 'not ';
  57. }
  58. print "ok $testnum\n";
  59. ++$testnum;
  60. my $newtiff2;
  61. $exifTool->SetNewValue(); # clear all the changes
  62. $exifTool->SetNewValue(Headline => 'headline');
  63. $exifTool->SetNewValue(ImageDescription => 'The picture caption');
  64. $exifTool->SetNewValue(Keywords => 'another keyword', DelValue => 1);
  65. $exifTool->SetNewValue(SupplementalCategories);
  66. writeInfo($exifTool, \$newtiff, \$newtiff2);
  67. $testfile = "t/${testname}_${testnum}_failed.tif";
  68. open(TESTFILE,">$testfile");
  69. binmode(TESTFILE);
  70. print TESTFILE $newtiff2;
  71. close(TESTFILE);
  72. if (binaryCompare($testfile,'t/images/ExifTool.tif')) {
  73. unlink $testfile;
  74. } else {
  75. print 'not ';
  76. }
  77. print "ok $testnum\n";
  78. }
  79. # test 6/7: Test rewriting a JPEG file then changing it back again
  80. {
  81. ++$testnum;
  82. my $exifTool = new Image::ExifTool;
  83. $exifTool->Options(Duplicates => 1, Unknown => 1);
  84. my $testfile1 = "t/${testname}_${testnum}_failed.jpg";
  85. unlink $testfile1;
  86. $exifTool->SetNewValue(DateTimeOriginal => '2005:01:01 00:00:00', Group => 'IFD0');
  87. $exifTool->SetNewValue(Contrast => '+2', Group => 'XMP');
  88. $exifTool->SetNewValue(ExposureCompensation => 999, Group => 'EXIF');
  89. $exifTool->SetNewValue(LightSource => 'cloud');
  90. $exifTool->SetNewValue('EXIF:Flash' => '0x1', Type => 'ValueConv');
  91. $exifTool->SetNewValue('Orientation#' => 3);
  92. $exifTool->SetNewValue(FocalPlaneResolutionUnit => 'mm');
  93. $exifTool->SetNewValue(Category => 'IPTC test');
  94. $exifTool->SetNewValue(Description => 'New description');
  95. $exifTool->SetNewValue(TimeCodes => '02:53:49:07 2009-11-19T12:38:35:21-03:00');
  96. writeInfo($exifTool, 't/images/Canon.jpg', $testfile1);
  97. my $info = $exifTool->ImageInfo($testfile1);
  98. print 'not ' unless check($exifTool, $info, $testname, $testnum);
  99. print "ok $testnum\n";
  100. ++$testnum;
  101. $exifTool->SetNewValue();
  102. $exifTool->SetNewValue(DateTimeOriginal => '2003:12:04 06:46:52');
  103. $exifTool->SetNewValue(Contrast => undef, Group => 'XMP');
  104. $exifTool->SetNewValue(ExposureCompensation => 0, Group => 'EXIF');
  105. $exifTool->SetNewValue('LightSource');
  106. $exifTool->SetNewValue('EXIF:Flash' => '0x0', Type => 'ValueConv');
  107. $exifTool->SetNewValue('Orientation#' => 1);
  108. $exifTool->SetNewValue(FocalPlaneResolutionUnit => 'in');
  109. $exifTool->SetNewValue('Category');
  110. $exifTool->SetNewValue('Description');
  111. $exifTool->SetNewValue('TimeCodes');
  112. my $image;
  113. writeInfo($exifTool, $testfile1, \$image);
  114. $exifTool->Options(Composite => 0);
  115. $info = $exifTool->ImageInfo(\$image, '-filesize');
  116. my $testfile2 = "t/${testname}_${testnum}_failed.jpg";
  117. if (check($exifTool, $info, $testname, $testnum)) {
  118. unlink $testfile1;
  119. unlink $testfile2;
  120. } else {
  121. # save bad file
  122. open(TESTFILE,">$testfile2");
  123. binmode(TESTFILE);
  124. print TESTFILE $image;
  125. close(TESTFILE);
  126. print 'not ';
  127. }
  128. print "ok $testnum\n";
  129. }
  130. # test 8: Test rewriting everything in a JPEG file
  131. {
  132. ++$testnum;
  133. my $exifTool = new Image::ExifTool;
  134. $exifTool->Options(Duplicates => 1, Binary => 1, List => 1);
  135. my $info = $exifTool->ImageInfo('t/images/Canon.jpg');
  136. my $tag;
  137. foreach $tag (keys %$info) {
  138. my $group = $exifTool->GetGroup($tag);
  139. # eat return values so warnings don't get printed
  140. my @rtns = $exifTool->SetNewValue($tag,$info->{$tag},Group=>$group);
  141. }
  142. undef $info;
  143. my $image;
  144. writeInfo($exifTool, 't/images/Canon.jpg', \$image);
  145. # (must drop Composite tags because their order may change)
  146. $exifTool->Options(Unknown => 1, Binary => 0, List => 0, Composite => 0);
  147. # (must ignore filesize because it changes as null padding is discarded)
  148. $info = $exifTool->ImageInfo(\$image, '-filesize');
  149. $testfile = "t/${testname}_${testnum}_failed.jpg";
  150. if (check($exifTool, $info, $testname, $testnum, 7)) {
  151. unlink $testfile;
  152. } else {
  153. # save bad file
  154. open(TESTFILE,">$testfile");
  155. binmode(TESTFILE);
  156. print TESTFILE $image;
  157. close(TESTFILE);
  158. print 'not ';
  159. }
  160. print "ok $testnum\n";
  161. }
  162. # test 9: Test copying over information with SetNewValuesFromFile()
  163. # (including a transfer of the ICC_Profile record)
  164. {
  165. ++$testnum;
  166. my $exifTool = new Image::ExifTool;
  167. $exifTool->SetNewValuesFromFile('t/images/Canon.jpg');
  168. $exifTool->SetNewValuesFromFile('t/images/ExifTool.tif', 'ICC_Profile');
  169. $testfile = "t/${testname}_${testnum}_failed.jpg";
  170. unlink $testfile;
  171. writeInfo($exifTool, 't/images/Nikon.jpg', $testfile);
  172. my $info = $exifTool->ImageInfo($testfile);
  173. if (check($exifTool, $info, $testname, $testnum)) {
  174. unlink $testfile;
  175. } else {
  176. print 'not ';
  177. }
  178. print "ok $testnum\n";
  179. }
  180. # test 10: Another SetNewValuesFromFile() test
  181. {
  182. ++$testnum;
  183. my $exifTool = new Image::ExifTool;
  184. $exifTool->Options('IgnoreMinorErrors' => 1);
  185. $exifTool->SetNewValuesFromFile('t/images/Pentax.jpg');
  186. $testfile = "t/${testname}_${testnum}_failed.jpg";
  187. unlink $testfile;
  188. writeInfo($exifTool, 't/images/Canon.jpg', $testfile);
  189. my $info = $exifTool->ImageInfo($testfile);
  190. if (check($exifTool, $info, $testname, $testnum)) {
  191. unlink $testfile;
  192. } else {
  193. print 'not ';
  194. }
  195. print "ok $testnum\n";
  196. }
  197. # tests 11/12: Try creating something from nothing and removing it again
  198. # (also test ListSplit and ListSep options)
  199. {
  200. ++$testnum;
  201. my $exifTool = new Image::ExifTool;
  202. $exifTool->Options(ListSplit => ';\\s*');
  203. $exifTool->Options(ListSep => ' <<separator>> ');
  204. $exifTool->SetNewValue(DateTimeOriginal => '2005:01:19 13:37:22', Group => 'EXIF');
  205. $exifTool->SetNewValue(FileVersion => 12, Group => 'IPTC');
  206. $exifTool->SetNewValue(Contributor => 'Guess who', Group => 'XMP');
  207. $exifTool->SetNewValue(GPSLatitude => q{44 deg 14' 12.25"}, Group => 'GPS');
  208. $exifTool->SetNewValue('Ducky:Quality' => 50);
  209. $exifTool->SetNewValue(Keywords => 'this; that');
  210. my $testfile1 = "t/${testname}_${testnum}_failed.jpg";
  211. unlink $testfile1;
  212. writeInfo($exifTool, 't/images/Writer.jpg', $testfile1);
  213. my $info = $exifTool->ImageInfo($testfile1);
  214. my $success = check($exifTool, $info, $testname, $testnum);
  215. print 'not ' unless $success;
  216. print "ok $testnum\n";
  217. ++$testnum;
  218. $exifTool->SetNewValue('DateTimeOriginal');
  219. $exifTool->SetNewValue('FileVersion');
  220. $exifTool->SetNewValue('Contributor');
  221. $exifTool->SetNewValue('GPSLatitude');
  222. $exifTool->SetNewValue('Ducky:Quality');
  223. $exifTool->SetNewValue('Keywords');
  224. my $testfile2 = "t/${testname}_${testnum}_failed.jpg";
  225. unlink $testfile2;
  226. writeInfo($exifTool, $testfile1, $testfile2);
  227. if (binaryCompare('t/images/Writer.jpg', $testfile2)) {
  228. unlink $testfile1 if $success;
  229. unlink $testfile2;
  230. } else {
  231. print 'not ';
  232. }
  233. print "ok $testnum\n";
  234. }
  235. # test 13: Copy tags from CRW file to JPG
  236. {
  237. ++$testnum;
  238. my $exifTool = new Image::ExifTool;
  239. $exifTool->SetNewValuesFromFile('t/images/CanonRaw.crw');
  240. $testfile = "t/${testname}_${testnum}_failed.jpg";
  241. unlink $testfile;
  242. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  243. my $info = $exifTool->ImageInfo($testfile);
  244. if (check($exifTool, $info, $testname, $testnum)) {
  245. unlink $testfile;
  246. } else {
  247. print 'not ';
  248. }
  249. print "ok $testnum\n";
  250. }
  251. # test 14: Delete all information in a group
  252. {
  253. ++$testnum;
  254. my $exifTool = new Image::ExifTool;
  255. $exifTool->SetNewValue('All' => undef, Group => 'MakerNotes');
  256. $testfile = "t/${testname}_${testnum}_failed.jpg";
  257. unlink $testfile;
  258. writeInfo($exifTool, 't/images/Canon.jpg', $testfile);
  259. my $info = $exifTool->ImageInfo($testfile);
  260. if (check($exifTool, $info, $testname, $testnum)) {
  261. unlink $testfile;
  262. } else {
  263. print 'not ';
  264. }
  265. print "ok $testnum\n";
  266. }
  267. # test 15: Copy a specific set of tags
  268. {
  269. ++$testnum;
  270. my $exifTool = new Image::ExifTool;
  271. my @copyTags = qw(exififd:all -lightSource ifd0:software);
  272. # also test new regular expression feature (ExifTool 9.15)
  273. push @copyTags, 'comment<${ make ; tr{ ,.}{_}; s{__}{_} } {cool, huh?}';
  274. $exifTool->SetNewValuesFromFile('t/images/Olympus.jpg', @copyTags);
  275. $testfile = "t/${testname}_${testnum}_failed.jpg";
  276. unlink $testfile;
  277. writeInfo($exifTool, 't/images/Canon.jpg', $testfile);
  278. my $info = $exifTool->ImageInfo($testfile);
  279. if (check($exifTool, $info, $testname, $testnum)) {
  280. unlink $testfile;
  281. } else {
  282. print 'not ';
  283. }
  284. print "ok $testnum\n";
  285. }
  286. # tests 16-18: Test SetNewValuesFromFile() order of operations
  287. {
  288. my @argsList = (
  289. [ 'ifd0:xresolution>xmp:*', 'ifd1:xresolution>xmp:*' ],
  290. [ 'ifd1:xresolution>xmp:*', 'ifd0:xresolution>xmp:*' ],
  291. [ '*:xresolution', '-ifd0:xresolution', 'xresolution>xmp:*' ],
  292. );
  293. my $args;
  294. foreach $args (@argsList) {
  295. ++$testnum;
  296. my $exifTool = new Image::ExifTool;
  297. $exifTool->SetNewValuesFromFile('t/images/GPS.jpg', @$args);
  298. $testfile = "t/${testname}_${testnum}_failed.jpg";
  299. unlink $testfile;
  300. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  301. my $info = $exifTool->ImageInfo($testfile, 'xresolution');
  302. if (check($exifTool, $info, $testname, $testnum)) {
  303. unlink $testfile;
  304. } else {
  305. print 'not ';
  306. }
  307. print "ok $testnum\n";
  308. }
  309. }
  310. # test 19: Test SaveNewValues()/RestoreNewValues()
  311. my $testOK;
  312. {
  313. ++$testnum;
  314. my $exifTool = new Image::ExifTool;
  315. $exifTool->SetNewValue(ISO => 25);
  316. $exifTool->SetNewValue(Sharpness => '+1');
  317. $exifTool->SetNewValue(Artist => 'Phil', Group => 'IFD0');
  318. $exifTool->SetNewValue(Artist => 'Harvey', Group => 'ExifIFD');
  319. $exifTool->SetNewValue(DateTimeOriginal => '2006:03:27 16:25:00');
  320. $exifTool->SetNewValue(Keywords => ['one','two']);
  321. $exifTool->SaveNewValues();
  322. $exifTool->SetNewValue(Artist => 'nobody');
  323. $exifTool->SetNewValue(Keywords => 'three');
  324. $exifTool->SetNewValuesFromFile('t/images/FujiFilm.jpg');
  325. $exifTool->RestoreNewValues();
  326. $testfile = "t/${testname}_${testnum}_failed.jpg";
  327. unlink $testfile;
  328. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  329. my $info = $exifTool->ImageInfo($testfile);
  330. if (check($exifTool, $info, $testname, $testnum)) {
  331. $testOK = 1;
  332. } else {
  333. print 'not ';
  334. }
  335. print "ok $testnum\n";
  336. }
  337. # test 20/21: Test edit in place (using the file from the last test)
  338. {
  339. my ($skip, $size);
  340. ++$testnum;
  341. $skip = '';
  342. if ($testOK) {
  343. my $exifTool = new Image::ExifTool;
  344. my $newComment = 'This is a new test comment';
  345. $exifTool->SetNewValue(Comment => $newComment);
  346. my $ok = writeInfo($exifTool, $testfile);
  347. my $info = $exifTool->ImageInfo($testfile, 'Comment');
  348. if ($$info{Comment} and $$info{Comment} eq $newComment and $ok) {
  349. $size = -s $testfile;
  350. } else {
  351. $testOK = 0;
  352. print 'not ';
  353. }
  354. } else {
  355. $skip = ' # skip Relies on previous test';
  356. }
  357. print "ok $testnum$skip\n";
  358. # test in-place edit of file passed by handle
  359. ++$testnum;
  360. $skip = '';
  361. if ($testOK) {
  362. my $exifTool = new Image::ExifTool;
  363. my $shortComment = 'short comment';
  364. $exifTool->SetNewValue(Comment => $shortComment);
  365. open FILE, "+<$testfile"; # open test file for update
  366. writeInfo($exifTool, \*FILE);
  367. close FILE;
  368. my $info = $exifTool->ImageInfo($testfile, 'Comment');
  369. if ($$info{Comment} and $$info{Comment} eq $shortComment) {
  370. my $newSize = -s $testfile;
  371. unless ($newSize < $size) {
  372. # test to see if the file got shorter as it should have
  373. $testOK = 0;
  374. $skip = ' # skip truncate() not supported on this system';
  375. }
  376. } else {
  377. $testOK = 0;
  378. print 'not ';
  379. }
  380. } else {
  381. $skip = ' # skip Relies on previous test';
  382. }
  383. print "ok $testnum$skip\n";
  384. }
  385. # test 22: Test time shift feature
  386. {
  387. ++$testnum;
  388. my @writeInfo = (
  389. ['DateTimeOriginal' => '1:2', 'Shift' => 1],
  390. ['ModifyDate' => '2:1: 3:4', 'Shift' => 1],
  391. ['CreateDate' => '200 0', 'Shift' => -1],
  392. ['DateCreated' => '20:', 'Shift' => -1],
  393. );
  394. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum, 't/images/XMP.jpg', 1);
  395. print "ok $testnum\n";
  396. }
  397. # test 23: Test renaming a file from the value of DateTimeOriginal
  398. {
  399. ++$testnum;
  400. my $skip = '';
  401. if (not eval { require POSIX }) {
  402. $skip = ' # skip Requires POSIX';
  403. } elsif ($testOK) {
  404. my $newfile = "t/${testname}_${testnum}_20060327_failed.jpg";
  405. unlink $newfile;
  406. my $exifTool = new Image::ExifTool;
  407. $exifTool->Options(DateFormat => "${testname}_${testnum}_%Y%m%d_failed.jpg");
  408. $exifTool->SetNewValuesFromFile($testfile, 'FileName<DateTimeOriginal');
  409. writeInfo($exifTool, $testfile);
  410. if (-e $newfile and not -e $testfile) {
  411. $testfile = $newfile;
  412. } else {
  413. $testOK = 0;
  414. print 'not ';
  415. }
  416. } else {
  417. $skip = ' # skip Relies on test 21';
  418. }
  419. print "ok $testnum$skip\n";
  420. $testOK and unlink $testfile; # erase test file if all tests passed
  421. }
  422. # test 24: Test redirection with expressions
  423. {
  424. ++$testnum;
  425. my $exifTool = new Image::ExifTool;
  426. $exifTool->SetNewValuesFromFile('t/images/FujiFilm.jpg',
  427. 'Comment<ISO=$ISO Aperture=${EXIF:fnumber} Exposure=${shutterspeed}'
  428. );
  429. $testfile = "t/${testname}_${testnum}_failed.jpg";
  430. unlink $testfile;
  431. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  432. my $info = $exifTool->ImageInfo($testfile, 'Comment');
  433. if (check($exifTool, $info, $testname, $testnum)) {
  434. unlink $testfile;
  435. } else {
  436. print 'not ';
  437. }
  438. print "ok $testnum\n";
  439. }
  440. # test 25/26: Test order of delete operations
  441. {
  442. my $i;
  443. for ($i=0; $i<2; ++$i) {
  444. ++$testnum;
  445. my $exifTool = new Image::ExifTool;
  446. $exifTool->SetNewValuesFromFile('t/images/Nikon.jpg', 'all:all', '-makernotes:all');
  447. $exifTool->SetNewValue(fnumber => 26) if $i == 1;
  448. $exifTool->SetNewValue('exififd:all'); # delete all exifIFD
  449. $exifTool->SetNewValue(fnumber => 25) if $i == 0;
  450. $testfile = "t/${testname}_${testnum}_failed.jpg";
  451. unlink $testfile;
  452. writeInfo($exifTool, 't/images/Canon.jpg', $testfile);
  453. my $info = $exifTool->ImageInfo($testfile);
  454. if (check($exifTool, $info, $testname, $testnum)) {
  455. unlink $testfile;
  456. } else {
  457. print 'not ';
  458. }
  459. print "ok $testnum\n";
  460. }
  461. }
  462. # test 27: Check that mandatory EXIF resolution tags get taken from JFIF
  463. {
  464. ++$testnum;
  465. my $exifTool = new Image::ExifTool;
  466. $exifTool->SetNewValue('exif:all'); # delete all EXIF
  467. $testfile = "t/${testname}_${testnum}_failed.jpg";
  468. unlink $testfile;
  469. writeInfo($exifTool, 't/images/ExifTool.jpg', $testfile);
  470. $exifTool->SetNewValue();
  471. $exifTool->SetNewValue('exif:datetimeoriginal', '2000:01:02 03:04:05');
  472. my $ok = writeInfo($exifTool, $testfile);
  473. $info = $exifTool->ImageInfo($testfile, 'XResolution', 'YResolution', 'DateTimeOriginal');
  474. if (check($exifTool, $info, $testname, $testnum) and $ok) {
  475. unlink $testfile;
  476. } else {
  477. print 'not ';
  478. }
  479. print "ok $testnum\n";
  480. }
  481. # tests 28-30: Check cross delete behaviour when deleting tags
  482. {
  483. my $group;
  484. my $exifTool = new Image::ExifTool;
  485. $exifTool->SetNewValue('IFD0:ISO',100);
  486. $exifTool->SetNewValue('ExifIFD:ISO',200);
  487. writeInfo($exifTool, 't/images/Writer.jpg', 't/tmp.jpg');
  488. foreach $group ('EXIF', 'IFD0', 'ExifIFD') {
  489. ++$testnum;
  490. $exifTool->SetNewValue(); # reset values
  491. $exifTool->SetNewValue("$group:ISO"); # delete ISO from specific group
  492. $testfile = "t/${testname}_${testnum}_failed.jpg";
  493. unlink $testfile;
  494. writeInfo($exifTool, 't/tmp.jpg', $testfile);
  495. my $info = $exifTool->ImageInfo($testfile, 'FileName', 'ISO');
  496. if (check($exifTool, $info, $testname, $testnum)) {
  497. unlink $testfile;
  498. } else {
  499. print 'not ';
  500. }
  501. print "ok $testnum\n";
  502. }
  503. unlink 't/tmp.jpg';
  504. }
  505. # test 31: Delete all but EXIF (excluding IFD1) and IPTC information
  506. {
  507. ++$testnum;
  508. my $exifTool = new Image::ExifTool;
  509. $exifTool->SetNewValue('*');
  510. $exifTool->SetNewValue('EXIF:*', undef, Replace => 2);
  511. $exifTool->SetNewValue('ifd1:all');
  512. $exifTool->SetNewValue('IPTC:*', undef, Replace => 2);
  513. $testfile = "t/${testname}_${testnum}_failed.jpg";
  514. unlink $testfile;
  515. writeInfo($exifTool, 't/images/ExifTool.jpg', $testfile);
  516. my $info = $exifTool->ImageInfo($testfile);
  517. if (check($exifTool, $info, $testname, $testnum)) {
  518. unlink $testfile;
  519. } else {
  520. print 'not ';
  521. }
  522. print "ok $testnum\n";
  523. }
  524. # tests 32-33: Read/Write ICC Profile tags
  525. {
  526. ++$testnum;
  527. my $exifTool = new Image::ExifTool;
  528. $exifTool->Options(IgnoreMinorErrors => 1);
  529. my $hdr = "\0\0\0\x18ADBE\x02\x10\0\0mntrRGB XYZ ";
  530. $exifTool->SetNewValue(AsShotICCProfile => $hdr . '<dummy>', Protected => 1);
  531. $exifTool->SetNewValue(CurrentICCProfile => $hdr . '<dummy 2>', Protected => 1);
  532. $testfile = "t/${testname}_${testnum}_failed.tif";
  533. unlink $testfile;
  534. my @tags = qw(ICC_Profile AsShotICCProfile CurrentICCProfile);
  535. writeInfo($exifTool, 't/images/ExifTool.tif', $testfile);
  536. my $info = $exifTool->ImageInfo($testfile, @tags);
  537. print 'not ' unless check($exifTool, $info, $testname, $testnum);
  538. print "ok $testnum\n";
  539. ++$testnum;
  540. my $srcfile = $testfile;
  541. $exifTool->SetNewValue();
  542. $exifTool->SetNewValue(ICC_Profile => $hdr . '<another dummy>', Protected => 1);
  543. $testfile = "t/${testname}_${testnum}_failed.tif";
  544. unlink $testfile;
  545. writeInfo($exifTool, $srcfile, $testfile);
  546. $info = $exifTool->ImageInfo($testfile, @tags);
  547. if (check($exifTool, $info, $testname, $testnum)) {
  548. unlink $srcfile;
  549. unlink $testfile;
  550. } else {
  551. print 'not ';
  552. }
  553. print "ok $testnum\n";
  554. }
  555. # test 34: copy list tag to list and non-list tags with different options
  556. {
  557. ++$testnum;
  558. my $exifTool = new Image::ExifTool;
  559. $exifTool->Options(List => 1);
  560. $exifTool->SetNewValuesFromFile('t/images/IPTC.jpg',
  561. { Replace => 1 },
  562. 'xmp:subject<filename',
  563. 'xmp:subject<iptc:keywords',
  564. 'comment<iptc:keywords',
  565. { Replace => 0 },
  566. 'xmp:HierarchicalSubject<filename',
  567. 'xmp:HierarchicalSubject<iptc:keywords',
  568. );
  569. $testfile = "t/${testname}_${testnum}_failed.jpg";
  570. unlink $testfile;
  571. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  572. $info = $exifTool->ImageInfo($testfile, 'xmp:subject', 'comment', 'HierarchicalSubject');
  573. my $err;
  574. if (check($exifTool, $info, $testname, $testnum)) {
  575. # make sure it was an array reference
  576. my $val = $$info{Subject} || '';
  577. my $err;
  578. if (ref $val ne 'ARRAY') {
  579. $err = "Subject is not an ARRAY: '$val'";
  580. } elsif (@$val != 3) {
  581. $err = "Subject does not contain 3 values: '" . join(', ', @$val) . "'";
  582. }
  583. if ($err) {
  584. warn "\n $err\n";
  585. } else {
  586. unlink $testfile;
  587. }
  588. } else {
  589. $err = 1;
  590. }
  591. print 'not ' if $err;
  592. print "ok $testnum\n";
  593. }
  594. # test 35: Add back all information after deleting everything
  595. {
  596. ++$testnum;
  597. my $exifTool = new Image::ExifTool;
  598. $exifTool->SetNewValue('*');
  599. $exifTool->SetNewValuesFromFile('t/images/ExifTool.jpg', 'all:all',
  600. 'icc_profile', 'canonvrd');
  601. $testfile = "t/${testname}_${testnum}_failed.jpg";
  602. unlink $testfile;
  603. writeInfo($exifTool, 't/images/ExifTool.jpg', $testfile);
  604. $exifTool->Options(Composite => 0);
  605. my $info = $exifTool->ImageInfo($testfile);
  606. if (check($exifTool, $info, $testname, $testnum)) {
  607. unlink $testfile;
  608. } else {
  609. print 'not ';
  610. }
  611. print "ok $testnum\n";
  612. }
  613. # test 36: Test adding and deleting from the same list
  614. {
  615. ++$testnum;
  616. my $exifTool = new Image::ExifTool;
  617. $exifTool->SetNewValue('IPTC:Keywords', 'out', DelValue => 1);
  618. $exifTool->SetNewValue('IPTC:Keywords', 'in', AddValue => 1);
  619. $testfile = "t/${testname}_${testnum}_failed.jpg";
  620. unlink $testfile;
  621. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  622. my $info = $exifTool->ImageInfo($testfile, 'IPTC:all');
  623. if (check($exifTool, $info, $testname, $testnum)) {
  624. unlink $testfile;
  625. } else {
  626. print 'not ';
  627. }
  628. print "ok $testnum\n";
  629. }
  630. # tests 37-38: Create EXIF file from EXIF block and individual tags
  631. {
  632. my $i;
  633. for ($i=0; $i<2; ++$i) {
  634. ++$testnum;
  635. my $exifTool = new Image::ExifTool;
  636. my @tags;
  637. if ($i == 0) {
  638. $exifTool->SetNewValuesFromFile('t/images/Sony.jpg', 'EXIF');
  639. $exifTool->Options(PrintConv => 0);
  640. @tags = qw(FileSize Compression);
  641. } else {
  642. $exifTool->SetNewValuesFromFile('t/images/Sony.jpg');
  643. $exifTool->Options(PrintConv => 1, Unknown => 1);
  644. }
  645. $testfile = "t/${testname}_${testnum}_failed.exif";
  646. unlink $testfile;
  647. writeInfo($exifTool, undef, $testfile);
  648. my $info = $exifTool->ImageInfo($testfile, @tags);
  649. if (check($exifTool, $info, $testname, $testnum)) {
  650. unlink $testfile;
  651. } else {
  652. print 'not ';
  653. }
  654. print "ok $testnum\n";
  655. }
  656. }
  657. # tests 39-40: Test writing only if the tag didn't already exist
  658. {
  659. ++$testnum;
  660. my @writeInfo = (
  661. [DateTimeOriginal => '', DelValue => 1],
  662. [DateTimeOriginal => '1999:99:99 99:99:99'],
  663. [XResolution => '', DelValue => 1],
  664. [XResolution => '123'],
  665. [ResolutionUnit => '', DelValue => 1],
  666. [ResolutionUnit => 'cm'],
  667. );
  668. my @check = qw(FileName DateTimeOriginal XResolution ResolutionUnit);
  669. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum,
  670. 't/images/Writer.jpg', \@check);
  671. print "ok $testnum\n";
  672. ++$testnum;
  673. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum,
  674. 't/images/Canon.jpg', \@check, 1);
  675. print "ok $testnum\n";
  676. }
  677. # test 41: Test writing Kodak APP3 and Canon CIFF Meta information
  678. {
  679. ++$testnum;
  680. my @writeInfo = (
  681. ['Meta:SerialNumber' => '12345'],
  682. ['CIFF:OwnerName' => 'CIFF Write Test'],
  683. );
  684. my @check = qw(SerialNumber OwnerName);
  685. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum,
  686. 't/images/ExifTool.jpg', \@check);
  687. print "ok $testnum\n";
  688. }
  689. # test 42: Test SetNewValuesFromFile with wildcards
  690. {
  691. ++$testnum;
  692. my $exifTool = new Image::ExifTool;
  693. $exifTool->SetNewValuesFromFile('t/images/ExifTool.jpg', 'ifd0:*<jfif:?resolution');
  694. $testfile = "t/${testname}_${testnum}_failed.jpg";
  695. unlink $testfile;
  696. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  697. $exifTool->Options(Composite => 0);
  698. my $info = $exifTool->ImageInfo($testfile, '-file:all');
  699. if (check($exifTool, $info, $testname, $testnum)) {
  700. unlink $testfile;
  701. } else {
  702. print 'not ';
  703. }
  704. print "ok $testnum\n";
  705. }
  706. # test 43: Test increment feature EXIF
  707. {
  708. ++$testnum;
  709. my $exifTool = new Image::ExifTool;
  710. $testfile = "t/${testname}_${testnum}_failed.jpg";
  711. unlink $testfile;
  712. my @writeInfo = (
  713. [ExposureTime => '1.5', Shift => 1],
  714. [SerialNumber => '-9', Shift => -1], # (two negatives make a positive)
  715. [MeteringMode => '1', Shift => 0, AddValue => 1],
  716. );
  717. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum, 't/images/Canon.jpg', 1);
  718. print "ok $testnum\n";
  719. }
  720. # test 44: Test increment feature with XMP
  721. {
  722. ++$testnum;
  723. my $exifTool = new Image::ExifTool;
  724. my @writeInfo = (
  725. ['XMP:ApertureValue' => '-0.1', Shift => 1], # increment
  726. ['XMP:FNumber' => '28/10', DelValue => 1], # conditional delete
  727. ['XMP:DateTimeOriginal' => '3', Shift => 0, AddValue => 1], # shift
  728. );
  729. print 'not ' unless writeCheck(\@writeInfo, $testname, $testnum, 't/images/XMP.xmp', 1);
  730. print "ok $testnum\n";
  731. }
  732. # test 45: Test writing different EXIF string encoding
  733. {
  734. ++$testnum;
  735. my $exifTool = new Image::ExifTool;
  736. $exifTool->Options(CharsetEXIF => 'Latin');
  737. my $testfile = "t/${testname}_${testnum}_failed.jpg";
  738. unlink $testfile;
  739. $exifTool->SetNewValue(Artist => "P\xc3\xaaro", Group => 'EXIF');
  740. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  741. $exifTool->Options(CharsetEXIF => undef);
  742. my $info = $exifTool->ImageInfo($testfile, 'artist');
  743. if (check($exifTool, $info, $testname, $testnum)) {
  744. unlink $testfile;
  745. } else {
  746. print 'not ';
  747. }
  748. print "ok $testnum\n";
  749. }
  750. # test 46: Test writing with wildcards
  751. {
  752. ++$testnum;
  753. my $exifTool = new Image::ExifTool;
  754. my $testfile = "t/${testname}_${testnum}_failed.jpg";
  755. unlink $testfile;
  756. $exifTool->SetNewValue('A*' => '7');
  757. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  758. my $info = $exifTool->ImageInfo($testfile);
  759. if (check($exifTool, $info, $testname, $testnum)) {
  760. unlink $testfile;
  761. } else {
  762. print 'not ';
  763. }
  764. print "ok $testnum\n";
  765. }
  766. # test 47: Test various WriteMode settings
  767. {
  768. ++$testnum;
  769. my $exifTool = new Image::ExifTool;
  770. my $testfile = "t/${testname}_${testnum}_failed.jpg";
  771. unlink $testfile; # Should the tag be written?
  772. $exifTool->Options(WriteMode => 'w'); # --- write existing tags only:
  773. $exifTool->SetNewValue(ISO => 150); # yes (already exists)
  774. $exifTool->SetNewValue(ImageDescription => 'N');# no (doesn't already exist)
  775. $exifTool->Options(WriteMode => 'c'); # --- create new tags only:
  776. $exifTool->SetNewValue(ApertureValue => 8.0); # no (already exists)
  777. $exifTool->SetNewValue(UserComment => 'No'); # no (exists, albeit empty)
  778. $exifTool->SetNewValue(Artist => 'Phil'); # yes (doesn't already exist)
  779. $exifTool->SetNewValue('XMP:Subject' => 'No'); # no (shouldn't create new group)
  780. $exifTool->Options(WriteMode => 'cg'); # --- also create new groups:
  781. $exifTool->SetNewValue('IPTC:Keywords' => 'Y'); # yes (should create new group)
  782. $exifTool->Options(Composite => 0, FastScan => 2);
  783. writeInfo($exifTool, 't/images/Canon.jpg', $testfile);
  784. my $info = $exifTool->ImageInfo($testfile, '-time:all');
  785. if (check($exifTool, $info, $testname, $testnum)) {
  786. unlink $testfile;
  787. } else {
  788. print 'not ';
  789. }
  790. print "ok $testnum\n";
  791. }
  792. # tests 48-50: More WriteMode 'cg' tests, and test AddUserDefinedTags()
  793. {
  794. ++$testnum;
  795. my $testfile = "t/${testname}_${testnum}_failed.jpg";
  796. unlink $testfile;
  797. my $exifTool = new Image::ExifTool;
  798. $exifTool->Options(WriteMode => 'cg');
  799. $exifTool->SetNewValue('XMP-dc:Title' => 'A');
  800. $exifTool->SetNewValue('XMP:Subject' => 'A');
  801. $exifTool->SetNewValue('XMP:LocationCreated' => '{city=A}');
  802. $exifTool->SetNewValue('XMP:Flash' => '{fired=true}');
  803. $exifTool->SetNewValue('IPTC:Keywords' => 'A');
  804. $exifTool->SetNewValue('IPTC:City' => 'A');
  805. $exifTool->SetNewValue('EXIF:Artist' => 'A');
  806. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  807. my $info = $exifTool->ImageInfo($testfile, '-time:all', '-filename');
  808. unless (check($exifTool, $info, $testname, $testnum)) {
  809. print 'not ';
  810. }
  811. print "ok $testnum\n";
  812. ++$testnum;
  813. my $testfile2 = "t/${testname}_${testnum}_failed.jpg";
  814. unlink $testfile2;
  815. $exifTool->SetNewValue();
  816. $exifTool->SetNewValue('XMP-dc:Title' => 'B');
  817. $exifTool->SetNewValue('XMP:Subject' => 'B');
  818. $exifTool->SetNewValue('XMP:LocationCreated' => '{city=B}');
  819. $exifTool->SetNewValue('XMP:Flash' => '{fired=false}');
  820. $exifTool->SetNewValue('IPTC:Keywords' => 'B');
  821. $exifTool->SetNewValue('IPTC:City' => 'B');
  822. $exifTool->SetNewValue('EXIF:Artist' => 'B');
  823. if (writeInfo($exifTool, $testfile, $testfile2, 1)) {
  824. unlink $testfile;
  825. unlink $testfile2;
  826. } else {
  827. $info = $exifTool->ImageInfo($testfile2, '-time:all', '-filename');
  828. check($exifTool, $info, $testname, $testnum, $testnum-1);
  829. print 'not ';
  830. }
  831. print "ok $testnum\n";
  832. ++$testnum;
  833. $testfile = "t/${testname}_${testnum}_failed.xmp";
  834. unlink $testfile;
  835. Image::ExifTool::AddUserDefinedTags('Image::ExifTool::XMP::dc', test => {} );
  836. $exifTool->SetNewValue();
  837. $exifTool->SetNewValue('XMP-dc:Title' => 'A');
  838. $exifTool->SetNewValue('XMP-dc:Test' => 'B');
  839. writeInfo($exifTool, undef, $testfile);
  840. $info = $exifTool->ImageInfo($testfile, 'xmp:all');
  841. if (check($exifTool, $info, $testname, $testnum)) {
  842. unlink $testfile;
  843. } else {
  844. print 'not ';
  845. }
  846. print "ok $testnum\n";
  847. }
  848. # test 51: Delete a unknown JPEG APP segment
  849. {
  850. ++$testnum;
  851. my $exifTool = new Image::ExifTool;
  852. $exifTool->SetNewValue('APP6:*' => undef);
  853. $testfile = "t/${testname}_${testnum}_failed.jpg";
  854. unlink $testfile;
  855. writeInfo($exifTool, 't/images/ExifTool.jpg', $testfile);
  856. my $info = $exifTool->ImageInfo($testfile);
  857. if (check($exifTool, $info, $testname, $testnum)) {
  858. unlink $testfile;
  859. } else {
  860. print 'not ';
  861. }
  862. print "ok $testnum\n";
  863. }
  864. # test 52: Delete groups by family 2 group name
  865. {
  866. ++$testnum;
  867. my $exifTool = new Image::ExifTool;
  868. $exifTool->SetNewValue('Image:*');
  869. $exifTool->SetNewValue('Camera:*');
  870. $testfile = "t/${testname}_${testnum}_failed.xmp";
  871. unlink $testfile;
  872. writeInfo($exifTool, 't/images/XMP.xmp', $testfile);
  873. my $info = $exifTool->ImageInfo($testfile);
  874. if (check($exifTool, $info, $testname, $testnum)) {
  875. unlink $testfile;
  876. } else {
  877. print 'not ';
  878. }
  879. print "ok $testnum\n";
  880. }
  881. # test 53: Exclude groups when copying
  882. {
  883. ++$testnum;
  884. my $exifTool = new Image::ExifTool;
  885. $exifTool->SetNewValuesFromFile('t/images/Canon.jpg', '-Exif:All', '-Canon:All');
  886. $testfile = "t/${testname}_${testnum}_failed.xmp";
  887. unlink $testfile;
  888. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  889. my $info = $exifTool->ImageInfo($testfile);
  890. if (check($exifTool, $info, $testname, $testnum)) {
  891. unlink $testfile;
  892. } else {
  893. print 'not ';
  894. }
  895. print "ok $testnum\n";
  896. }
  897. # test 54: Specify multiple groups when copying, excluding a single tag
  898. {
  899. ++$testnum;
  900. my $exifTool = new Image::ExifTool;
  901. $exifTool->SetNewValuesFromFile('t/images/Canon.jpg', 'Exif:Time:All', '-createdate');
  902. $testfile = "t/${testname}_${testnum}_failed.xmp";
  903. unlink $testfile;
  904. writeInfo($exifTool, 't/images/Writer.jpg', $testfile);
  905. my $info = $exifTool->ImageInfo($testfile, 'exif:*', '-image:all');
  906. if (check($exifTool, $info, $testname, $testnum)) {
  907. unlink $testfile;
  908. } else {
  909. print 'not ';
  910. }
  911. print "ok $testnum\n";
  912. }
  913. # test 55-56: Create and edit EXV file
  914. {
  915. ++$testnum;
  916. my $exifTool = new Image::ExifTool;
  917. $exifTool->SetNewValue(Artist => 'me');
  918. $exifTool->SetNewValue(Keywords => ['one','two']);
  919. $testfile = "t/${testname}_${testnum}_failed.exv";
  920. unlink $testfile;
  921. writeInfo($exifTool, undef, $testfile);
  922. my $info = $exifTool->ImageInfo($testfile, 'exif:*', 'iptc:*', 'xmp:*');
  923. unless (check($exifTool, $info, $testname, $testnum)) {
  924. print 'not ';
  925. }
  926. print "ok $testnum\n";
  927. ++$testnum;
  928. $exifTool->SetNewValue();
  929. $exifTool->SetNewValue(Artist);
  930. $exifTool->SetNewValue(Title => 'Test');
  931. my $testfile2 = "t/${testname}_${testnum}_failed.exv";
  932. unlink $testfile2;
  933. writeInfo($exifTool, $testfile, $testfile2);
  934. $info = $exifTool->ImageInfo($testfile2, 'exif:*', 'iptc:*', 'xmp:*');
  935. if (check($exifTool, $info, $testname, $testnum)) {
  936. unlink $testfile;
  937. unlink $testfile2;
  938. } else {
  939. print 'not ';
  940. }
  941. print "ok $testnum\n";
  942. }
  943. # end