A Simple X Image Viewer
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

142 líneas
3.0 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, 2) < 0)
  66. goto abort;
  67. if (btous(data, order) != JPEG_MARKER_SOI)
  68. goto abort;
  69. if (s_read(fd, file->name, data, 4) < 0)
  70. goto abort;
  71. if (btous(data, order) == JPEG_MARKER_APP0) {
  72. len = btous(data + 2, order);
  73. if (lseek(fd, len - 2, SEEK_CUR) == (off_t) -1)
  74. goto abort;
  75. if (s_read(fd, file->name, data, 4) < 0)
  76. goto abort;
  77. }
  78. if (btous(data, order) != JPEG_MARKER_APP1)
  79. goto abort;
  80. len = btous(data + 2, order);
  81. if (len < 8)
  82. goto abort;
  83. if (s_read(fd, file->name, data, 6) < 0)
  84. goto abort;
  85. if (btoui(data, order) != EXIF_HEAD)
  86. goto abort;
  87. len -= 8;
  88. if (len < 12 || len > EXIF_MAX_LEN)
  89. goto abort;
  90. if (s_read(fd, file->name, data, len) < 0)
  91. goto abort;
  92. switch (btous(data, order)) {
  93. case EXIF_BO_BIG_ENDIAN:
  94. order = BO_BIG_ENDIAN;
  95. break;
  96. case EXIF_BO_LITTLE_ENDIAN:
  97. order = BO_LITTLE_ENDIAN;
  98. break;
  99. default:
  100. goto abort;
  101. break;
  102. }
  103. if (btous(data + 2, order) != EXIF_TAG_MARK)
  104. goto abort;
  105. idx = btoui(data + 4, order);
  106. if (idx > len - 2)
  107. goto abort;
  108. val = 0;
  109. cnt = btous(data + idx, order);
  110. for (idx += 2; cnt > 0 && idx < len - 12; cnt--, idx += 12) {
  111. if (btous(data + idx, order) == EXIF_TAG_ORIENTATION) {
  112. val = btous(data + idx + 8, order);
  113. break;
  114. }
  115. }
  116. close(fd);
  117. return val;
  118. abort:
  119. close(fd);
  120. return -1;
  121. }