JPEG adatból RGB adat

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:


...
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 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. :)

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();

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.

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);

}

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

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.