A Simple X Image Viewer
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

135 行
2.8 KiB

  1. /* Copyright 2012 Bert Muennich
  2. *
  3. * This file is part of sxiv.
  4. *
  5. * sxiv is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published
  7. * by the Free Software Foundation; either version 2 of the License,
  8. * or (at your option) any later version.
  9. *
  10. * sxiv is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with sxiv. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #define _POSIX_C_SOURCE 200112L
  19. #include <stdlib.h>
  20. #include <fcntl.h>
  21. #include <sys/stat.h>
  22. #include <unistd.h>
  23. #include "exif.h"
  24. #include "util.h"
  25. ssize_t s_read(int fd, const char *fn, void *buf, size_t n)
  26. {
  27. ssize_t ret;
  28. ret = read(fd, buf, n);
  29. if (ret < n) {
  30. warn("unexpected end-of-file: %s", fn);
  31. return -1;
  32. } else {
  33. return ret;
  34. }
  35. }
  36. unsigned short btous(unsigned char *buf, byteorder_t order)
  37. {
  38. if (buf == NULL)
  39. return 0;
  40. if (order == BO_BIG_ENDIAN)
  41. return buf[0] << 8 | buf[1];
  42. else
  43. return buf[1] << 8 | buf[0];
  44. }
  45. unsigned int btoui(unsigned char *buf, byteorder_t order)
  46. {
  47. if (buf == NULL)
  48. return 0;
  49. if (order == BO_BIG_ENDIAN)
  50. return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
  51. else
  52. return buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
  53. }
  54. int exif_orientation(const fileinfo_t *file)
  55. {
  56. int fd;
  57. unsigned char data[EXIF_MAX_LEN];
  58. byteorder_t order = BO_BIG_ENDIAN;
  59. unsigned int cnt, len, idx, val;
  60. if (file == NULL || file->path == NULL)
  61. return -1;
  62. fd = open(file->path, O_RDONLY);
  63. if (fd < 0)
  64. return -1;
  65. if (s_read(fd, file->name, data, 4) < 0)
  66. goto abort;
  67. if (btous(data, order) != JPEG_MARKER_SOI)
  68. goto abort;
  69. if (btous(data + 2, order) != JPEG_MARKER_APP1)
  70. goto abort;
  71. if (s_read(fd, file->name, data, 2) < 0)
  72. goto abort;
  73. len = btous(data, order);
  74. if (len < 8)
  75. goto abort;
  76. if (s_read(fd, file->name, data, 6) < 0)
  77. goto abort;
  78. if (btoui(data, order) != EXIF_HEAD)
  79. goto abort;
  80. len -= 8;
  81. if (len < 12 || len > EXIF_MAX_LEN)
  82. goto abort;
  83. if (s_read(fd, file->name, data, len) < 0)
  84. goto abort;
  85. switch (btous(data, order)) {
  86. case EXIF_BO_BIG_ENDIAN:
  87. order = BO_BIG_ENDIAN;
  88. break;
  89. case EXIF_BO_LITTLE_ENDIAN:
  90. order = BO_LITTLE_ENDIAN;
  91. break;
  92. default:
  93. goto abort;
  94. break;
  95. }
  96. if (btous(data + 2, order) != EXIF_TAG_MARK)
  97. goto abort;
  98. idx = btoui(data + 4, order);
  99. if (idx > len - 2)
  100. goto abort;
  101. val = 0;
  102. cnt = btous(data + idx, order);
  103. for (idx += 2; cnt > 0 && idx < len - 12; cnt--, idx += 12) {
  104. if (btous(data + idx, order) == EXIF_TAG_ORIENTATION) {
  105. val = btous(data + idx + 8, order);
  106. break;
  107. }
  108. }
  109. close(fd);
  110. return val;
  111. abort:
  112. close(fd);
  113. return -1;
  114. }