Improved Search
parent
cfe603d3ed
commit
193e7c1f9d
|
|
@ -17,6 +17,8 @@ and restart your stable-diffusion-webui, then you can see the new tab "Image Bro
|
||||||
Please be aware that when scanning a directory for the first time, the png-cache will be built. This can take several minutes, depending on the amount of images.
|
Please be aware that when scanning a directory for the first time, the png-cache will be built. This can take several minutes, depending on the amount of images.
|
||||||
|
|
||||||
## Recent updates
|
## Recent updates
|
||||||
|
- Improved Search
|
||||||
|
- Formatted EXIF display
|
||||||
- Initial support for videos
|
- Initial support for videos
|
||||||
- --image-browser-tmp-db command line parameter to offload database operations to a different location
|
- --image-browser-tmp-db command line parameter to offload database operations to a different location
|
||||||
- "All"-tab showing all the images from all tabs combined
|
- "All"-tab showing all the images from all tabs combined
|
||||||
|
|
|
||||||
|
|
@ -738,24 +738,37 @@ def check_ext(ext):
|
||||||
break
|
break
|
||||||
return found
|
return found
|
||||||
|
|
||||||
def exif_search(needle, haystack, use_regex, case_sensitive):
|
def exif_search(needle, haystack, use_regex):
|
||||||
found = False
|
# Convert both haystack and needle to lowercase for case-insensitive search
|
||||||
if use_regex:
|
|
||||||
if case_sensitive:
|
|
||||||
pattern = re.compile(needle, re.DOTALL)
|
|
||||||
else:
|
|
||||||
pattern = re.compile(needle, re.DOTALL | re.IGNORECASE)
|
|
||||||
if pattern.search(haystack) is not None:
|
|
||||||
found = True
|
|
||||||
else:
|
|
||||||
if not case_sensitive:
|
|
||||||
haystack = haystack.lower()
|
haystack = haystack.lower()
|
||||||
needle = needle.lower()
|
needle = needle.lower()
|
||||||
if needle in haystack:
|
|
||||||
found = True
|
|
||||||
return found
|
|
||||||
|
|
||||||
def get_all_images(dir_name, sort_by, sort_order, keyword, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex, case_sensitive):
|
if use_regex:
|
||||||
|
# Set regex flags for dotall (dot matches newline) and ignore case
|
||||||
|
flags = re.DOTALL | re.IGNORECASE
|
||||||
|
pattern = re.compile(needle, flags)
|
||||||
|
return pattern.search(haystack) is not None
|
||||||
|
else:
|
||||||
|
# Function to parse and evaluate the logical expression
|
||||||
|
def parse_expression(expression):
|
||||||
|
# Split the expression by 'or' to handle OR logic first
|
||||||
|
or_parts = expression.split(' or ')
|
||||||
|
for part in or_parts:
|
||||||
|
# Split each part by 'and' to handle AND logic
|
||||||
|
and_parts = part.split(' and ')
|
||||||
|
# Check if all conditions in the AND part are satisfied
|
||||||
|
if all(
|
||||||
|
(subpart[4:] not in haystack) if subpart.startswith('not ')
|
||||||
|
else (subpart in haystack)
|
||||||
|
for subpart in and_parts
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
# Return False if none of the OR parts evaluate to True
|
||||||
|
return False
|
||||||
|
|
||||||
|
return parse_expression(needle)
|
||||||
|
|
||||||
|
def get_all_images(dir_name, sort_by, sort_order, keyword, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex):
|
||||||
global current_depth
|
global current_depth
|
||||||
logger.debug("get_all_images")
|
logger.debug("get_all_images")
|
||||||
current_depth = 0
|
current_depth = 0
|
||||||
|
|
@ -791,7 +804,7 @@ def get_all_images(dir_name, sort_by, sort_order, keyword, tab_base_tag_box, img
|
||||||
print(f"Regex error: {e}")
|
print(f"Regex error: {e}")
|
||||||
if (use_regex and not regex_error) or not use_regex:
|
if (use_regex and not regex_error) or not use_regex:
|
||||||
if negative_prompt_search == "Yes":
|
if negative_prompt_search == "Yes":
|
||||||
fileinfos = [x for x in fileinfos if exif_search(exif_keyword, exif_cache[x[0]], use_regex, case_sensitive)]
|
fileinfos = [x for x in fileinfos if exif_search(exif_keyword, exif_cache[x[0]], use_regex)]
|
||||||
else:
|
else:
|
||||||
result = []
|
result = []
|
||||||
for file_info in fileinfos:
|
for file_info in fileinfos:
|
||||||
|
|
@ -803,13 +816,13 @@ def get_all_images(dir_name, sort_by, sort_order, keyword, tab_base_tag_box, img
|
||||||
if negative_prompt_search == "Only":
|
if negative_prompt_search == "Only":
|
||||||
start_index = start_index + len(np)
|
start_index = start_index + len(np)
|
||||||
sub_string = file_exif[start_index:end_index].strip()
|
sub_string = file_exif[start_index:end_index].strip()
|
||||||
if exif_search(exif_keyword, sub_string, use_regex, case_sensitive):
|
if exif_search(exif_keyword, sub_string, use_regex):
|
||||||
result.append(file_info)
|
result.append(file_info)
|
||||||
else:
|
else:
|
||||||
sub_string = file_exif[start_index:end_index].strip()
|
sub_string = file_exif[start_index:end_index].strip()
|
||||||
file_exif = file_exif.replace(sub_string, "")
|
file_exif = file_exif.replace(sub_string, "")
|
||||||
|
|
||||||
if exif_search(exif_keyword, file_exif, use_regex, case_sensitive):
|
if exif_search(exif_keyword, file_exif, use_regex):
|
||||||
result.append(file_info)
|
result.append(file_info)
|
||||||
fileinfos = result
|
fileinfos = result
|
||||||
filenames = [finfo[0] for finfo in fileinfos]
|
filenames = [finfo[0] for finfo in fileinfos]
|
||||||
|
|
@ -981,7 +994,7 @@ def set_tooltip_info(image_list):
|
||||||
image_browser_img_info_json = json.dumps(image_browser_img_info)
|
image_browser_img_info_json = json.dumps(image_browser_img_info)
|
||||||
return image_browser_img_info_json
|
return image_browser_img_info_json
|
||||||
|
|
||||||
def get_image_page(img_path, page_index, filenames, keyword, sort_by, sort_order, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex, case_sensitive):
|
def get_image_page(img_path, page_index, filenames, keyword, sort_by, sort_order, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex):
|
||||||
logger.debug("get_image_page")
|
logger.debug("get_image_page")
|
||||||
if img_path == "":
|
if img_path == "":
|
||||||
return [], page_index, [], "", "", "", 0, "", None, "", "[]", False, gr.update(visible=False)
|
return [], page_index, [], "", "", "", 0, "", None, "", "[]", False, gr.update(visible=False)
|
||||||
|
|
@ -991,7 +1004,7 @@ def get_image_page(img_path, page_index, filenames, keyword, sort_by, sort_order
|
||||||
tempfile.tempdir = shared.opts.temp_dir
|
tempfile.tempdir = shared.opts.temp_dir
|
||||||
|
|
||||||
img_path, _ = pure_path(img_path)
|
img_path, _ = pure_path(img_path)
|
||||||
filenames = get_all_images(img_path, sort_by, sort_order, keyword, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex, case_sensitive)
|
filenames = get_all_images(img_path, sort_by, sort_order, keyword, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword, negative_prompt_search, use_regex)
|
||||||
page_index = int(page_index)
|
page_index = int(page_index)
|
||||||
length = len(filenames)
|
length = len(filenames)
|
||||||
max_page_index = math.ceil(length / num_of_imgs_per_page)
|
max_page_index = math.ceil(length / num_of_imgs_per_page)
|
||||||
|
|
@ -1341,7 +1354,6 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
exif_keyword_search = gr.Textbox(value="", label="EXIF keyword search")
|
exif_keyword_search = gr.Textbox(value="", label="EXIF keyword search")
|
||||||
negative_prompt_search = gr.Radio(value="No", choices=["No", "Yes", "Only"], label="Search negative prompt", interactive=True)
|
negative_prompt_search = gr.Radio(value="No", choices=["No", "Yes", "Only"], label="Search negative prompt", interactive=True)
|
||||||
with gr.Row(elem_classes="exif-search-panel"):
|
with gr.Row(elem_classes="exif-search-panel"):
|
||||||
case_sensitive = gr.Checkbox(value=False, label="case sensitive")
|
|
||||||
use_regex = gr.Checkbox(value=False, label=r"regex - e.g. ^(?!.*Hires).*$")
|
use_regex = gr.Checkbox(value=False, label=r"regex - e.g. ^(?!.*Hires).*$")
|
||||||
with gr.Box() as ranking_filter_panel:
|
with gr.Box() as ranking_filter_panel:
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
|
|
@ -1724,7 +1736,7 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
if standard_ui or others_dir:
|
if standard_ui or others_dir:
|
||||||
turn_page_switch.change(
|
turn_page_switch.change(
|
||||||
fn=get_image_page,
|
fn=get_image_page,
|
||||||
inputs=[img_path, page_index, filenames, filename_keyword_search, sort_by, sort_order, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword_search, negative_prompt_search, use_regex, case_sensitive],
|
inputs=[img_path, page_index, filenames, filename_keyword_search, sort_by, sort_order, tab_base_tag_box, img_path_depth, ranking_filter, ranking_filter_min, ranking_filter_max, aes_filter_min, aes_filter_max, exif_keyword_search, negative_prompt_search, use_regex],
|
||||||
outputs=[filenames, page_index, image_gallery, img_file_name, img_file_time, img_file_info, visible_img_num, warning_box, hidden, image_page_list, image_browser_img_info, video_checkbox, video_checkbox_panel],
|
outputs=[filenames, page_index, image_gallery, img_file_name, img_file_time, img_file_info, visible_img_num, warning_box, hidden, image_page_list, image_browser_img_info, video_checkbox, video_checkbox_panel],
|
||||||
show_progress=show_progress_setting
|
show_progress=show_progress_setting
|
||||||
).then(
|
).then(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue