tool to fixes some issues in baseline tiffs (with extensions), see http://andreas-romeyke.de
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.
 
 
 

116 lines
3.8 KiB

  1. /* fixes broken TIFF Files
  2. *
  3. * fixes unused tags in Baseline-TIFFs,
  4. * based on http://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
  5. *
  6. * author: Andreas Romeyke, 2013
  7. * licensed under conditions of libtiff
  8. */
  9. #include "fixit_tiff.h"
  10. #include "check_baseline.h"
  11. #include "tiff_helper.h"
  12. #include <tiffio.h>
  13. #include <assert.h>
  14. /** load a tiff, clean it up if needed, store tiff
  15. * @param filename filename which should be processed, repaired
  16. */
  17. int cleanup_tag(const char * filename, uint32 tag_to_remove ) {
  18. /* load file */
  19. TIFF* tif = TIFFOpen(filename, "r+");
  20. if (NULL == tif) {
  21. fprintf( stderr, "file '%s' could not be opened\n", filename);
  22. exit (FIXIT_TIFF_READ_PERMISSION_ERROR);
  23. };
  24. uint32 tag_counter=TIFFGetRawTagListCount(tif);
  25. uint32 tagidx;
  26. uint32 tags[tag_counter];
  27. int fd = TIFFFileno( tif);
  28. off_t count_pos=lseek(fd, -2, SEEK_CUR);
  29. if (count_pos < 0) {
  30. perror("TIFF seek error in IFD0");
  31. exit(EXIT_FAILURE);
  32. }
  33. if (lseek(fd,2, SEEK_CUR) < 0) {
  34. perror("TIFF seek error in IFD0");
  35. exit(EXIT_FAILURE);
  36. }
  37. for (tagidx=0; tagidx < tag_counter; tagidx++) {
  38. uint32 tag = TIFFGetRawTagListEntry( tif, tagidx );
  39. if (tag == tag_to_remove) {
  40. if (FLAGGED == flag_be_verbose) printf("removed tag %u\n", tags[tagidx]);
  41. /* via TIFFGetRawTagListEntry we have the tag read
  42. * now we should seek 10 bytes forward and read the entire IFD block until (including) end
  43. * then we should seek n*12 + 4 bytes backward and write
  44. * the Block out.
  45. * Also we rewind to IFD0 and write current count to
  46. * count-1
  47. */
  48. off_t actual_pos = lseek(fd, -2, SEEK_CUR);
  49. if (actual_pos < 0) {
  50. perror("TIFF seek error in IFD0");
  51. exit(EXIT_FAILURE);
  52. }
  53. off_t next_tag = lseek(fd, 12, SEEK_CUR); /* 12 bytes forward to next IFD */
  54. if (next_tag < 0) {
  55. perror("TIFF seek error in IFD0");
  56. exit(EXIT_FAILURE);
  57. }
  58. int unread_tags = tag_counter - tagidx -1;
  59. assert (unread_tags >= 0);
  60. off_t last_tag = next_tag + 12*(tag_counter - tagidx) + 4; /* last tags and offset to next ifd */
  61. int bytes = last_tag - next_tag;
  62. char buf[ bytes ];
  63. if (read(fd, &buf, bytes) != bytes) {
  64. perror("TIFF read error in IFD0");
  65. exit(EXIT_FAILURE);
  66. }
  67. if (lseek(fd, actual_pos, SEEK_SET) != actual_pos) {
  68. perror("TIFF seek error in IFD0");
  69. exit(EXIT_FAILURE);
  70. }
  71. if (write(fd, &buf, bytes) != bytes) {
  72. perror("TIFF write error in IFD0");
  73. exit(EXIT_FAILURE);
  74. }
  75. /* update count */
  76. if (lseek(fd, count_pos, SEEK_SET) != count_pos) {
  77. perror("TIFF seek error in IFD0");
  78. exit(EXIT_FAILURE);
  79. }
  80. uint16 count=0;
  81. if (read(fd, &count, 2) != 2) {
  82. perror("TIFF read error in IFD0");
  83. exit(EXIT_FAILURE);
  84. }
  85. if (lseek(fd, count_pos, SEEK_SET) != count_pos) {
  86. perror("TIFF seek error in IFD0");
  87. exit(EXIT_FAILURE);
  88. }
  89. //printf("found count=%i (0x%04x)\n", count, count);
  90. if (TIFFIsByteSwapped(tif))
  91. TIFFSwabShort(&count);
  92. count--;
  93. if (TIFFIsByteSwapped(tif)) // Swab again to write correctly out
  94. TIFFSwabShort(&count);
  95. //printf("(-1) count=%i (0x%04x)\n", count, count);
  96. if (write(fd, &count, 2) != 2) {
  97. perror("TIFF write error in IFD0");
  98. exit(EXIT_FAILURE);
  99. }
  100. if (0 != close(fd)) {
  101. perror("TIFF could not be closed");
  102. exit(EXIT_FAILURE);
  103. }
  104. goto EXIT;
  105. /* break; */
  106. }
  107. }
  108. EXIT:
  109. if (FLAGGED == flag_be_verbose) printf("After correction\n-----------------\n");
  110. if (FIXIT_TIFF_IS_VALID == check_baseline (filename)) return FIXIT_TIFF_IS_CORRECTED;
  111. else return FIXIT_TIFF_IS_CHECKED;
  112. }
  113. /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 smarttab expandtab :*/