Differenze tra le versioni di "Mostrare una immagine JPEG in una finestra con le funzioni del API di X11 e di Libjpeg"
(Creata pagina con 'Per mostrare una immagine JPEG in una finestra creata con le risorse della libreria del server grafico ''X11'', sarà necessario decodificare il file immagine. <BR>Per effettu...') |
|||
Riga 250: | Riga 250: | ||
Shell "gcc -o /tmp/libadhoc_jpeg.so /tmp/libadhoc_jpeg.c -shared -fPIC -lX11 -ljpeg" Wait | Shell "gcc -o /tmp/libadhoc_jpeg.so /tmp/libadhoc_jpeg.c -shared -fPIC -lX11 -ljpeg" Wait | ||
− | p = Decodifica_jpeg("/ | + | p = Decodifica_jpeg("''/percorso/del/file/immagine.jpg''", VarPtr(iW), VarPtr(iH)) |
disp = XOpenDisplay(0) | disp = XOpenDisplay(0) |
Versione delle 16:35, 4 nov 2014
Per mostrare una immagine JPEG in una finestra creata con le risorse della libreria del server grafico X11, sarà necessario decodificare il file immagine.
Per effettuare tale decodifica ci serviremo delle risorse esterne della libreria Libjpepg.
Per maggiore sicurezza la maggior parte della procedura di decodifica sarà effettuata utilizzando istruzioni di codice in linguaggio C poste all'interno di una libreria condivisa .so, da noi realizzata, che sarà chiamata dal programma principale scritto in Gambas.
Per poter utilizzare le risorse esterne del API di X11 sarà necessario richiamare la libreria (nella sua attuale versione): "libX11.so.6.3.0" .
Pertanto, il codice C contenuto dalla libreria condivisa .so, da noi appositamente realizzata e che porremo nella cartella Dati dell'applicazione principale Gambas, sarà il seguente:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <X11/Xlib.h> #include <X11/keysym.h> #include <jpeglib.h> #include <jerror.h> #ifndef u_char #define u_char unsigned char #endif ' /*Ritorna un vettore per un'immagine a 24 bit.*/ u_char *Decodifica_jpeg (char *nomefile, int *widthP, int *heightP) { register JSAMPARRAY buffer; //--> occupa 8 byte struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr err_mgr; int bytePerPixel, x, y; FILE *fl; u_char *BufferRitorno; fl = fopen (nomefile, "rb"); if (NULL == fl) { perror (NULL); return NULL; } cinfo.err = jpeg_std_error (&err_mgr); jpeg_create_decompress (&cinfo); jpeg_stdio_src (&cinfo, fl); jpeg_read_header (&cinfo, 1); cinfo.do_fancy_upsampling = 0; cinfo.do_block_smoothing = 0; jpeg_start_decompress (&cinfo); *widthP = cinfo.output_width; *heightP = cinfo.output_height; bytePerPixel = cinfo.output_components; buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, (*widthP * bytePerPixel), 1); BufferRitorno = malloc (3 * (*widthP * *heightP)); if (NULL == BufferRitorno) { perror (NULL); return NULL; } if (3 == bytePerPixel) { int scorrLinea = (*widthP * 3); for (y = 0; y < cinfo.output_height; ++y) { jpeg_read_scanlines (&cinfo, buffer, 1); for (x = 0; x < scorrLinea; ++x) { BufferRitorno[(scorrLinea * y) + x] = buffer[0][x]; ++x; BufferRitorno[(scorrLinea * y) + x] = buffer[0][x]; ++x; BufferRitorno[(scorrLinea * y) + x] = buffer[0][x]; } } } else if (1 == bytePerPixel) { unsigned int col; int scorrLinea = (*widthP * 3); int indiceBuff; for (y = 0; y < cinfo.output_height; ++y) { jpeg_read_scanlines (&cinfo, buffer, 1); indiceBuff = 0; for (x = 0; x < scorrLinea; ++x) { col = buffer[0][indiceBuff]; BufferRitorno[(scorrLinea * y) + x] = col; ++x; BufferRitorno[(scorrLinea * y) + x] = col; ++x; BufferRitorno[(scorrLinea * y) + x] = col; ++indiceBuff; } } } else { fprintf (stderr, "Errore: il numero dei canali del colore è %d. Questa applicazione può gestire soltanto 1 o 3\n", bytePerPixel); return NULL; } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); fclose (fl); return BufferRitorno; }
Il codice Gambas potrà essere il seguente:
Public Struct XEventStruct type As Integer serial As Long send_event As Boolean display As Pointer windowL As Long root As Long subwindow As Long timeL As Long x As Integer y As Integer x_root As Integer y_root As Integer state As Integer keycode As Integer same_screen As Boolean End Struct Public Struct Visual XExtData As Pointer visualid As Integer classe As Long red_mask As Long green_mask As Long blue_mask As Long map_entries As Integer End Struct Private Const ExposureMask As Integer = 32768 Private Const KeyPressMask As Byte = 1 Private Const ButtonPressMask As Byte = 4 Private Enum KeyPress = 2, KeyRelease, ButtonPress, ButtonRelease, MotionNotify, EnterNotify, LeaveNotify, FocusIn, FocusOut, KeymapNotify, Expose, GraphicsExpose, NoExpose Private disp As Pointer Library "libX11:6.3.0" Private Const ZPixmap As Integer = 2 ' Display *XOpenDisplay(disp) ' Opens a connection to the X server that controls a display. Private Extern XOpenDisplay(displayP As Pointer) As Pointer ' XCloseDisplay(display) ' Closes the connection to the X server for the display specified in the Display structure and destroys all windows. Private Extern XCloseDisplay(displayP As Pointer) ' int XDefaultScreen (display) ' returns the default screen number referenced by the XOpenDisplay function. Private Extern XDefaultScreen(displayP As Pointer) As Integer ' unsigned long XWhitePixel (display, screen_number) ' returns the white pixel value for the specified screen. Private Extern XWhitePixel(displayP As Pointer, screen_number As Integer) As Long ' unsigned long XBlackPixel (display, screen_number) ' returns the black pixel value for the specified screen. Private Extern XBlackPixel(displayP As Pointer, screen_number As Integer) As Long ' Window XDefaultRootWindow(display) ' Return the root window for the default screen. Private Extern XDefaultRootWindow(displayP As Pointer) As Integer ' Window XCreateSimpleWindow(display, parent, x, y, width, height, border_width, border, background) ' Creates an unmapped InputOutput subwindow for a specified parent window, returns the window ID of the created window. Private Extern XCreateSimpleWindow(displayP As Pointer, parent As Integer, x As Integer, y As Integer, width As Integer, height As Integer, border_width As Integer, border As Integer, background As Integer) As Integer ' XSetStandardProperties (display, w, window_name, icon_name, icon_pixmap, argv, argc, hints) ' Specifies a minimum set of properties describing the simplest application. Private Extern XSetStandardProperties(displayP As Pointer, w As Integer, window_name As String, icon_name As String, icon_pixmap As Integer, argv As String, argc As Integer, hints As Pointer) ' XSelectInput (display, w, event_mask) ' Requests that the X server report the events associated with the specified Event mask. Private Extern XSelectInput(displayP As Pointer, w As Integer, event_mask As Long) ' GC XCreateGC(display, d, valuemask, values) ' Creates a graphics context and returns a GC. Private Extern XCreateGC(displayP As Pointer, w As Integer, valuemask As Long, values As Pointer) As Pointer ' XClearWindow(display, w) ' Clears the entire area in the specified window. Private Extern XClearWindow(displayP As Pointer, w As Integer) ' XMapRaised (display, w) ' Raises the specified window to the top of the stack. Private Extern XMapRaised(displayP As Pointer, w As Integer) ' XNextEvent (display, event_return) ' Gets the next event and remove it from the queue. Private Extern XNextEvent(displayP As Pointer, event_return As XEventStruct) ' XFreeGC(display, gc) ' Destroys the specified GC as well as all the associated storage. Private Extern XFreeGC(displayP As Pointer, gcP As Pointer) ' XDestroyWindow(display, w) ' Destroys the specified window as well as all of its subwindows. Private Extern XDestroyWindow(displayP As Pointer, w As Integer) ' XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height) ' Combines an image with a rectangle of the specified drawable. Private Extern XPutImage(displayP As Pointer, w As Integer, gcP As Pointer, image As Pointer, src_x As Integer, src_y As Integer, dest_x As Integer, dest_y As Integer, width As Integer, height As Integer) ' int DefaultDepth(display, screen_number) ' Returns the depth (number of planes) of the default root window for the specified screen. Private Extern XDefaultDepth(displayP As Pointer, screen_number As Integer) As Integer ' Visual *XDefaultVisual(display, screen_number) ' Returns the default visual type for the specified screen. Private Extern XDefaultVisual(displayP As Pointer, screen_number As Integer) As Visual ' XImage *XCreateImage(display, visual, depth, format, offset, data, width, height, bitmap_pad, bytes_per_line) ' Allocates the memory needed for an XImage structure for the specified display but does not allocate space for the image itself. Private Extern XCreateImage(displayP As Pointer, visu As Visual, depth As Integer, formatI As Integer, offset As Integer, data As Integer[], width As Integer, height As Integer, bitmap_pad As Integer, bytes_per_line As Integer) As Pointer ' Status XInitImage(image) ' Initializes the internal image manipulation routines of an image structure, based on the values of the various structure members. Private Extern XInitImage(image As Pointer) Private Extern exitus(status As Integer) In "libc:6" Exec "exit" Private Extern Decodifica_jpeg(FileImmagine As String, wP As Pointer, hP As Pointer) As Pointer In Lib "/tmp/libadhoc_jpeg" Public Sub Main() Dim screen, id, prof, iW, iH As Integer Dim pxW, pxB As Long Dim ev As New XEventStruct Dim gc, p, img As Pointer Dim ImmBuffer As Integer[] If Exist("/tmp/libadhoc_jpeg.c") = False Then Copy "libadhoc_jpeg.c" To "/tmp/libadhoc_jpeg.c" Shell "gcc -o /tmp/libadhoc_jpeg.so /tmp/libadhoc_jpeg.c -shared -fPIC -lX11 -ljpeg" Wait p = Decodifica_jpeg("/percorso/del/file/immagine.jpg", VarPtr(iW), VarPtr(iH)) disp = XOpenDisplay(0) If IsNull(disp) Then Error.Raise("Impossibile aprire il display !") screen = XDefaultScreen(disp) prof = XDefaultDepth(disp, screen) ImmBuffer = Crea_Dati_immagine(screen, prof, p, iW, iH) img = XCreateImage(disp, Null, prof, ZPixmap, 0, ImmBuffer, iW, iH, 32, 0) If IsNull(img) Then Error.Raise("Errore !") pxW = XWhitePixel(disp, screen) pxB = XBlackPixel(disp, screen) id = XCreateSimpleWindow(disp, XDefaultRootWindow(disp), 0, 0, iW, iH, 5, pxW, &FF0000) Print "ID della finestra creata: "; Hex(id, 6) XSetStandardProperties(disp, id, "Prova creazione finestra", "Nome icona finestra", 0, Null, 0, Null) XSelectInput(disp, id, ExposureMask Or KeyPressMask Or ButtonPressMask) gc = XCreateGC(disp, id, 0, Null) If IsNull(gc) Then Error.Raise("Impossibile creare un nuovo contesto grafico !") XMapRaised(disp, id) While True XNextEvent(disp, ev) Select Case ev.type Case Expose redraw(id) XInitImage(img) XPutImage(disp, id, gc, img, 0, 0, 0, 0, iW, IH) Case Else Exit End Select Wend chiude_X(id, gc) End Private Procedure redraw(idR As Integer) ' Pulisce la superficie della finestra da ogni elemento presente: XClearWindow(disp, idR) End Public Sub chiude_X(idCh As Integer, gcont As Pointer) XFreeGC(disp, gcont) ' Chiude la finestra: XDestroyWindow(disp, idCh) XCloseDisplay(disp) exitus(0) End Private Function Crea_Dati_immagine(screen As Integer, profond As Integer, buf As Pointer, width As Integer, height As Integer) As Integer[] Dim r, g, b, scorr As Integer Dim vis As New Visual Dim rRatio, gRatio, bRatio As Float Dim vettI As Integer[] Dim st As Stream Dim buffer As Byte vis = XDefaultVisual(disp, screen) rRatio = CFloat(vis.red_mask) / 255.0 gRatio = CFloat(vis.green_mask) / 255.0 bRatio = CFloat(vis.blue_mask) / 255.0 st = Memory buf For Read If profond >= 24 Then vettI = New Integer[](width * height) Do Read #st, buffer r = CInt(buffer * rRatio) Read #st, buffer g = CInt(buffer * gRatio) Read #st, buffer b = CInt(buffer * bRatio) r = r And vis.red_mask g = g And vis.green_mask b = b And vis.blue_mask vettI[scorr] = r Or g Or b Inc scorr Loop Until scorr >= vettI.Max Else Error.Raise("Questa applicazione non supporta una profondità inferiore a 24 !") Endif st.Close Return vettI End