[FERTIG !!! ] Optipng und Multicore nutzung -> lösung vorhanden :)

Heyho

kurz zur einleitung, optipng (aktuelle verrsion 0.6.3.) bietet die funktionaltität pngs ohne quallittätsverlust zu optimieren und damit platz zu spaaren. grade bei webgrafiken ist das für mich unersetzbar das tool.

nun aber auch direkt zu meinem problem, das programm unterstützt keinen multicore und wenn ich ne große menge von pngs optimieren will braucht das mit hohen einstellugnen recht lange, da es einfach nur ne bruteforce methode zum optimieren nutzt.

jetzt also mein plan, wenn ich 20 datein habe, dann starte ich das einfach für jeweils 5 daten ings. 4mal um alle 4 kerne zu nutzen.
einfacher gedacht als gemacht, weil ich hab mich kurz umgeschaut, wie ich das am besten mit ner bat unter windows hinbekomme, aber bin da nicht weiter vorran gekommen, sowas wie "mehrere" threads zu starten bzw. die datein in einem verzeichnis alle aufzunehmen (nur pngs!) und eben auf 4 programme zu verteilen.

die aufruf von optipng sieht zb eben so aus:

Code:
optipng -zc1-9 -zm1-9 -zs0-3 -f0-5 *.png

hat also einer ne idee, wie ich das gut umsetzen kann?
ne idee war natürlich auch, einfach das direkt in den code mit reinzuhacken, aber das geben meine c kenntnisse (die sehr sehr gering sind) nicht her :|

------------------------------------------
edit:

da hats mich gepackt, und ich fang einfach mal an, bissl c zu lernen und mir da nen kleines tool zu schreiben, was mir optipng aufruft.

mit den threads, das habsch schon hinbekommen, verzeichnis auslesen mit etwas googlen auch aber nun folgendes:

ich möcht alle dateinamen mit png in meinem verzeichnis ja irgendwie abspeicher, quasi in ein string array, ... in php kein thema: $arr[] = "neue wert ins array"; und zack fertig.
aber wie macht man sowas in c? ich komm grad nicht weiter...

Code:
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>         // needed for _beginthread()
#include <dirent.h>

void  runthread( void * );
int  ispng( char c[]);

INT threadcount;
INT imagecount = 5;

int main()
{

    char pfad[] = "L:\\www.verfriemelt.org\\img";
    threadcount = 0;
    
    //pfad auslesen, nach pngs suchen....
    
    DIR *verzeichnis;
    struct dirent *datei;
    
    //verzeichnis öffnen
    verzeichnis = opendir(pfad);
    
    while (datei = readdir(verzeichnis)) {
            
            printf(datei->d_name);
            
            if (ispng(datei->d_name)) {
                printf(" ist ein png....");
            }
            
            printf("\n");
    }

    /*
    while(1) {
        if (threadcount < 4 && imagecount > 0) {
            threadcount++;
            imagecount--;
            printf("startthread %d \n",threadcount);
            _beginthread( runthread, 0, (void*)threadcount );
        } else {
            Sleep(500);
            printf("waiting...\n");
        }
        
        if (imagecount == 0) {
            printf("done... exit \n");
            return 0;
        }
    }

    //WaitForSingleObject( hth1, INFINITE ); */
}

int ispng( char c[]) {
    
    char ext[] = ".png";
    
    int i,j,k;
    
    for (i = 0;i < 5; i++) {
        j = strlen(c) - i;
        k = strlen(ext) - i;
        if (c[j] != ext[k]) {
          return 0;
        }
    }
    
    return 1;
}

void  runthread( void *arg )
{
    int i;
    for (i = 10; i > 0; i--) {
      printf("  thread %d: %d \n",(INT_PTR)arg,i);
      Sleep(100);
    }
    
    //printf( "The silly() function was passed %d\n", (INT_PTR)arg ) ;
    
    threadcount--;
}

wenn ich da bis dahin sonst noch ein absolutes nogo produziert hab, sagts mir :)
 
Du könntest dir eine rekursive Datenstruktur schreiben (spricht verkettete Liste) und darin deine Dateinamen abspeichern, siehe beispielsweise http://moritz.faui2k3.org/de/dmisc/einfach-verkettete-listen. Das wäre wohl etwas einfacher, als deine Dateinamen in einem Array zu speichern ;)

Um Verzeichnisse auszulesen nutzt du (struct dirent *) opendir und (DIR *) readdir.
 
