CivArchive
    ← All articles
    Published December 8, 2024by Gablingus

    How to extract png positive prompt and save to txt file in the same directory (linux)

    81 views1 reactions0 comments on CivitAI6 collected
    image taginglora trainingdata prepextract metadata

    How to extract positive prompt from a png file made with forge or a1111 or any sd png that has the prompt in the parameters metadata. (in linux)

    steps

    create a c file for the script

    nano extract_parameters.c

    make sure libpng-dev is installed

    sudo apt-get install libpng-dev

    paste in the script:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <libpng16/png.h>
    #include <sys/stat.h>
    
    // Function to check if a file has a .png extension
    int is_png(const char *filename) {
        const char *ext = strrchr(filename, '.');
        return ext && strcmp(ext, ".png") == 0;
    }
    
    // Function to extract "parameters" metadata
    void extract_parameters(const char *png_file, const char *output_dir) {
        printf("Processing file: %s\n", png_file);
    
        FILE *fp = fopen(png_file, "rb");
        if (!fp) {
            perror("Failed to open PNG file");
            return;
        }
    
        png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        png_infop info_ptr = png_create_info_struct(png_ptr);
    
        if (!png_ptr || !info_ptr) {
            fprintf(stderr, "Failed to initialize libpng\n");
            fclose(fp);
            return;
        }
    
        if (setjmp(png_jmpbuf(png_ptr))) {
            fprintf(stderr, "Error during PNG processing\n");
            fclose(fp);
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            return;
        }
    
        png_init_io(png_ptr, fp);
        png_read_info(png_ptr, info_ptr);
    
        png_textp text_ptr;
        int num_text;
    
        if (png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) {
            printf("Found %d text entries in file: %s\n", num_text, png_file);
            for (int i = 0; i < num_text; i++) {
                printf("Key: %s\n", text_ptr[i].key);
    
                if (strcmp(text_ptr[i].key, "parameters") == 0) {
                    char *parameters = text_ptr[i].text;
    
                    // Find "Negative prompt:" and truncate
                    char *negative_prompt = strstr(parameters, "Negative prompt:");
                    if (negative_prompt) {
                        *negative_prompt = '\0';
                    }
    
                    // Print the truncated value
                    printf("Extracted parameters metadata (truncated):\n%s\n", parameters);
    
                    // Determine output file path
                    char output_file[1024];
                    const char *base_name = strrchr(png_file, '/'); // Get the base name
                    base_name = base_name ? base_name + 1 : png_file; // Skip the slash if present
    
                    if (output_dir) {
                        // Save to the specified output directory
                        snprintf(output_file, sizeof(output_file), "%s/%.*s.txt", 
                                 output_dir, 
                                 (int)(strrchr(base_name, '.') - base_name), 
                                 base_name);
                    } else {
                        // Save in the same directory as the input PNG
                        char input_dir[1024];
                        strncpy(input_dir, png_file, strrchr(png_file, '/') - png_file);
                        input_dir[strrchr(png_file, '/') - png_file] = '\0';
                        snprintf(output_file, sizeof(output_file), "%s/%.*s.txt", 
                                 input_dir, 
                                 (int)(strrchr(base_name, '.') - base_name), 
                                 base_name);
                    }
    
                    // Write to file
                    FILE *out_fp = fopen(output_file, "w");
                    if (out_fp) {
                        fprintf(out_fp, "%s", parameters);
                        fclose(out_fp);
                        printf("Extracted metadata written to %s\n", output_file);
                    } else {
                        perror("Failed to write metadata file");
                    }
                    break;
                }
            }
        } else {
            printf("No metadata found in file: %s\n", png_file);
        }
    
        fclose(fp);
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    }
    
    // Function to process a directory
    void process_directory(const char *dir_path, const char *output_dir) {
        DIR *dir = opendir(dir_path);
        if (!dir) {
            perror("Failed to open directory");
            return;
        }
    
        struct dirent *entry;
        while ((entry = readdir(dir)) != NULL) {
            if (entry->d_type == DT_REG && is_png(entry->d_name)) {
                char full_path[1024];
                snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
                extract_parameters(full_path, output_dir);
            }
        }
    
        closedir(dir);
    }
    
    int main(int argc, char *argv[]) {
        if (argc < 2) {
            fprintf(stderr, "Usage: %s <directory> [output_directory]\n", argv[0]);
            return EXIT_FAILURE;
        }
    
        const char *input_dir = argv[1];
        const char *output_dir = NULL;
    
        if (argc >= 3) {
            output_dir = argv[2];
    
            // Check if output directory exists, create it if necessary
            struct stat st;
            if (stat(output_dir, &st) == -1) {
                if (mkdir(output_dir, 0700) == -1) {
                    perror("Failed to create output directory");
                    return EXIT_FAILURE;
                }
            } else if (!S_ISDIR(st.st_mode)) {
                fprintf(stderr, "Error: Output path is not a directory\n");
                return EXIT_FAILURE;
            }
        }
    
        process_directory(input_dir, output_dir);
    
        return EXIT_SUCCESS;
    }
    
    

    Compile the program:

    gcc extract_parameters.c -o extract_parameters -lpng

    Run program

    ./extract_parameters <input_directory> <output_directory>

    you can run it with just input_directory and it will save the .txt file to the input_directory. this will run very fast.