Improved Search

pull/259/head
AlUlkesh 2024-06-25 10:38:26 +02:00
parent cfe603d3ed
commit 193e7c1f9d
2 changed files with 36 additions and 22 deletions

View File

@ -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

View File

@ -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(