das mit den listen habsch schon irgendwo gefunden gehabt und versucht irgendwie anzuwenden, wenn ich den code aber so compiliere bekomm ich keine fehler und beim ausführen stürzt das kommentarlos ab :(

wieso ist das in c nur so stressig, da verliert man echt die lust :|


Code:
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>         // needed for _beginthread()
#include <dirent.h>

void  runthread( void * );
int  ispng( char c[]);



typedef struct elem *list;
typedef struct elem {
    char *name;
    list next;
} listtype;

list l = NULL;
list *start;
INT threadcount;
INT imagecount;

int main()
{
  
    char pfad[] = "L:\\www.verfriemelt.org\\img";
    threadcount = 0;
    
    //pfad auslesen, nach pngs suchen....
    
    DIR *verzeichnis;
    struct dirent *datei;
    
    //verzeichnis öffnen
    verzeichnis = opendir(pfad);
    
    //liste anlegen
    list l;
    
    while (datei = readdir(verzeichnis)) {
            if (ispng(datei->d_name)) {
                
                if (l == NULL) {
                    
                    //neues listen element
                    list neu;
                    neu = (list) malloc(sizeof(listtype));
                    neu->name = (char*)malloc(strlen(datei->d_name)*sizeof(char));
                    
                    //filenamen abspeichern
                    neu->name = datei->d_name;
                    
                    //pointer übertragen 
                    l = neu;
                    l->next = NULL;

                } else {
                    //hilfeigen
                    list z;
                    //ursprung der liste kurz merken
                    z = l;
                    
                    //durchlaufen, bis der zeiger auf null zeigt
                    while(z->next != NULL) {
                        z = z->next;
                    }
                    
                    //neues element erstellen....
                    list neu;
                    neu = (list) malloc(sizeof(listtype));
                    neu->name = (char*)malloc(strlen(datei->d_name)*sizeof(char));
                    neu->name = datei->d_name;
                    neu->next = NULL;
                    //abspeichern
                    z->next = neu;
                }
            }
    }

    /*
    while(1) {
        if (threadcount < 4 && imagecount > 0) {
            threadcount++;
            imagecount--;
            printf("startthread %d \n",threadcount);
            _beginthread( runthread, 0, (void*)threadcount );
        } else {
            Sleep(500);
            printf("waiting...\n");
        }
        
        if (imagecount == 0) {
            printf("done... exit \n");
            return 0;
        }
    }

    //WaitForSingleObject( hth1, INFINITE ); */
}

int ispng( char c[]) {
    
    char ext[] = ".png";
    
    int i,j,k;
    
    for (i = 0;i < 5; i++) {
        j = strlen(c) - i;
        k = strlen(ext) - i;
        if (c[j] != ext[k]) {
          return 0;
        }
    }
    
    return 1;
}

void  runthread( void *arg )
{
    int i;
    for (i = 10; i > 0; i--) {
      printf("  thread %d: %d \n",(INT_PTR)arg,i);
      Sleep(100);
    }
    
    //printf( "The silly() function was passed %d\n", (INT_PTR)arg ) ;
    
    threadcount--;
}

wenn ich das jetzt aber ausführe, stürzt das ganze kommentarlos ab?!

es ist geschafft, es läuft alles.
zwar nicht wirklich sauber und gut wie ich es mir anfangs gedacht hab, aber ich hab die backen dicke :D prinzipiell arbeitet es so wie es soll und das reicht mir.
ich werd wohl nie wieder mit c nen programm schreiben, das hat mich stundenlanges kopfzerbrechen und rumgooglen für sone stupide aufgabe bescherrt... das tu ich mir kein zweites mal an :D

wie auch immer, hier der source:

Code:
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>         // needed for _beginthread()
#include <dirent.h>

void  runthread( void * );
int  ispng( char c[]);

INT file_i = 0;
INT threadcount = 0;
INT imagecount = 0;
char** files;

int main()
{
;
    char pfad[] = "./";
    threadcount = 0;
    
    //pfad auslesen, nach pngs suchen....
    
    DIR *verzeichnis;
    struct dirent *datei;
    
    //anzahl der daten feststellen
    verzeichnis = opendir(pfad);
    while (datei = readdir(verzeichnis)) {
        if (ispng(datei->d_name)) {
            imagecount++;
        }
    }
    closedir(verzeichnis);
    
    //speicher anfordern
    files = (char **) malloc (imagecount * sizeof (*files));
    
    // datennamen abspeichern....
    
    int count = 0;
    verzeichnis = opendir(pfad);
    while (datei = readdir(verzeichnis)) {
            if (ispng(datei->d_name)) {
                files[count] = strdup (datei->d_name);
                count++;
            }
    }
    closedir(verzeichnis);
    
    int i;
    for(i = 0; i < imagecount; i++) {
      printf(files[i]);
      printf("\n\n");
    }
    
    
    while(1) {
        if (threadcount < 4 && imagecount-file_i > 0) {
            printf("startthread %d \n",threadcount);
            _beginthread( runthread, 0, (void*)threadcount );
            Sleep(500);
        } else {
            Sleep(500);
        }
        
        if (threadcount == 0 && imagecount-file_i == 0) {
            printf("\n\n where done... \n");
            return 0;
        }

    }

    //WaitForSingleObject( hth1, INFINITE ); */
    
}

int ispng( char c[]) {
    
    char ext[] = ".png";
    
    int i,j,k;
    
    for (i = 0;i < 5; i++) {
        j = strlen(c) - i;
        k = strlen(ext) - i;
        if (c[j] != ext[k]) {
          return 0;
        }
    }
    
    return 1;
}

void  runthread( void *arg )
{
    threadcount++;
    file_i++;
    
    char* call = "optipng.exe -zc1-9 -zm1-9 -zs0-3 -f0-5 \"";
    int buflen = strlen(call) + strlen(files[0]) + strlen("\"");
    char *beide = (char *)malloc(buflen+1);
    strncpy(beide, call, buflen);
    strncat(beide, files[file_i], buflen);
    strncat(beide, "\"", buflen);
    system(beide);

    threadcount--;
}

und im anhang ne compilierte version ;)

zum arbeiten muss die optipng exe im %path% sein ;)
so, das wars!
ende aus vorbei!
 
Zurück
Oben