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!
- 1775 megtekintés
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:
...
jpeg_stdio_src(&cinfo, infile);
...
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 hozzászóláshoz be kell jelentkezni
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. :)
- A hozzászóláshoz be kell jelentkezni
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? :-)
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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();
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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 :)
- A hozzászóláshoz be kell jelentkezni
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?
- A hozzászóláshoz be kell jelentkezni
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);
}
- A hozzászóláshoz be kell jelentkezni
csinald ugy, hogy a GdkPixbuf globalis valtozo legyen, ha ez nem okoz problemat
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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 [...]
- A hozzászóláshoz be kell jelentkezni
ÖÖÖ ezt most nem nagyon értem, egy kicsit bővebben esetleg... megköszönném.
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Köszi!
Sajnos a GTK-t magamtól próbálom elsajátítani, egy két irott segédlettel.
- A hozzászóláshoz be kell jelentkezni
Esetleg, ha C++ is jó, akkor ez Ultimate++-ban valahogy így néz ki:
Image image = StreamRaster::LoadStringAny(string_amiben_a_kep_van);
A jpeg plugin legyen hozzáadva a programodhoz és akkor automatikusan felismeri ezt a formátumot is.
- A hozzászóláshoz be kell jelentkezni