util.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* GdkPixbuf library - JPEG2000 Image Loader
  2. *
  3. * Copyright © 2020 - 2024 Nichlas Severinsen
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library 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 GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #ifndef UTIL_H
  20. #define UTIL_H
  21. #include <openjpeg.h>
  22. // The following defines and functions were copied from openjpeg.c
  23. // They are not included in libopenjp2 for whatever reason.
  24. // If they are ever included we should remove these and use them from libopenjp2 instead.
  25. #if defined(WIN32) && !defined(Windows95) && !defined(__BORLANDC__) && \
  26. !(defined(_MSC_VER) && _MSC_VER < 1400) && \
  27. !(defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x800)
  28. # define OPJ_FSEEK(stream, offset, whence) _fseeki64(stream, offset, whence)
  29. # define OPJ_FTELL(stream) _ftelli64(stream)
  30. #else
  31. # define OPJ_FSEEK(stream, offset, whence) fseek(stream, offset, whence)
  32. # define OPJ_FTELL(stream) ftell(stream)
  33. #endif
  34. #define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
  35. #define JP2_MAGIC "\x0d\x0a\x87\x0a"
  36. /* position 45: "\xff\x52" */
  37. #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
  38. static OPJ_SIZE_T opj_read_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *p_file)
  39. {
  40. OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, p_file);
  41. return l_nb_read ? l_nb_read : (OPJ_SIZE_T) -1;
  42. }
  43. static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, FILE *p_user_data)
  44. {
  45. if (OPJ_FSEEK(p_user_data, p_nb_bytes, SEEK_SET)) {
  46. return OPJ_FALSE;
  47. }
  48. return OPJ_TRUE;
  49. }
  50. static OPJ_OFF_T opj_skip_from_file(OPJ_OFF_T p_nb_bytes, FILE *p_user_data)
  51. {
  52. if (OPJ_FSEEK(p_user_data, p_nb_bytes, SEEK_CUR)) {
  53. return -1;
  54. }
  55. return p_nb_bytes;
  56. }
  57. static OPJ_UINT64 opj_get_data_length_from_file(FILE *p_file)
  58. {
  59. OPJ_OFF_T file_length = 0;
  60. OPJ_FSEEK(p_file, 0, SEEK_END);
  61. file_length = (OPJ_OFF_T) OPJ_FTELL(p_file);
  62. OPJ_FSEEK(p_file, 0, SEEK_SET);
  63. return (OPJ_UINT64) file_length;
  64. }
  65. static OPJ_SIZE_T opj_write_from_file(void *p_buffer, OPJ_SIZE_T p_nb_bytes, FILE *p_file)
  66. {
  67. return fwrite(p_buffer, 1, p_nb_bytes, p_file);
  68. }
  69. // End of defines and functions copied from openjpeg.c
  70. /**
  71. * Create stream from file pointer.
  72. * A similar funtion was deprecated and removed from openjpeg.c.
  73. */
  74. opj_stream_t* util_create_stream(FILE *fp, int is_input)
  75. {
  76. opj_stream_t *stream;
  77. stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, is_input);
  78. if(!stream)
  79. {
  80. return NULL;
  81. }
  82. opj_stream_set_read_function(stream, (opj_stream_read_fn) opj_read_from_file);
  83. opj_stream_set_seek_function(stream, (opj_stream_seek_fn) opj_seek_from_file);
  84. opj_stream_set_skip_function(stream, (opj_stream_skip_fn) opj_skip_from_file);
  85. opj_stream_set_user_data(stream, fp, NULL);
  86. opj_stream_set_user_data_length(stream, opj_get_data_length_from_file(fp));
  87. opj_stream_set_write_function(stream, (opj_stream_write_fn) opj_write_from_file);
  88. return stream;
  89. }
  90. /**
  91. * Destroy stream, codec, and image. As long as they aren't null pointers.
  92. */
  93. void util_destroy(opj_codec_t *codec, opj_stream_t* stream, opj_image_t *image)
  94. {
  95. if(stream != NULL)
  96. {
  97. opj_stream_destroy(stream);
  98. }
  99. if(codec != NULL)
  100. {
  101. opj_destroy_codec(codec);
  102. }
  103. if(image != NULL)
  104. {
  105. opj_image_destroy(image);
  106. }
  107. }
  108. /**
  109. * Identify what OPJ_CODEC to use for input file.
  110. */
  111. int util_identify(FILE *fp)
  112. {
  113. int length;
  114. unsigned char buffer[12];
  115. memset(buffer, 0, 12);
  116. length = fread(buffer, 1, 12, fp);
  117. if(length != 12)
  118. {
  119. return -1;
  120. }
  121. fseek(fp, 0, SEEK_SET);
  122. if(memcmp(buffer, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buffer, JP2_MAGIC, 4) == 0)
  123. {
  124. return OPJ_CODEC_JP2;
  125. }
  126. else if(memcmp(buffer, J2K_CODESTREAM_MAGIC, 4) == 0)
  127. {
  128. return OPJ_CODEC_J2K;
  129. }
  130. // TODO: OPJ_CODEC_JPT? OPJ_CODEC_JPP? OPJ_CODEC_JPX? OPJ_CODEC_JPH?
  131. return -1;
  132. }
  133. /**
  134. * Calculate rowstride for image
  135. */
  136. int util_rowstride(opj_image_t *image, int comps_needed)
  137. {
  138. return image->comps[0].w * comps_needed;
  139. // return ((image->comps[0].w * comps_needed * image->comps[0].prec + 7U) / 8U);
  140. }
  141. /**
  142. * Clamp value between 0 and max
  143. */
  144. int util_clamp(int value, int max)
  145. {
  146. if(value > max)
  147. {
  148. value = max;
  149. }
  150. else if(value < 0)
  151. {
  152. value = 0;
  153. }
  154. return value;
  155. }
  156. // Debug functions
  157. #if DEBUG == TRUE
  158. static void error_callback(const char *msg, void *client_data)
  159. {
  160. (void)client_data;
  161. g_print("[ERROR] %s", msg);
  162. }
  163. static void warning_callback(const char *msg, void *client_data)
  164. {
  165. (void)client_data;
  166. g_print("[WARNING] %s", msg);
  167. }
  168. static void info_callback(const char *msg, void *client_data)
  169. {
  170. (void)client_data;
  171. g_print("[INFO] %s", msg);
  172. }
  173. #endif
  174. #endif