Eine Frage bei der Konvertierung vom PNG-Bild zum JPG-Bild mit Libpng



  • Guten Morgen, Alle

    Ich wollte ein Programm schreiben, das eine Konvertierung vom PNG-Bild zum JPG-Bild macht. Bisher habe ich folgendes getan:

    1. png.h eingebunden;

    2. habe eine read-Funktion geschrieben wie folgendes:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <time.h>
    #include <inttypes.h>
    
    #include "png.h"
    
    #include "pngio.h"
    #include "error.h"
    #include "image.h"
    
    /*==============================================================================*
     *  read_png    	    			                                            *
     *==============================================================================*/
    
    int x, y;
    
    int width, height;
    
    int channels;
    
    png_byte color_type;
    png_byte bit_depth;
    
    png_structp png_ptr;
    png_infop info_ptr;
    int number_of_passes;
    png_bytep *row_pointers;
    
    png_uint_32 w, h;
    size_t npixels;
    //png_uint_32* raster;
    //png_uint_32
    
    int read_png (char * input_filename, picture *thePicture, FILE *status_log)
    {
    	int err = no_err;	
    
    	char header[8];    // 8 is the maximum size that can be checked
    
            /* open file and test for it being a png */
            FILE *fp = fopen(input_filename, "rb");
            if (fp){		
    
    		//abort_("[read_png_file] File %s could not be opened for reading", file_name);
    
    		fread(header, 1, 8, fp);
    
    		/* checked out with a proper PNG signature */
    		if (png_check_sig(header, 8)){
    
    			/* initialize stuff */
    			png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
    			if (png_ptr){
    
    				info_ptr = png_create_info_struct(png_ptr);
    				if (info_ptr){
    
    					if (setjmp(png_jmpbuf(png_ptr))){
    
    						fprintf(status_log, "Error during init_io. \n");
    
    					}else{
    
    						//takes our file stream pointer(fp) and stores it in the png_ptr struct for later use.
    						png_init_io(png_ptr, fp);
    						//lets libpng know that we already checked the 8 signature bytes
    						png_set_sig_bytes(png_ptr, 8);
    
    						//information is stored in the information struct
    						png_read_info(png_ptr, info_ptr);
    
    						//png_read_update_info(png_ptr, info_ptr);
    
    						width = png_get_image_width(png_ptr, info_ptr);
    						height = png_get_image_height(png_ptr, info_ptr);
    
    						//w = png_get_image_width(png_ptr, info_ptr);
    						//h = png_get_image_height(png_ptr, info_ptr);
    
    						fprintf(status_log,"png-image-details: width=%i - height=%i\n",width,height);
    
    						//npixels = width * height;
    						npixels = width * height;
    
    						/* Read the whole image into memory at once. */
    
    						/* read file */
    						if (setjmp(png_jmpbuf(png_ptr)))
    
    							fprintf(status_log, "Error during read_image. \n");
    
    						png_uint_32 *raster = malloc(npixels * 4 *sizeof(png_uint_32));
    
    						//row_pointers = (png_bytep*) malloc(npixels * sizeof(png_bytep));
    						row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    
    						for (y=0; y<height; y++)
    							row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
    
    						png_read_image(png_ptr, row_pointers);						
    
    						if(raster != NULL){
    
    							channels = png_get_channels(png_ptr, info_ptr);
    							fprintf(status_log,"Bild-Kanal ist %d .\n", channels);
    
    							fprintf(status_log,"Bild ist geladen\n");
    
    							thePicture->pixelmap = row_pointers;
    							thePicture->width = width;
    							thePicture->height = height;
    							thePicture->type = png_type;
    
    						}else{
    
    								fprintf(status_log,"Memory error.\n");
    								err = mem_err;
    
    						}
    						fclose(fp);
    
    					}
    
    				}else{
    					fprintf(status_log, "png_create_info_struct failed. \n");
    					//err = mem_err;
    				}
    
    			}else{
    
    				fprintf(status_log, "png_create_read_struct failed. \n");
    			}
    
    		}else{
    
    			fprintf(status_log, "checking PNG failed. \n");
    
    		}
    
    	}else{
    
    		fprintf(status_log,"Error. Fail to open the png.\n");
    		err = file_err;
    
    	}
    
    	return err;
    
    }
    

    3. habe in einer h-Datei image.h die Struktur vom Bildern (RGB oder RGBA) deklariert und die Positionen jeder Zeile bestimmt.

    typedef struct pixel{
    
    pixelvalue r;
    pixelvalue g;
    pixelvalue b;
    
    }pixel
    
    typedef struct pixel3{
    
    pixelvalue r;
    pixelvalue g;
    pixelvalue b;
    pixelvalue a;
    
    }pixel3
    
    typedef struct image{
    
    pixel *pixelmap;
    int width;
    int height;
    
    }image
    
    typedef struct picture{
    
    pixel *pixelmap;
    int width;
    int height;
    int type; 
    
    }picture
    
    //Position
    
    get_pixel(x, y, image) (((pixel)(image->pixelmap))[(size_t)y*(size_t)image->width+(size_t)x]);
    get_pixel3(x, y, image) (((pixel3)(image->pixelmap))[(size_t)y*(size_t)image->width+(size_t)x]);
    

    4. Das Ergebnis ist aber nicht korrekt:

    1). PNG-Bild: http://imageshack.us/a/img854/5375/wu5x.png

    2). JPG-Bild: http://imageshack.us/a/img842/721/d5d2.jpg

    5. Kann mir jemand Tipps geben woran es liegen könnte und was für Funktionen von der Bibliotheken ich noch brauche?

    Herzlichen Dank.

    Freundliche Grüße.



  • Bist du sicher, dass der Fehler beim Einlesen ist?

    Wozu brauchst du raster? Du besorgst Speicher dafür, benutzt ihn aber gar nicht.
    Und gibst ihn auch nicht frei.



  • Vielen Dank für deine Antwort, DirkB

    Ich bin mir nicht sicher dass das Problem daran liegt. Ich weiß eigentlich nicht woran es liegen könnte...

    row_pointers kann auch Speicher belegen.

    Korrektur des Codes: in (pixel) sollte ein * sein -> (pixel*)

    //Position
    
    get_pixel(x, y, image) (((pixel*)(image->pixelmap))[(size_t)y*(size_t)image->width+(size_t)x]);
    get_pixel3(x, y, image) (((pixel3*)(image->pixelmap))[(size_t)y*(size_t)image->width+(size_t)x]);
    

    Viele Grüße.



  • Wie du an der Masse der Antworten siehst, kann keiner etwas mit deinen Angaben anfangen.

    Du weißt nicht ob der Fehler in dem gezeigten Code liegt,
    du weißt nicht warum du SPeicher allokierst,
    du verbesserst Code der nicht benutzt wird und
    du benutzt eine sehr spezielle Library.

    Das jpg-Bild sieht mir danach aus, als ob ein Header als Bilddaten abgelegt wird (der komische Weiße Streifen oben) und das die Spaltenanzahl nicht stimmt (Das Bild ist verschoben).

    Nimm mal ganz einfache Bilder (senkrechter Strich) mit durch 8 teilbaren Format (z.B. 256*256 Punkte)
    Dann kannst du immer noch Krumme Werte nehmen.


Log in to reply