@@ -4278,7 +4278,8 @@ static std::optional<ImageGenerationEmbeds> prepare_image_generation_embeds(sd_c
42784278
42794279static sd_image_t * decode_image_outputs (sd_ctx_t * sd_ctx,
42804280 const GenerationRequest& request,
4281- const std::vector<sd::Tensor<float >>& final_latents) {
4281+ const std::vector<sd::Tensor<float >>& final_latents,
4282+ int * num_images_out) {
42824283 if (final_latents.empty ()) {
42834284 LOG_ERROR (" no latent images to decode" );
42844285 return nullptr ;
@@ -4320,11 +4321,14 @@ static sd_image_t* decode_image_outputs(sd_ctx_t* sd_ctx,
43204321 return nullptr ;
43214322 }
43224323
4323- sd_image_t * result_images = (sd_image_t *)calloc (request.batch_count , sizeof (sd_image_t ));
4324+ int image_count = static_cast <int >(decoded_images.size ());
4325+ sd_image_t * result_images = (sd_image_t *)calloc (image_count, sizeof (sd_image_t ));
43244326 if (result_images == nullptr ) {
43254327 return nullptr ;
43264328 }
4327- memset (result_images, 0 , request.batch_count * sizeof (sd_image_t ));
4329+ if (num_images_out != nullptr ) {
4330+ *num_images_out = image_count;
4331+ }
43284332
43294333 for (size_t i = 0 ; i < decoded_images.size (); i++) {
43304334 result_images[i] = tensor_to_sd_image (decoded_images[i]);
@@ -4517,9 +4521,18 @@ static std::vector<float> make_hires_sigma_schedule(sd_ctx_t* sd_ctx,
45174521 sigmas.end ());
45184522}
45194523
4520- SD_API sd_image_t * generate_image (sd_ctx_t * sd_ctx, const sd_img_gen_params_t * sd_img_gen_params) {
4524+ SD_API bool generate_image (sd_ctx_t * sd_ctx,
4525+ const sd_img_gen_params_t * sd_img_gen_params,
4526+ sd_image_t ** images_out,
4527+ int * num_images_out) {
4528+ if (images_out != nullptr ) {
4529+ *images_out = nullptr ;
4530+ }
4531+ if (num_images_out != nullptr ) {
4532+ *num_images_out = 0 ;
4533+ }
45214534 if (sd_ctx == nullptr || sd_img_gen_params == nullptr ) {
4522- return nullptr ;
4535+ return false ;
45234536 }
45244537
45254538 sd_ctx->sd ->reset_cancel_flag ();
@@ -4542,7 +4555,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
45424555 &request,
45434556 &plan);
45444557 if (!latents_opt.has_value ()) {
4545- return nullptr ;
4558+ return false ;
45464559 }
45474560 ImageGenerationLatents latents = std::move (*latents_opt);
45484561
@@ -4552,7 +4565,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
45524565 &plan,
45534566 &latents);
45544567 if (!embeds_opt.has_value ()) {
4555- return nullptr ;
4568+ return false ;
45564569 }
45574570 ImageGenerationEmbeds embeds = std::move (*embeds_opt);
45584571
@@ -4562,7 +4575,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
45624575 sd_cancel_mode_t cancel = sd_ctx->sd ->get_cancel_flag ();
45634576 if (cancel == SD_CANCEL_ALL ) {
45644577 LOG_ERROR (" cancelling generation" );
4565- return nullptr ;
4578+ return false ;
45664579 }
45674580 if (cancel == SD_CANCEL_NEW_LATENTS ) {
45684581 LOG_INFO (" cancelling new latent generation, returning %zu/%d completed latents" ,
@@ -4614,29 +4627,29 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
46144627 b + 1 ,
46154628 request.batch_count ,
46164629 (sampling_end - sampling_start) * 1 .0f / 1000 );
4617- return nullptr ;
4630+ return false ;
46184631 }
46194632 int64_t denoise_end = ggml_time_ms ();
46204633 LOG_INFO (" generating %zu latent images completed, taking %.2fs" ,
46214634 final_latents.size (),
46224635 (denoise_end - denoise_start) * 1 .0f / 1000 );
46234636 if (final_latents.empty ()) {
46244637 LOG_ERROR (" no latent images generated" );
4625- return nullptr ;
4638+ return false ;
46264639 }
46274640
46284641 if (request.hires .enabled && request.hires .target_width > 0 ) {
46294642 if (sd_ctx->sd ->get_cancel_flag () == SD_CANCEL_ALL ) {
46304643 LOG_ERROR (" cancelling generation before hires fix" );
4631- return nullptr ;
4644+ return false ;
46324645 }
46334646 LOG_INFO (" hires fix: upscaling to %dx%d" , request.hires .target_width , request.hires .target_height );
46344647
46354648 std::unique_ptr<UpscalerGGML> hires_upscaler;
46364649 if (request.hires .upscaler == SD_HIRES_UPSCALER_MODEL ) {
46374650 if (sd_ctx->sd ->get_cancel_flag () == SD_CANCEL_ALL ) {
46384651 LOG_ERROR (" cancelling generation before hires model load" );
4639- return nullptr ;
4652+ return false ;
46404653 }
46414654 LOG_INFO (" hires fix: loading model upscaler from '%s'" , request.hires .model_path );
46424655 hires_upscaler = std::make_unique<UpscalerGGML>(sd_ctx->sd ->n_threads ,
@@ -4649,7 +4662,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
46494662 if (!hires_upscaler->load_from_file (request.hires .model_path ,
46504663 sd_ctx->sd ->n_threads )) {
46514664 LOG_ERROR (" load hires model upscaler failed" );
4652- return nullptr ;
4665+ return false ;
46534666 }
46544667 }
46554668
@@ -4673,7 +4686,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
46734686 for (int b = 0 ; b < (int )final_latents.size (); b++) {
46744687 if (sd_ctx->sd ->get_cancel_flag () == SD_CANCEL_ALL ) {
46754688 LOG_ERROR (" cancelling generation during hires fix" );
4676- return nullptr ;
4689+ return false ;
46774690 }
46784691 int64_t cur_seed = request.seed + b;
46794692 sd_ctx->sd ->rng ->manual_seed (cur_seed);
@@ -4684,7 +4697,7 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
46844697 request,
46854698 hires_upscaler.get ());
46864699 if (upscaled.empty ()) {
4687- return nullptr ;
4700+ return false ;
46884701 }
46894702
46904703 sd::Tensor<float > noise = sd::randn_like<float >(upscaled, sd_ctx->sd ->rng );
@@ -4738,24 +4751,33 @@ SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* s
47384751 b + 1 ,
47394752 (int )final_latents.size (),
47404753 (hires_sample_end - hires_sample_start) * 1 .0f / 1000 );
4741- return nullptr ;
4754+ return false ;
47424755 }
47434756 int64_t hires_denoise_end = ggml_time_ms ();
47444757 LOG_INFO (" hires fix completed, taking %.2fs" , (hires_denoise_end - hires_denoise_start) * 1 .0f / 1000 );
47454758
47464759 final_latents = std::move (hires_final_latents);
47474760 }
47484761
4749- auto result = decode_image_outputs (sd_ctx, request, final_latents);
4762+ int num_images = 0 ;
4763+ auto result = decode_image_outputs (sd_ctx, request, final_latents, &num_images);
47504764 if (result == nullptr ) {
4751- return nullptr ;
4765+ return false ;
47524766 }
47534767
47544768 sd_ctx->sd ->lora_stat ();
47554769
47564770 int64_t t1 = ggml_time_ms ();
47574771 LOG_INFO (" generate_image completed in %.2fs" , (t1 - t0) * 1 .0f / 1000 );
4758- return result;
4772+ if (num_images_out != nullptr ) {
4773+ *num_images_out = num_images;
4774+ }
4775+ if (images_out != nullptr ) {
4776+ *images_out = result;
4777+ } else {
4778+ free_sd_images (result, num_images);
4779+ }
4780+ return true ;
47594781}
47604782
47614783static std::optional<ImageGenerationLatents> prepare_video_generation_latents (sd_ctx_t * sd_ctx,
0 commit comments