Skip to content

Commit 9e4c29f

Browse files
committed
generate both gif and pick smaller (+1 squashed commits)
Squashed commits: [09122d0] generate both gif and pick the smaller one
1 parent 4117542 commit 9e4c29f

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

otherarch/sdcpp/avi_writer.h

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <string.h>
88

99
#include "stable-diffusion.h"
10+
#include "./gif.h" // charlietangora/gif-h
1011

1112
#ifndef MSF_GIF_IMPL
1213
#define MSF_GIF_IMPL
@@ -401,7 +402,7 @@ int create_mjpg_avi_membuf_from_sd_images(sd_image_t* images, int num_images, in
401402
// ---------------- Helper: create_gif_buf_from_sd_images ----------------
402403
// Builds a GIF in memory from an array of sd_image_t. Returns 0 on success, -1 on failure.
403404
// Caller must free(*out_data) when done.
404-
int create_gif_buf_from_sd_images(sd_image_t* images, int num_images, int fps, uint8_t** out_data, size_t *out_len)
405+
int create_gif_buf_from_sd_images_msf(sd_image_t* images, int num_images, int fps, uint8_t** out_data, size_t *out_len)
405406
{
406407
if(!images || num_images <= 0 || !out_data || !out_len) return -1;
407408

@@ -471,4 +472,96 @@ int create_gif_buf_from_sd_images(sd_image_t* images, int num_images, int fps,
471472
return 0;
472473
}
473474

475+
int create_gif_buf_from_sd_images_gifh(sd_image_t* images, int num_images, int fps, uint8_t** out_data, size_t *out_len)
476+
{
477+
if(!images || num_images <= 0 || !out_data || !out_len) return -1;
478+
479+
// basic parameter heuristics
480+
if(fps <= 0) fps = 16;
481+
uint32_t delay = (uint32_t)(100 / fps); // hundredths of a second per frame
482+
483+
int bitDepth = 8;
484+
bool dither = false;
485+
486+
// assume all images same size; use first
487+
uint32_t width = images[0].width;
488+
uint32_t height = images[0].height;
489+
490+
GifWriter gw;
491+
memset(&gw, 0, sizeof(gw));
492+
493+
if(!GifBegin(&gw, width, height, delay, bitDepth, dither))
494+
{
495+
if(gw.oldImage) GIF_FREE(gw.oldImage);
496+
497+
fprintf(stderr, "Error: GifBegin failed.\n");
498+
return -1;
499+
}
500+
501+
// Feed frames
502+
for (int i = 0; i < num_images; i++)
503+
{
504+
sd_image_t* img = &images[i];
505+
506+
if (img->width != width || img->height != height) {
507+
fprintf(stderr, "Frame %d has mismatched dimensions.\n", i);
508+
GifEnd(&gw);
509+
memfile_free(&gw.mem);
510+
return -1;
511+
}
512+
513+
// gif-h expects 4 channels (RGBA) or 3 channels (RGB). It quantizes internally.
514+
// If your images have 3 channels, that’s fine. If 4 channels, it also works.
515+
int channels = img->channel;
516+
if (channels != 3 && channels != 4) {
517+
fprintf(stderr, "Unsupported channel count: %d\n", channels);
518+
GifEnd(&gw);
519+
memfile_free(&gw.mem);
520+
return -1;
521+
}
522+
523+
// gif-h requires 4 channels (RGBA). If you only have RGB, add opaque alpha.
524+
uint8_t* frame_rgba = NULL;
525+
if (channels == 3) {
526+
frame_rgba = (uint8_t*)malloc(width * height * 4);
527+
for (int p = 0; p < width * height; p++) {
528+
frame_rgba[p*4+0] = img->data[p*3+0];
529+
frame_rgba[p*4+1] = img->data[p*3+1];
530+
frame_rgba[p*4+2] = img->data[p*3+2];
531+
frame_rgba[p*4+3] = 255;
532+
}
533+
} else {
534+
frame_rgba = img->data; // already RGBA
535+
}
536+
537+
if(!GifWriteFrame(&gw, frame_rgba, width, height, delay, bitDepth, dither))
538+
{
539+
fprintf(stderr, "GIF Write Failed\n");
540+
GifEnd(&gw);
541+
memfile_free(&gw.mem);
542+
return -1;
543+
}
544+
545+
if (channels == 3) {
546+
free(frame_rgba);
547+
}
548+
}
549+
550+
if(!GifEnd(&gw))
551+
{
552+
memfile_free(&gw.mem);
553+
return -1;
554+
}
555+
556+
uint8_t* buf = memfile_detach(&gw.mem, out_len);
557+
if(!buf)
558+
{
559+
memfile_free(&gw.mem);
560+
return -1;
561+
}
562+
563+
*out_data = buf;
564+
return 0;
565+
}
566+
474567
#endif // __AVI_WRITER_H__

otherarch/sdcpp/sdtype_adapter.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,20 +944,46 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs)
944944
uint8_t * out_data = nullptr;
945945
size_t out_len = 0;
946946
int status = 0;
947+
947948
if(vid_req_avi==1)
948949
{
949950
status = create_mjpg_avi_membuf_from_sd_images(results, generated_num_results, 16, 40, &out_data,&out_len);
950951
}
951952
else
952953
{
953-
status = create_gif_buf_from_sd_images(results, generated_num_results, 16, &out_data,&out_len);
954+
uint8_t * out_data_a = nullptr;
955+
uint8_t * out_data_b = nullptr;
956+
int status_a = 0;
957+
int status_b = 0;
958+
size_t out_len_a = 0;
959+
size_t out_len_b = 0;
960+
status_a = create_gif_buf_from_sd_images_gifh(results, generated_num_results, 16, &out_data_a,&out_len_a);
961+
status_b = create_gif_buf_from_sd_images_msf(results, generated_num_results, 16, &out_data_b,&out_len_b);
962+
if(!sd_is_quiet && sddebugmode==1)
963+
{
964+
printf("GIF-H Len: %zu, MSF Len: %zu\n",out_len_a,out_len_b);
965+
}
966+
if(status_a==0 && out_len_a < out_len_b)
967+
{
968+
free(out_data_b);
969+
out_len = out_len_a;
970+
out_data = out_data_a;
971+
status = status_a;
972+
}
973+
else
974+
{
975+
free(out_data_a);
976+
out_len = out_len_b;
977+
out_data = out_data_b;
978+
status = status_b;
979+
}
954980
}
955981

956982
if(!sd_is_quiet && sddebugmode==1)
957983
{
958984
if(status==0)
959985
{
960-
printf("Video Saved (Len %d)!\n",out_len);
986+
printf("Video Saved (Len %zu)!\n",out_len);
961987
}else{
962988
printf("Save Failed!\n");
963989
}

0 commit comments

Comments
 (0)