[LocalVisage] Does not work with images in folders in archives
Stash supports creating galleries from zip files containing images, but when building the face recognition model, the log fills up with these warning messages:
[Plugin / Local Visage] Image path does not exist and cannot be read: C:\path\to\file.zip\internal\path\to\image.jpg
I think the plugin is likely treating that as a direct path to an image on the file system, and not recognizing there is a zip archive in the middle of the path, that needs to be extracted to get the image
Actually, I'm looking at the Python code this morning, and it looks like it actually does open the zip file to get the image. For some reason, it's just not finding it. It doesn't appear to be throwing an exception, because I don't see the message from the catch in the logs log.warning(f"Error reading from ZIP file {image_path}: {e}"), but for some reason, it's still falling down to the false return. I'll add some more log messages and see which if statement it's failing on
Ok, the issue is with the slashes not matching. I wrote a quick Python script to open up the zip file and just print out the namelist. The internal path in Stash is fullwatermarked\047.jpg (with a backslash). The paths in the namelist from the zip file are:
...
'fullwatermarked/020.jpg',
'fullwatermarked/064.jpg',
'fullwatermarked/047.jpg',
'fullwatermarked/076.jpg',
..
All with forward slashes.
So if internal_path in zip_file.namelist(): is false, because the slashes aren't the same.
I fixed this locally with this code. It's not very DRY, but it does the job as a bandaid. It's possible that the zip file name list will always use forward slashes, which would make the first branch unnecessary, but I'm not 100% that's the case, and didn't want to assume or go digging though docs and specs
# Check if the internal path exists in the ZIP
if internal_path in zip_file.namelist():
# Extract to temporary file and return temp path
with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(internal_path)[1]) as tmp_file:
tmp_file.write(zip_file.read(internal_path))
return True, tmp_file.name
elif internal_path.replace("\\", "/") in zip_file.namelist():
fixed_path = internal_path.replace("\\", "/")
with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(fixed_path)[1]) as tmp_file:
tmp_file.write(zip_file.read(fixed_path))
return True, tmp_file.name