Skip to content

Commit 938aa95

Browse files
committed
start hacking
1 parent 7228c33 commit 938aa95

File tree

3 files changed

+92
-29
lines changed

3 files changed

+92
-29
lines changed

libvips/foreign/tiff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ openout_target_unmap(thandle_t st, tdata_t start, toff_t len)
300300

301301
TIFF *
302302
vips__tiff_openout_target(VipsTarget *target, gboolean bigtiff,
303-
VipsTiffErrorHandler error_fn, VipsTiffErrorHandler warning_fn,
303+
https://gitlab.com/libtiff/libtiff/-/blob/v4.7.0/libtiff/tif_unix.c#L97-125 VipsTiffErrorHandler error_fn, VipsTiffErrorHandler warning_fn,
304304
void *user_data)
305305
{
306306
const char *mode = bigtiff ? "w8" : "w";

libvips/include/vips/connection.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,13 @@ struct _VipsTarget {
438438
*/
439439
gboolean delete_on_close;
440440
char *delete_on_close_filename;
441+
442+
/* If this target doesn't support read and seek (eg. a pipe) and
443+
* vips_target_need_seek() has been called (eg. by tiffsave), we need to
444+
* redirect output to this temp target and do a copy to the real output on
445+
* close.
446+
*/
447+
VipsTarget *temp;
441448
};
442449

443450
typedef struct _VipsTargetClass {
@@ -496,6 +503,8 @@ VipsTarget *vips_target_new_temp(VipsTarget *target);
496503
VIPS_API
497504
int vips_target_write(VipsTarget *target, const void *data, size_t length);
498505
VIPS_API
506+
int vips_target_need_seek(VipsTarget *target);
507+
VIPS_API
499508
gint64 vips_target_read(VipsTarget *target, void *buffer, size_t length);
500509
VIPS_API
501510
gint64 vips_target_seek(VipsTarget *target, gint64 offset, int whence);

libvips/iofuncs/target.c

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ vips_target_finalize(GObject *gobject)
9797
G_OBJECT_CLASS(vips_target_parent_class)->finalize(gobject);
9898
}
9999

100+
static void
101+
vips_target_dispose(GObject *gobject)
102+
{
103+
VipsTarget *target = VIPS_TARGET(gobject);
104+
105+
VIPS_DEBUG_MSG("vips_target_dispose:\n");
106+
107+
VIPS_UNREF(target->temp);
108+
109+
G_OBJECT_CLASS(vips_target_parent_class)->dispose(gobject);
110+
}
111+
100112
static int
101113
vips_target_build(VipsObject *object)
102114
{
@@ -275,6 +287,7 @@ vips_target_class_init(VipsTargetClass *class)
275287
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
276288
VipsObjectClass *object_class = VIPS_OBJECT_CLASS(class);
277289

290+
gobject_class->dispose = vips_target_dispose;
278291
gobject_class->finalize = vips_target_finalize;
279292
gobject_class->set_property = vips_object_set_property;
280293
gobject_class->get_property = vips_object_get_property;
@@ -427,8 +440,7 @@ vips_target_new_temp(VipsTarget *based_on)
427440

428441
if (!(filename = vips__temp_name("%s.target")))
429442
return NULL;
430-
if ((descriptor =
431-
vips__open_image_write(filename, TRUE)) < 0) {
443+
if ((descriptor = vips__open_image_write(filename, TRUE)) < 0) {
432444
g_free(filename);
433445
return NULL;
434446
}
@@ -468,10 +480,9 @@ vips_target_write_unbuffered(VipsTarget *target,
468480
* one to make sure we don't get stuck in this loop.
469481
*/
470482
if (bytes_written <= 0) {
471-
vips_error_system(errno,
472-
vips_connection_nick(
473-
VIPS_CONNECTION(target)),
474-
"%s", _("write error"));
483+
const char *nick = vips_connection_nick(VIPS_CONNECTION(target));
484+
485+
vips_error_system(errno, nick, "%s", _("write error"));
475486
return -1;
476487
}
477488

@@ -515,20 +526,52 @@ vips_target_write(VipsTarget *target, const void *buffer, size_t length)
515526
{
516527
VIPS_DEBUG_MSG("vips_target_write: %zd bytes\n", length);
517528

518-
if (length > VIPS_TARGET_BUFFER_SIZE - target->write_point &&
519-
vips_target_flush(target))
520-
return -1;
521-
522-
if (length > VIPS_TARGET_BUFFER_SIZE - target->write_point) {
523-
/* Still too large? Do an unbuffered write.
524-
*/
525-
if (vips_target_write_unbuffered(target, buffer, length))
529+
if (target->temp) {
530+
if (vips_target_write(target->temp, data, length))
526531
return -1;
527532
}
528533
else {
529-
memcpy(target->output_buffer + target->write_point,
530-
buffer, length);
531-
target->write_point += length;
534+
if (length > VIPS_TARGET_BUFFER_SIZE - target->write_point &&
535+
vips_target_flush(target))
536+
return -1;
537+
538+
if (length > VIPS_TARGET_BUFFER_SIZE - target->write_point) {
539+
/* Still too large? Do an unbuffered write.
540+
*/
541+
if (vips_target_write_unbuffered(target, buffer, length))
542+
return -1;
543+
}
544+
else {
545+
memcpy(target->output_buffer + target->write_point, buffer, length);
546+
target->write_point += length;
547+
}
548+
}
549+
550+
return 0;
551+
}
552+
553+
/**
554+
* vips_target_need_seek:
555+
* @target: target to operate on
556+
*
557+
* Some writers need to be able to seek the output (for example, `tiffsave`),
558+
* however, some targets (eg. pipes) don't support this.
559+
*
560+
* Calling `vips_target_need_seek()` on a target with no seek method redirects
561+
* output to a temporary file or to memory, then on close, copies that object
562+
* to the output.
563+
*
564+
* Returns: 0 on success, -1 on error.
565+
*/
566+
int
567+
vips_target_need_seek(VipsTarget *target)
568+
{
569+
g_assert(!target->temp);
570+
571+
if (vips_target_seek(target, 0, SEEK_CUR) != -1) {
572+
VIPS_DEBUG_MSG("vips_target_need_seek: redirecting output to temp\n");
573+
if (!(target->temp = vips_target_new_temp(target)))
574+
return -1;
532575
}
533576

534577
return 0;
@@ -558,10 +601,17 @@ vips_target_read(VipsTarget *target, void *buffer, size_t length)
558601

559602
VIPS_DEBUG_MSG("vips_target_read: %zd bytes\n", length);
560603

561-
if (vips_target_flush(target))
562-
return -1;
604+
if (target->temp) {
605+
if (vips_target_read(target->temp, buffer, length))
606+
return -1;
607+
}
608+
else {
609+
if (vips_target_flush(target) ||
610+
class->read(target, buffer, length))
611+
return -1;
612+
}
563613

564-
return class->read(target, buffer, length);
614+
return 0;
565615
}
566616

567617
/**
@@ -584,17 +634,21 @@ vips_target_seek(VipsTarget *target, gint64 position, int whence)
584634

585635
gint64 new_position;
586636

587-
VIPS_DEBUG_MSG("vips_target_seek: pos = %" G_GINT64_FORMAT
588-
", whence = %d\n",
589-
position, whence);
637+
if (target->temp)
638+
new_position = vips_target_seek(target->temp, position, whence);
639+
else {
640+
VIPS_DEBUG_MSG("vips_target_seek: pos = %" G_GINT64_FORMAT
641+
", whence = %d\n",
642+
position, whence);
590643

591-
if (vips_target_flush(target))
592-
return -1;
644+
if (vips_target_flush(target))
645+
return -1;
593646

594-
new_position = class->seek(target, position, whence);
647+
new_position = class->seek(target, position, whence);
595648

596-
VIPS_DEBUG_MSG("vips_target_seek: new_position = %" G_GINT64_FORMAT "\n",
597-
new_position);
649+
VIPS_DEBUG_MSG("vips_target_seek: "
650+
"new_position = %" G_GINT64_FORMAT "\n", new_position);
651+
}
598652

599653
return new_position;
600654
}

0 commit comments

Comments
 (0)