source.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include "source.h"
  2. // --- async source ----------------------------------------------------------------------
  3. // define glib subtype for vips async source
  4. #define VIPS_TYPE_ASYNC_SOURCE (vips_async_source_get_type())
  5. G_DEFINE_FINAL_TYPE(VipsAsyncSource, vips_async_source, VIPS_TYPE_SOURCE)
  6. extern void closeAsyncReader(uintptr_t handle);
  7. extern gint64 asyncReaderSeek(uintptr_t handle, gint64 offset, int whence);
  8. extern gint64 asyncReaderRead(uintptr_t handle, gpointer buffer, gint64 size);
  9. // loads jpeg from a source
  10. int
  11. vips_jpegload_source_go(VipsAsyncSource *source, int shrink, VipsImage **out)
  12. {
  13. if (shrink > 1)
  14. return vips_jpegload_source(VIPS_SOURCE(source), out, "shrink", shrink,
  15. NULL);
  16. return vips_jpegload_source(VIPS_SOURCE(source), out, NULL);
  17. }
  18. // loads xjl from source
  19. int
  20. vips_jxlload_source_go(VipsAsyncSource *source, int pages, VipsImage **out)
  21. {
  22. return vips_jxlload_source(VIPS_SOURCE(source), out, "n", pages, NULL);
  23. }
  24. int
  25. vips_pngload_source_go(VipsAsyncSource *source, VipsImage **out, int unlimited)
  26. {
  27. return vips_pngload_source(
  28. VIPS_SOURCE(source), out,
  29. "unlimited", unlimited,
  30. NULL);
  31. }
  32. int
  33. vips_webpload_source_go(VipsAsyncSource *source, double scale, int pages, VipsImage **out)
  34. {
  35. return vips_webpload_source(
  36. VIPS_SOURCE(source), out,
  37. "scale", scale,
  38. "n", pages,
  39. NULL);
  40. }
  41. int
  42. vips_gifload_source_go(VipsAsyncSource *source, int pages, VipsImage **out)
  43. {
  44. return vips_gifload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL);
  45. }
  46. int
  47. vips_svgload_source_go(VipsAsyncSource *source, double scale, VipsImage **out, int unlimited)
  48. {
  49. // libvips limits the minimal scale to 0.001, so we have to scale down dpi
  50. // for lower scale values
  51. double dpi = 72.0;
  52. if (scale < 0.001) {
  53. dpi *= VIPS_MAX(scale / 0.001, 0.001);
  54. scale = 0.001;
  55. }
  56. return vips_svgload_source(
  57. VIPS_SOURCE(source), out,
  58. "scale", scale,
  59. "dpi", dpi,
  60. "unlimited", unlimited,
  61. NULL);
  62. }
  63. int
  64. vips_heifload_source_go(VipsAsyncSource *source, VipsImage **out, int thumbnail)
  65. {
  66. return vips_heifload_source(
  67. VIPS_SOURCE(source), out,
  68. "access", VIPS_ACCESS_SEQUENTIAL,
  69. "thumbnail", thumbnail,
  70. NULL);
  71. }
  72. int
  73. vips_tiffload_source_go(VipsAsyncSource *source, VipsImage **out)
  74. {
  75. return vips_tiffload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
  76. }
  77. // dereferences source
  78. void
  79. unref_source(VipsAsyncSource *source)
  80. {
  81. VIPS_UNREF(source);
  82. }
  83. // read function for vips async source
  84. static gint64
  85. vips_async_source_read(VipsSource *source, void *buffer, size_t length)
  86. {
  87. VipsAsyncSource *self = (VipsAsyncSource *) source;
  88. gint64 read_length = asyncReaderRead(self->readerHandle, buffer, length);
  89. if (read_length < 0) {
  90. vips_error("vips_async_source_read", "failed to read from async source");
  91. }
  92. return read_length;
  93. }
  94. // seek function for vips async source. whence can be SEEK_SET (0), SEEK_CUR (1), or SEEK_END (2).
  95. static gint64
  96. vips_async_source_seek(VipsSource *source, gint64 offset, int whence)
  97. {
  98. VipsAsyncSource *self = (VipsAsyncSource *) source;
  99. gint64 actual_offset = asyncReaderSeek(self->readerHandle, offset, whence);
  100. if (actual_offset < 0) {
  101. vips_error("vips_async_source_seek", "failed to seek in async source");
  102. }
  103. return actual_offset;
  104. }
  105. static void
  106. vips_async_source_dispose(GObject *gobject)
  107. {
  108. VipsAsyncSource *source = (VipsAsyncSource *) gobject;
  109. closeAsyncReader(source->readerHandle);
  110. G_OBJECT_CLASS(vips_async_source_parent_class)->dispose(gobject);
  111. }
  112. // attaches seek/read handlers to the async source class
  113. static void
  114. vips_async_source_class_init(VipsAsyncSourceClass *klass)
  115. {
  116. GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
  117. VipsObjectClass *object_class = VIPS_OBJECT_CLASS(klass);
  118. VipsSourceClass *source_class = VIPS_SOURCE_CLASS(klass);
  119. object_class->nickname = "async_source";
  120. object_class->description = "async input source";
  121. gobject_class->dispose = vips_async_source_dispose;
  122. source_class->read = vips_async_source_read;
  123. source_class->seek = vips_async_source_seek;
  124. }
  125. // initializes the async source (nothing to do here yet)
  126. static void
  127. vips_async_source_init(VipsAsyncSource *source)
  128. {
  129. }
  130. // creates a new async source with the given reader handle
  131. VipsAsyncSource *
  132. vips_new_async_source(uintptr_t readerHandle)
  133. {
  134. VipsAsyncSource *source = g_object_new(VIPS_TYPE_ASYNC_SOURCE, NULL);
  135. source->readerHandle = readerHandle;
  136. return source;
  137. }