Skip to content

Commit d428835

Browse files
authored
Merge pull request #48 from DarthAffe/Inpainting
Fixed Image2Image and added Inpainting support
2 parents 59133b2 + 489c233 commit d428835

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

StableDiffusion.NET/Models/DiffusionModel.cs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,75 @@ public IImage<ColorRGB> ImageToImage(string prompt, IImage image, DiffusionParam
202202

203203
ObjectDisposedException.ThrowIf(_disposed, this);
204204
ArgumentNullException.ThrowIfNull(prompt);
205+
ArgumentNullException.ThrowIfNull(image);
205206

206207
parameter.Validate();
207208

208209
if (image is not IImage<ColorRGB> refImage)
209210
refImage = image.ConvertTo<ColorRGB>();
210211

211-
fixed (byte* imagePtr = refImage.AsRefImage())
212-
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), parameter);
212+
// DarthAffe 10.08.2024: Mask needs to be a 1 channel all max value image when it's not used - I really don't like this concept as it adds unnecessary allocations, but that's how it is :(
213+
Span<byte> maskBuffer = new byte[image.Width * image.Height];
214+
maskBuffer.Fill(byte.MaxValue);
215+
216+
fixed (byte* maskPtr = maskBuffer)
217+
{
218+
Native.sd_image_t maskImage = new()
219+
{
220+
width = (uint)image.Width,
221+
height = (uint)image.Height,
222+
channel = 1,
223+
data = maskPtr
224+
};
225+
226+
fixed (byte* imagePtr = refImage.AsRefImage())
227+
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), maskImage, parameter);
228+
}
229+
}
230+
231+
public IImage<ColorRGB> Inpaint(string prompt, IImage image, IImage mask, DiffusionParameter? parameter = null)
232+
{
233+
parameter ??= GetDefaultParameter();
234+
235+
ObjectDisposedException.ThrowIf(_disposed, this);
236+
ArgumentNullException.ThrowIfNull(prompt);
237+
ArgumentNullException.ThrowIfNull(image);
238+
ArgumentNullException.ThrowIfNull(mask);
239+
240+
if (image.Width != mask.Width) throw new ArgumentException("The mask needs to have the same with as the image.", nameof(mask));
241+
if (image.Height != mask.Height) throw new ArgumentException("The mask needs to have the same height as the image.", nameof(mask));
242+
243+
parameter.Validate();
244+
245+
if (image is not IImage<ColorRGB> refImage)
246+
refImage = image.ConvertTo<ColorRGB>();
247+
248+
// DarthAffe 10.08.2024: HPPH does currently not support monochrome images, that's why we need to convert it here. We're going for the simple conversion as the source image is supposed to be monochrome anyway.
249+
Span<byte> maskBuffer = new byte[image.Width * image.Height];
250+
for (int y = 0; y < image.Height; y++)
251+
for (int x = 0; x < image.Width; x++)
252+
{
253+
IColor color = mask[x, y];
254+
maskBuffer[(image.Width * y) + x] = (byte)Math.Round((color.R + color.G + color.B) / 3.0);
255+
}
256+
257+
fixed (byte* maskPtr = maskBuffer)
258+
{
259+
Native.sd_image_t maskImage = new()
260+
{
261+
width = (uint)image.Width,
262+
height = (uint)image.Height,
263+
channel = 1,
264+
data = maskPtr
265+
};
266+
267+
fixed (byte* imagePtr = refImage.AsRefImage())
268+
return ImageToImage(prompt, refImage.ToSdImage(imagePtr), maskImage, parameter);
269+
}
270+
213271
}
214272

215-
private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, DiffusionParameter parameter)
273+
private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, Native.sd_image_t mask, DiffusionParameter parameter)
216274
{
217275
ObjectDisposedException.ThrowIf(_disposed, this);
218276
ArgumentNullException.ThrowIfNull(prompt);
@@ -246,6 +304,7 @@ private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, Di
246304

247305
result = Native.img2img(_ctx,
248306
image,
307+
mask,
249308
prompt,
250309
parameter.NegativePrompt,
251310
parameter.ClipSkip,
@@ -283,6 +342,7 @@ private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, Di
283342

284343
result = Native.img2img(_ctx,
285344
image,
345+
mask,
286346
prompt,
287347
parameter.NegativePrompt,
288348
parameter.ClipSkip,
@@ -312,6 +372,7 @@ private IImage<ColorRGB> ImageToImage(string prompt, Native.sd_image_t image, Di
312372
{
313373
result = Native.img2img(_ctx,
314374
image,
375+
mask,
315376
prompt,
316377
parameter.NegativePrompt,
317378
parameter.ClipSkip,

StableDiffusion.NET/Models/Parameter/Extensions/DiffusionParameterExtension.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ public static DiffusionParameter WithNegativePrompt(this DiffusionParameter para
6464
return parameter;
6565
}
6666

67+
public static DiffusionParameter WithStrength(this DiffusionParameter parameter, float strength)
68+
{
69+
parameter.Strength = strength;
70+
71+
return parameter;
72+
}
73+
6774
public static DiffusionParameter WithSlgScale(this DiffusionParameter parameter, float slgScale)
6875
{
6976
parameter.SlgScale = slgScale;

StableDiffusion.NET/Native/Native.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ internal struct sd_image_t
102102
[LibraryImport(LIB_NAME, EntryPoint = "img2img")]
103103
internal static partial sd_image_t* img2img(sd_ctx_t* sd_ctx,
104104
sd_image_t init_image,
105+
sd_image_t mask_image,
105106
[MarshalAs(UnmanagedType.LPStr)] string prompt,
106107
[MarshalAs(UnmanagedType.LPStr)] string negative_prompt,
107108
int clip_skip,

0 commit comments

Comments
 (0)