mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-08 02:52:12 +00:00
masking and inpainting works
This commit is contained in:
1 parent
4521088453
commit
1bc275293b
6 files changed
+74
-6
No files matched your search
+2
-2
@@ -131,8 +131,8 @@ pub async fn enqueue_image_inpaint_command(
|
||||
sora_task_queue: State<'_, SoraTaskQueue>,
|
||||
) -> ResponseOrErrorType<EnqueueImageInpaintSuccessResponse, EnqueueInpaintImageErrorType> {
|
||||
|
||||
info!("enqueue_image_inpaint_command called; full request: {:?}",
|
||||
&request);
|
||||
info!("enqueue_image_inpaint_command called; model: {:?}, image_media_token: {:?}, prompt: {:?}",
|
||||
&request.model, &request.image_media_token, &request.prompt);
|
||||
|
||||
let result = handle_request(
|
||||
&request,
|
||||
|
||||
+3
-2
@@ -47,6 +47,7 @@ use storyteller_client::media_files::get_media_file::get_media_file;
|
||||
use storyteller_client::media_files::upload_image_media_file_from_bytes::upload_image_media_file_from_bytes;
|
||||
use storyteller_client::media_files::upload_image_media_file_from_file::upload_image_media_file_from_file;
|
||||
use tauri::AppHandle;
|
||||
use images::mask_images::normalize_image_bytes_to_flux_mask::normalize_image_bytes_to_flux_mask;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
pub async fn handle_flux_pro_1_inpaint_artcraft(
|
||||
@@ -156,7 +157,7 @@ async fn get_mask(
|
||||
let image_bytes = request.mask_image_raw_bytes.as_ref()
|
||||
.ok_or(InternalImageInpaintError::NoMaskImageSpecified)?;
|
||||
|
||||
let png_with_dims = image_bytes_to_png_bytes_with_dimensions(image_bytes)
|
||||
let image_bytes = normalize_image_bytes_to_flux_mask(image_bytes)
|
||||
.map_err(|err| {
|
||||
error!("Failed to convert image bytes to png: {:?}", err);
|
||||
InternalImageInpaintError::CouldNotEncodeMask
|
||||
@@ -167,7 +168,7 @@ async fn get_mask(
|
||||
let result = upload_image_media_file_from_bytes(
|
||||
&app_env_configs.storyteller_host,
|
||||
Some(&storyteller_creds),
|
||||
png_with_dims.png_bytes
|
||||
image_bytes.0
|
||||
).await
|
||||
.map_err(|err| {
|
||||
error!("Failed to upload image media file: {:?}", err);
|
||||
|
||||
@@ -26,6 +26,7 @@ pub use image;
|
||||
pub mod encoding;
|
||||
pub mod error;
|
||||
pub mod image_info;
|
||||
pub mod mask_images;
|
||||
pub mod resize_image_file_preserving_aspect;
|
||||
pub mod resize_preserving_aspect;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod normalize_image_bytes_to_flux_mask;
|
||||
@@ -0,0 +1,67 @@
|
||||
use crate::error::ImagesError;
|
||||
use image::{GenericImage, GenericImageView, ImageFormat, ImageReader, Rgba};
|
||||
use std::io::Cursor;
|
||||
|
||||
pub struct PngBytes(pub Vec<u8>);
|
||||
|
||||
/// Normalize arbitrary image bytes to a PNG format image.
|
||||
/// Make sure the bitmap is in the correct mask format.
|
||||
pub fn normalize_image_bytes_to_flux_mask(
|
||||
arbitrary_image_bytes: &[u8],
|
||||
) -> Result<PngBytes, ImagesError> {
|
||||
|
||||
let reader = ImageReader::new(Cursor::new(arbitrary_image_bytes));
|
||||
|
||||
let mut image = reader
|
||||
.with_guessed_format()? // NB: Can raise IoError.
|
||||
.decode()?;
|
||||
|
||||
let (width, height) = image.dimensions();
|
||||
|
||||
//let mut corrected_mask: ImageBuffer<Rgba<u8>, Vec<u8>> = ImageBuffer::new(width, height);
|
||||
|
||||
// Iterate through each pixel
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let rgba_pixel = image.get_pixel(x, y);
|
||||
|
||||
if rgba_pixel[3] == 0 {
|
||||
// Alpha pixel is transparent
|
||||
// Set to black. Mask ignore region.
|
||||
image.put_pixel(x, y, Rgba([0, 0, 0, 255]));
|
||||
} else {
|
||||
// Set to white. Mask interest region.
|
||||
image.put_pixel(x, y, Rgba([255, 255, 255, 255]));
|
||||
}
|
||||
|
||||
/*match pixel.channels().get(4) {
|
||||
Some(0) => {
|
||||
// Alpha pixel is transparent
|
||||
// Set to black. Mask ignore region.
|
||||
pixel = Rgba([0, 0, 0, 255]);
|
||||
}
|
||||
_ => {
|
||||
// Set to white. Mask interest region.
|
||||
pixel = Rgba([255, 255, 255, 255]);
|
||||
},
|
||||
}
|
||||
|
||||
let rgb_pixel = pixel.to_rgba(); // Convert to Rgba<u8>
|
||||
|
||||
// Check if the pixel is pure black (R=0, G=0, B=0)
|
||||
if rgb_pixel[0] == 0 && rgb_pixel[1] == 0 && rgb_pixel[2] == 0 {
|
||||
// Set the pixel to white (R=255, G=255, B=255)
|
||||
corrected_mask.put_pixel(x, y, Rgba([255, 255, 255, 255]));
|
||||
} else {
|
||||
// Keep the original color for non-black pixels
|
||||
corrected_mask.put_pixel(x, y, rgb_pixel);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mut output_bytes: Vec<u8> = Vec::new();
|
||||
image.write_to(&mut Cursor::new(&mut output_bytes), ImageFormat::Png)?;
|
||||
|
||||
Ok(PngBytes(output_bytes))
|
||||
}
|
||||
@@ -895,8 +895,6 @@ export const Modal = ({
|
||||
>
|
||||
{/* Animated Modal Content */}
|
||||
{transitions((styles, item) => {
|
||||
// Debug logging - remove this after testing
|
||||
console.log("Modal animation styles:", styles);
|
||||
return item ? (
|
||||
<Dialog.Content
|
||||
forceMount
|
||||
|
||||
Reference in new issue
Block a user