[XLib] Bild wird nur mit 1/4 der Größe vom eigentlichen Format dargestellt



  • Hallo c-community,

    ich möchte das Bild meiner WebCam in einem Fenster darstellen. Folgendes habe ich schon fertig:
    - Camera Bilder aufnehmen
    - XLib Fenster erzeugen (in der Größe des Bildes, welches dargestellt werden soll
    - Darstellung des Bildes im Fenster

    Bei der Darstellung des Bildes im Fenster gibt es aber noch ein Problem. Das Bild ist mehrfach (4mal in X-Richtung und 2 mal in Y-Richtung (insgesamt 8 mal)) mit einem viertel der Originalgröße.

    Folgenden Code habe ich verwendet:
    Fenster initialisieren:

    if (NULL == ((*XWindow)->display = XOpenDisplay(NULL))) APPLICATION_Set_Error(V4LCamera->Application, XWINDOW, "failed to open display", 123, -1, APPLICATION_ERROR_MESSAGE);
    	(*XWindow)->screen = XDefaultScreen((*XWindow)->display);
    	(*XWindow)->gc = XDefaultGC((*XWindow)->display, 0);
    	(*XWindow)->root = RootWindow((*XWindow)->display, (*XWindow)->screen);
    	(*XWindow)->white_pixel = WhitePixel((*XWindow)->display, (*XWindow)->screen);
    	(*XWindow)->black_pixel = BlackPixel((*XWindow)->display, (*XWindow)->screen);
    	(*XWindow)->nplanes = DisplayPlanes((*XWindow)->display, (*XWindow)->screen);
    	(*XWindow)->visual = XDefaultVisual((*XWindow)->display, (*XWindow)->screen);
    	(*XWindow)->window = XCreateSimpleWindow(	(*XWindow)->display,
    												(*XWindow)->root,
    												(*XWindow)->X,
    												(*XWindow)->Y,
    												(*XWindow)->Width,
    												(*XWindow)->Height,
    												1,
    												(*XWindow)->black_pixel,
    												(*XWindow)->white_pixel);
    	XSelectInput((*XWindow)->display, (*XWindow)->window, ButtonPressMask);
    	(*XWindow)->wmDeleteMessage = XInternAtom((*XWindow)->display, "WM_DELETE_WINDOW", True);
    	if ((*XWindow)->wmDeleteMessage) XSetWMProtocols((*XWindow)->display, (*XWindow)->window, &(*XWindow)->wmDeleteMessage, 1);
    	XMapWindow((*XWindow)->display, (*XWindow)->window);
    

    Darstellungsschleife:

    while (APPLICATION_Get_Status(XWindow->Object->Application) < 3)
    	{
    		unsigned char* MonoChromImage = V4LCAMERA_Get_Image(XWindow->V4LCamera);
    		if (MonoChromImage != NULL)
    		{
    			//XClearWindow(XWindow->display, XWindow->window);
    			unsigned char* RGBImage = XWINDOW_Convert_MonoChrom2RGB(XWindow, MonoChromImage);
    			free(MonoChromImage);
    			XImage* xImage = XCreateImage(	XWindow->display,
    											XWindow->visual,
    											XWindow->nplanes,
    											ZPixmap,
    											0,
    											(char*)RGBImage,
    											XWindow->V4LCamera->fmt.fmt.pix.width,
    											XWindow->V4LCamera->fmt.fmt.pix.height,
    											8,
    											XWindow->V4LCamera->fmt.fmt.pix.bytesperline * 4);
    			if (xImage != NULL)
    			{
    				XPutImage(XWindow->display, XWindow->window, XWindow->gc, xImage, 0, 0, 0, 0, XWindow->V4LCamera->fmt.fmt.pix.width, XWindow->V4LCamera->fmt.fmt.pix.height);
    				XDestroyImage(xImage);
    			}
    			//free(RGBImage);
    			XSync(XWindow->display, 0);
    		}
    		//XFlush(XWindow->display);
    		if (XCheckIfEvent(XWindow->display, &XWindow->event, XWINDOW_PredictateXCheckIfEvent, (char*)XWindow))
    		{
    			printf("Passendes Event gefunden\n");
    			switch(XWindow->event.type)
    			{
    				case ButtonPress:
    					printf("Mouse button pressed!\n");
    					break;
    				case ClientMessage:
    					if (XWindow->event.xclient.data.l[0] == XWindow->wmDeleteMessage)APPLICATION_Set_Status(XWindow->Object->Application, APPLICATION_STATUS_PREPARECLOSE);
    					break;
    				default:
    					// nothing
    					break;
    			}
    		}
    		usleep(10000);
    	}
    

    Wenn ich das Bild als BMP speichere, hat es die richtige Größe. Es liegt also nicht an dem Format, welches mir die Kamera liefert, sondern rein an der Darstellung mit XLib.

    Weiterhin zum besseren Verständnis:
    Es handelt sich um eine 8 bit Monochrom-Kamera, welche zu einem SRGB-Bild konvertiert wird und anschließend mit XCreateImage und XPutImage dargestellt wird.

    Hoffe jemand kann mir hier helfen, wo der Fehler in der Darstellung liegt.

    MfG
    mirrowwinger



  • Push

    Leider habe ich noch keine Änderungsmöglichkeit gefunden.

    Vielen Dank
    mirrowwinger



  • Was hast du als BMP gespeichert?
    MonoChromImage, RGBImage oder xImage?

    Und wie sieht die Funktion XWINDOW_Convert_MonoChrom2RGB aus?



  • Also was ich von der Kamera bekomme ist natürlich monochrom 8bit. Dies speichere ich auch als BMP (einfach Header vor).

    Für die Darstellung wandle ich das ganze in das RGBA-Format (32bit) um, indem ich den Inhalt eines BildPunktes aus dem Monochrombild auf den R-, G- und B-Kanal des neuen Bildspeichers schreibe und den Transparentkanal setze ich überall auf 0. Somit entsteht ein Buffer für den gilt:
    - Width x Height x Depth x 4 (4Byte)
    Dies sollte eigentlich den Vorgaben entsprechen, was XLib als char-Array für XCreateImage erwartet.
    (Theoretisch)



  • Na dann schätze ich mal dass du falsch umrechnest.



  • Ok hier mal meine ganze Umrechnungsfunktion:

    unsigned char*	XWINDOW_Convert_MonoChrom2RGB(pClassXWindow XWindow, unsigned char* MonoChromImage)
    {
    	int x, y;
    	int position;
    	unsigned char PixelValue;
    	unsigned char* RGBImage = mem_malloc(sizeof(char) * (XWindow->V4LCamera->fmt.fmt.pix.width * XWindow->V4LCamera->fmt.fmt.pix.height * 4 + 1), XWINDOW, "failed to allocate memory for image buffer", 131);
    
    	position = 0;
    	for (y = 0; y < XWindow->V4LCamera->fmt.fmt.pix.width - 1; y++)
    	{
    		for (x = 0; x < XWindow->V4LCamera->fmt.fmt.pix.height - 1; x++)
    		{
    			PixelValue = MonoChromImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x];
    			RGBImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x] = PixelValue;
    			RGBImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x + 1] = PixelValue;
    			RGBImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x + 2] = PixelValue;
    			RGBImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x + 3] = 0;
    		}
    	}
            	RGBImage[XWindow->V4LCamera->fmt.fmt.pix.width * XWindow->V4LCamera->fmt.fmt.pix.height * 4] = '\0';
    	return RGBImage;
    }
    

    Ok kurze Erklärung der Variablen:
    XWindow - ist das Darstellungsfenster
    MonoChromImage - klar das 8bit Graubild
    x, y - Laufvariablen für Höhe und Breite
    PixelValue - der Wert für die Position [x, y] im Graubild
    RGBImage - RGBA-Image welches (klar) 4 mal so groß ist, wie das Graubild (+1 für Nullterminierung)

    Hoffe es ist wirklich nur ein kleiner Umrechnungsfehler in der Funktion. Leider sehe ich ihn nicht.

    mirrowwinger



  • Der Fehler war eingentlich einfach. Leider hat es mich eine ganze Weile beschäftigt diesen zu finden.

    Fehler liegt in meiner Konvertierung:

    unsigned char*  XWINDOW_Convert_MonoChrom2RGB(pClassXWindow XWindow, unsigned char* MonoChromImage)
    {
        int x, y;
        int position;
        unsigned char PixelValue;
        unsigned char* RGBImage = mem_malloc(sizeof(char) * (XWindow->V4LCamera->fmt.fmt.pix.width * XWindow->V4LCamera->fmt.fmt.pix.height * 4 + 1), XWINDOW, "failed to allocate memory for image buffer", 131);
    
        position = 0;
        for (y = 0; y < XWindow->V4LCamera->fmt.fmt.pix.width - 1; y++)
        {
            for (x = 0; x < XWindow->V4LCamera->fmt.fmt.pix.height - 1; x++)
            {
                PixelValue = MonoChromImage[y * XWindow->V4LCamera->fmt.fmt.pix.height + x];
                RGBImage[(y * XWindow->V4LCamera->fmt.fmt.pix.height + x) * 4] = PixelValue;
                RGBImage[(y * XWindow->V4LCamera->fmt.fmt.pix.height + x) * 4 + 1] = PixelValue;
                RGBImage[(y * XWindow->V4LCamera->fmt.fmt.pix.height + x) * 4 + 2] = PixelValue;
                RGBImage[(y * XWindow->V4LCamera->fmt.fmt.pix.height + x) * 4 + 3] = 0;
            }
        }
                RGBImage[XWindow->V4LCamera->fmt.fmt.pix.width * XWindow->V4LCamera->fmt.fmt.pix.height * 4] = '\0';
        return RGBImage;
    }
    

    Ich hatte zwar daran gedacht, dass ich RGBA setzen muss aber habe dann die 3 letzten Werte durch die Missachtung der neuen Indexierung immer wieder überschrieben.


Anmelden zum Antworten