Fórumok
A következő probléma áll elöttem: JPEG adatból kellene RGB adatra konvertálnom.
JPEG adat az letöltéskor keletkezik, de nem akarom fájlba kiirni (ki lehet irni, jó az adat), most pillanatnyilag egy string tárolja.
Ezt az adathalmazt kellene átkonvertálnom RGB-re, hogy meg tudjam jeleníteni mindenféle fájlművelet nélkül.
A megjelenítésre elvileg a gdk_pixbuf_new_from_data() függvény (vagy valami hasonló) jó is lenne, csakhogy RGB-ben kéri be a képet.
Valaki foglalkozott már e ilyesmivel? Valami tippek? Minden infót szivesen várok!
Hozzászólások
gtk-ban nem vagyok otthon, lehet, hogy van közvetlen megoldás a problémádra.
Ha nincs akkor mondok rögtön kettőt:
a) Közvetlen libjpeg-et használsz. (http://www.ijg.org/)
Ha megnézed a leírását, akkor a forrást így kell beállítani:
Ez persze neked megint nem jó, de ha megnézed a jpeg_stdio_src forrássát, és a jpeg_source_mgr struct-ot, akkor kis okoskodással képes lehetsz írni memóriából működő "source manager"-t.
b) Használj FIFO-t...
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
A fájműveleteket nem csak azért akarom számüzni, mert kerregtetné a vinyót (ha rendes file), időt is szeretnék nyerni. És szerintem értelmetlen beleirni valamibe, egy bonyolult eljárással, majd kiolvasni ezt egy másik eljárással, egyszerübb lenne a címet átadni és kész.
Valamit már találtam igy a problémára. Ami azt csinálta hogy a jpeg_stdio_src-t lecserélte valami memóriás függvényre. Csak mág tesztelni nem tudtam, még legalább 2 órán át nem is fogom tudni, mert megyek fizikaórára. :(
Amint megjöttem ránézek a dologra.
Infó addig is jöhet! Majd feldolgozom. :)
Csinálj egy memória fájlrendszert és akkor nem kerreg.
Nem értem mi a bonyolult egy fájlba írásban.
Persze lehet, hogy a jpeg libbel könnyebben célhoz érsz, csak kötekedtem.
Ja, és a szokásos kérdésem: mire kell pontosan? :-)
Már próbáltam annó ramdiskkel csak rengeteg temp fájlom lenne. És sok időt venne el a fájlbizgerélés.
Olyaannyira titkos, ha elmondanám, megkellene hogy ölljelek :) Kameraképeket kell megjelenítenem.
Nézd meg a JasPer Jpeg modulját. Ő használja az előttem említett IJG libjpeg-jét, viszont a JasPer-ban van olyan, hogy a memóriában lévő JPEG struktúrát tudod feldolgozni (pl. RGB-be szétdobni).
http://www.ijg.org/
http://www.ece.uvic.ca/~mdadams/jasper/
vagy
# apt-get install libjpeg-dev libjasper-dev
Keresd meg azt a procedúrát, amivel meg tudod csinálni a jasper stream-et a memóriában lévő JPEG blokkról, aztán:
(Ezt én így használom. A betöltési rész nyilván nem kell bele, csak valahogy stream-et kellene átadnod.)
-----------------------------------------------
#include "jasper/jasper.h"
...
...
// JasPer library inicializálása
jas_init();
jas_stream_t *stream;
jas_image_t *image;
jas_matrix_t *data;
// fájl betöltése és formátum dekódolás
stream = jas_stream_fopen(file_name, "rb");
if (stream == NULL) return 0;
// bitmap formátum letárolása
bitmap_format = jas_image_getfmt(stream);
image = jas_image_decode(stream, -1, NULL);
jas_stream_close(stream);
if (image == NULL) return 0;
bitmap_width = jas_image_width(image);
bitmap_height = jas_image_height(image);
bitmap_clrspc = jas_image_clrspc(image);
// fájl vizsgálata, hogy RGB formátumú és 8 bites-e??
int clr_spc;
clr_spc = jas_clrspc_fam(bitmap_clrspc);
if ((clr_spc != JAS_CLRSPC_FAM_RGB) && (clr_spc != JAS_CLRSPC_FAM_GRAY)) return 0;
if (jas_image_cmptprec(image, 0) != 8) return 0;
// debug
//int raws = jas_image_rawsize(image);
//printf("width = %d\n", (int)bitmap_width);
//printf("height = %d\n", (int)bitmap_height);
// JasPer mátrix létrehozása
int dx,dy;
dx = bitmap_width;
dy = bitmap_height;
data=jas_matrix_create(dy,dx);
//memória lefoglalása
bitmap_buffer = (char*) malloc(bitmap_width * bitmap_height * 3);
if (bitmap_buffer == 0) return 0;
// adat kiolvasása az JasPer objektumból és átmásolása a memória blokkba
int i, j;
int channel;
// csatornák számának megállípítása => GRAY=1 és RGB=3
int num_of_channels;
num_of_channels = 1;
if (clr_spc == JAS_CLRSPC_FAM_GRAY) { num_of_channels = 1; }
if (clr_spc == JAS_CLRSPC_FAM_RGB) { num_of_channels = 3; }
// RGB szín-adatok kimásolása a bitmap memória részre
for(channel=0; channel
jas_image_readcmpt(image, channel, 0, 0, dx, dy, data);
jas_image_setcmpttype(image, channel, JAS_IMAGE_CT_RGB_R+channel);
for(j=0; j
for(i=0; i
int idx=(j * dx + i) * 3;
if (num_of_channels == 1){
bitmap_buffer[idx+0] = jas_matrix_get(data, j, i);
bitmap_buffer[idx+1] = jas_matrix_get(data, j, i);
bitmap_buffer[idx+2] = jas_matrix_get(data, j, i); }
else{
bitmap_buffer[idx+channel] = jas_matrix_get(data, j, i); }
}
}
}
// lefoglalt objektumok felszabadítása
jas_image_destroy(image);
jas_matrix_destroy(data);
jas_image_clearfmts();
//jas_cleanup();
gdk_pixbuf_loader_new-nak beadhatsz szinte barmilyen ismertebb formatumot majd a gdk_pixbuf_loader_get_pixbuf mehet a gdk_pixbuf_new_from_data()-nak
itt a link is: http://www.gtk.org/api/2.6/gdk-pixbuf/GdkPixbufLoader.html
Nálam ez volt a nyerő megoldás. Ezzel sikerül teljes mértékig kizárni a temp-fájlos dolgot. Ja és működött is. Kis keresgélés azért még kellett hozzá. :)
Mostmár csak annyi a gondom hogy minden képfrissítéskor eszi a memóriát a program. Olyan mintha mindig nyitna megának egy új helyet a memóriában, de a régit is lefoglalva tartja.
Kb olyan 5-10 Mb-ot eszik mp-ként.
Ha nem rajzoltatom vele a képet csak pl. letöltöm a string-be a képet és annak kiirom mondjuk a hosszát, akkor nem eszi a memóriát, szóval mindenképp a képfrissítés részére gyanakodok.
Próbáltam a függvényben található változókat kiirtani, ez olyan jól sikerült hogy egy óriási memória hibát rak elém. :)
delete függvénnyel próbáltam.
Szerintem este van és azért nem megy :)
C-ről beszélünk? Lehet hogy hülyeséget mondok, de mi lenne ha nem String-be tennéd az adatot, hanem malloc-kal memóriát foglalnál le, elvégeznéd a műveleteket, aztán meg felszabadítanád?
String-be a jpeg fájlt olvasom be, na ezt nem tudom hogy mekkora lesz, mivel erősen függ attól is hogy mi van benne, mennyire tömöríthető, nehéz lenne lefoglalni neki egy bizonyos méretü memóriát. Amúgy nincs gond szerintem a string-es résszel mivel ha irok egy olyan progit ami letölti és kiirja a string hosszát és ez lefut kb. 0,5mp-ként akkor nem eszi a progi a memóriát.
Ellenben ha egy akármilyen jpeg fájlt (a gépen van rendes fájlként) betöltök, pl 0,5mp-ként akkor eszi a memóriát rendesen.
Itt van az ami nem megy, vagyis eszi a memóriát:
GtkWidget * image1 = NULL;
void viewer_read_image_from_file(gchar *filename) {
GdkPixbuf *image;
image = NULL;
/* Load the image and render it. */
image = gdk_pixbuf_new_from_file(filename,NULL);
gtk_image_set_from_pixbuf (GTK_IMAGE(image1), image);
}
csinald ugy, hogy a GdkPixbuf globalis valtozo legyen, ha ez nem okoz problemat
Kipróbáltam, sajnos nem segitett.
Még egy olyanra gondoltam hogy nem függvényként irom meg hanem osztály + függvényként (szóval használjuk a c++-t), mivel úgyis egy halom ilyet kellesz futtatnom párhuzamosan.
dereferenciázd az image pointert az utolsó sorban! Ez nem Java és nem is .NET.
Idézet a doksiból:
gdk_pixbuf_new_from_file ()
[...]
Returns : A newly-created pixbuf with a reference count of 1, or NULL if any of several error conditions occurred [...]
ÖÖÖ ezt most nem nagyon értem, egy kicsit bővebben esetleg... megköszönném.
Erősen ajánlom, hogy nézz utána a gtk memóriakezelésének.
gdk_pixbuf_new_from_file:
"A newly-created pixbuf with a reference count of 1"
gtk_image_set_from_pixbuf:
"Creates a new GtkImage displaying pixbuf. The GtkImage does not assume a reference to the pixbuf; you still need to unref it if you own references. GtkImage will add its own reference rather than adopting yours."
Körübelül felvázolom mi is történik:
Tehát, mikor létrehozod a pixbuf-t, akkor a ref számláló értéke 1.
Mikor berakod a GtkImage-be, akkor már 2.
Mikor kicseréled a GtkImage-ben, akkor lecsökken 1-re, azaz nem szűnik meg, a memóriában marad.
Tehát neked le kell csökkenteni, ott ahol zsolt mondta.
"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o
Az utolsó sorba írd ezt:
gdk_pixbuf_unref(image);
Amúgy minden referencia-számolt pointerrel referencia csökkentést kell csinálnod, ha már nem használod, különben tele lesz a progi leak-kel. Ez alap dolog GTK-ban.
Köszi!
Sajnos a GTK-t magamtól próbálom elsajátítani, egy két irott segédlettel.
Esetleg, ha C++ is jó, akkor ez Ultimate++-ban valahogy így néz ki:
A jpeg plugin legyen hozzáadva a programodhoz és akkor automatikusan felismeri ezt a formátumot is.