Newsgroup: it.comp.lang.visual-basic
Titolo: Creare una Picture da un array di byte

Ciao.
Dunque ho la necessità di 'spostare' un'immagine (un icona) passando
attraverso la sua rappresentazione come array di bytes.
Il problema è che, dato l'array, non riesco a ricostruirla.
Ho provato con l'esempio trovato qui:
http://groups.google.it/group/it.comp.lang.visual-basic/browse_frm/thread/6bf9ea76cfd8051e/65c6217e5fe379cd?lnk=gst&q=immagine+bytes&rnum=1&hl=it#65c6217e5fe379cd
ma non mi funziona (penso che per usarla occorra lavorare partendo dal
caricamento di un file).
Inoltre, non avendo un HICON valido (il mio array deriva dalla
serializzazione di un'icona di un item di una ListView), non credo di
poter usare la OleCreatePictureIndirect.
Idee?
Daniele.

 caricamento di un file).
Cerca nei post dei giorni scorsi, se ne è parlato più di una volta :)
Dev'essere una moda del momento convertire un array in un'immagine :)
Ciao 


Cosa hai usato per serializzare l'icona in un byte array?
Non è sufficiente eseguire il procedimento inverso?
Bye
Raf
-----------------------------------------------------
Funk: cooler than the other side of the pillow.


Chiedo scusa, ho visto che eri proprio tu con l'operazione inversa.
Domanda: come dice Rafunk, ti ha dato una soluzione A -> B, non puoi 
invertirla in B -> A?
Altrimenti non ne vedo altre che quella porcheria che avevo trovato io con 
Get/SetBitmapBits()
Ciao 

 Non è sufficiente eseguire il procedimento inverso?
Si, si...chiedo scusa...
Per serializzare licona ho usato la PropertyBag come suggerito da
Raf..
Il problema (che non ho specificato bene) è che la devo ricostruire in
un altro processo.
(La serializzo in una libreria e la ricostruisco nell'app.)
Quindi non posso usare la PB per ricrearla, non conoscendo il nome
assegnato alla proprietà...
..ho la senzazione che sto prendendo una cantonata....
tnx,
Daniele.

 ..ho la senzazione che sto prendendo una cantonata....
Eggià... ne sparo una prendendo il codice di Rafunk:
    ' Lettura
    Dim pb As PropertyBag
    Set pb = New PropertyBag
    pb.Contents = b ' l'array di byte con l'immagine
    pb.WriteProperty "MyImage", Nothing ' forzo l'esistenza di MyImage
    Set Picture1.Picture = pb.ReadProperty("MyImage") ' la rileggo
Ciao 

     Set Picture1.Picture = pb.ReadProperty("MyImage") ' la rileggo
Aspetta aspetta....ma facendo
pb.WriteProperty "MyImage", Nothing
Non vai di fatto ad azzerare il contenuto di pb.Contents?
Si vede che non me la cavo bene con le PropertyBag?
Tnx,
Daniele.


Fabio mi ha già citato (e gli chiederò i diritti per questo ;-)), ma a questo
punto non capisco perché i due processi (processi?) non possano scambiarsi,
oltre al byte array, anche il nome della proprietà (del tutto arbitrario, tra
l'altro) utilizzato nell'oggetto PB...


 Si vede che non me la cavo bene con le PropertyBag?
Non direi, anzi!


 per far sì che esista l'elemento nella propertybag.
Sicuro?
primo, il Nothing è indicato solo come valore di default, ma se serve basta 
fare un
pb.WriteProperty "MyImage", b
secondo, il problema è che il PropertyBag di Barzo è solo in lettura in quel 
processo e quindi giustamente la proprietà MyImage non esiste.
Come faccio io rendo semblicemente l'array associabile alla picture.
Ciao 

 l'altro) utilizzato nell'oggetto PB...
Si si...ma ci sono anche molte altre strade!
Perchè invece di esporre il byte array non esponi direttamente
l'oggetto Picture!? :-)
Il fatto è che ho un UDT con un campo ResData() As Byte che
rappresenta un BLOB in un database, questo BLOB può essere un immagine
o un suono e quindi volevo astrarre l'oggetto in sé e passarlo
all'esterno come un array di Byte.
Nulla mi vieta di mettere due campi: un ResSound() as Byte e un
ResImage As StdPicture!
Era solo perchè io mi voglio sempre complicare le cose!
Tnx!
Daniele.

 Come faccio io rendo semblicemente l'array associabile alla picture.
Giuro che stavolta non ti ho capito...
-- 


 Daniele.


 ??? Perché mai dovrebbe essere readonly? C'č qualcosa che mi sfugge?
Non ci capiamo.
Barzo dice che la PropertyBag che deve leggere sta in un altro processo.
Che poi sia vero o no non l'ho capito, ma se sta in un altro processo non 
puň leggere MyImage semplicemente perchč non c'č.
Verifica:
- apri un nuovo progetto
- aggiungi il codice
    Dim pb As PropertyBag
    Set pb = New PropertyBag
    Set Picture1.Picture = pb.ReadProperty("MyImage")
Esegui e otterrai l'errore.
Se Barzo invece si č spiegato male a livello di processi e di array passati 
da un processo all'altro come dice nell'altro post non so.
Voi dite che funziona... fatemi vedere il codice incriminato :)
Ciao 

 Ciao
Ok, ora è più chiaro.
A parte il lapsus di Barzo (non sono 2 processi ma un EXE e una DLL, a quanto ho
capito), lui non passa direttamente la PB ma il byte array ottenuto
"serializzando" una picture tramite un oggetto PB.
Secondo me, se Barzo ha seguito le mie e tue indicazioni, il codice dovrebbe
essere pressapoco questo:
-- EXE --
Sub ProcessPicture(ThePicture As StdPicture)
Dim pb As New PropertyBag
Dim b() As Byte
Dim oMyClass As New MyDLL.MyClass
    pb.WriteProperty "Serialized", ThePicture
    b = pb.Contents
    oMyClass.PassMeThatFuckingPicture b
End Sub
-- DLL --
Private MyFuckingPicture As StdPicture
Public Sub PassMeThatFuckingPicture(b() As Byte)
Dim pb As New PropertyBag
    pb.Contents = b
    Me.MyFuckingPicture = pb.ReadProperty "Serialized"
End Sub
Adesso sembra anche a te più chiaro?


 Adesso sembra anche a te più chiaro?
Ah, ecco!
Una dll è *IN*process, quindi tutto giusto, la proprietà ci resta e la leggi 
come vuoi.
Però a questo punto non ho capito perchè Barzo al primo post dice che non 
può usare il nome della proprietà perchè non esiste nell'altro processo... 
non ha provato! :)
Ciao 

 non ha provato! :)
Calma, calma.. :-)
Come ho già detto nell'altro post (delle 8.49), ho avuto palesemente
un lapsus dicendo 'processi' e non spiegandomi bene...chiedo venia!
Mi sa che tutto nasce dal fatto che io _NON_ so usare bene le PB!
Il mio intento era quello di ricostruire (nell'EXE) un immagine da uno
stream di byte ricevuto dalla DLL.
Ora, per usare la PB nell'exe dovrei conoscere il _NOME_ dato alla
proprietà nella DLL.
Ma ovviamente a quel livello non lo conosco (a meno che non lo passo
fuori assieme all'array).
Non so se mi sono spiegato.
Ehehe...ormai è diventata quasi una questione di principio!
(Si vede che in sto periodo non ho un piffero da fare!)
Tnx.
Daniele.


Ok, ma visto che la PB è un oggetto solo di appoggio, che serve esclusivamente
per serializzare, la proprietà utilizzata a tale scopo non potrebbe avere un
nome FISSO, noto ad EXE e a DLL, deciso da te una volta per tutte?
Bye


 nome FISSO, noto ad EXE e a DLL, deciso da te una volta per tutte?
Certo...come ho già detto di soluzioni ce ne sono infinite.
A me piace sempre cercare di trovare quella + elegante (nel limite del
possibile).
Cmq, non capisco perchè non mi funge la PictureFromBits che aveva
postato Hal nel lontano 2004!
Va bè!
Anzi, visto che ci sono apro un piccolo OT..
Mi sono sempre chiesto la modalità di funzionamento dell PB (e delle
SetProp, GetProp)...voi sapete come e dove vengono memorizzati i
dati?!
Tnx.
Daniele.


Per l'oggetto PropertyBag credo che i dati stiano in un buffer binario, su come
siano strutturati, ti confesso che lo ignoro (e non mi sono mai posto il
problema).
Per SetProp e GetProp immagino ti riferisca alle API che permettono di
aggiungere delle informazioni custom associate ad un handle di finestra, giusto?


 aggiungere delle informazioni custom associate ad un handle di finestra, giusto?
Si, bè in effetti per queste la risposta è facile visto che non sono
permanenti.
Bye,
Daniele.

 End Sub
Dunque...diciamo che ho 'quasi' fatto così...
Però ora mi è sorto un nuovo problema: l'immagine recuperata dalla PB
è 'distorta'...
...cioè sembra essere a 16 colori e con lo sfondo tutto nero!
Avete vaga idea del perchè?
PS. L'immagine (icona a 256 colori) è in una DLL (standard) di
risorse, ma sono sicuro che viene caricata bene.
Tnx,
Daniele.

 risorse, ma sono sicuro che viene caricata bene.
Prova a postare il codice intero grazie al quale l'icona dal file di risorse si
trasforma in un byte array.
Bye


 trasforma in un byte array.
------------------------------------- DLL
-------------------------------------
Public Type TResItem
  ResName   As String
  ResSize     As EIconSize
  ResType     As EResType
  ResSource As ERESSource
  ResData()   As Byte
End Type
-------------------------------------
Dim pb As New PropertyBag
Dim RsObj As TResItem
pb.WriteProperty LVRes.SelectedItem.Key, Resources.Image(0,
LVRes.SelectedItem.Key)
ResObj.ResData = pb.Contents
-------------------------------------
La property Resources.Image() ritorna una StdPicture:
Public Property Get Image(Index As EImages, Optional ImgKey As String)
As StdPicture
  'Images è una Collection (vengono usati Indice e chiave separati per
sfruttare l'intellisense)
  If Index <= 0 Then
      Set Image = Images(ImgKey)
  Else
      Set Image = Images(ImageKeys(Index).ImageKey)
  End If
End Property
------------------------------------- EXE
-------------------------------------
  Dim pb As PropertyBag
  Dim mIcon As TResItem
  Set pb = New PropertyBag
  mIcon = ResObj.ShowResourceForm(RF_ICONS, DBService, IconSize,
RESOURCE_LIB, Me)
  If mIcon.ResName = vbNullString Then Exit Sub
  pb.Contents = mIcon.ResData
  Set oImage.Picture = pb.ReadProperty(mIcon.ResName)
-----------------------------------------------------------------------------------
Zio bello...sono sicuro che l'immagine viene caricata correttamente
perchè se la passo 'direttamente' viene visualizzata correttamente!
Tnx,
Daniele.

 Daniele.
Potrebbe essere proprio un problema nel passaggio tramite PB.
Cosa succede se fai:
pb.WriteProperty "pippo", LoadResPicture(...)
...
Set Picture1.Picture = pb.ReadProperty("pippo")
?
Al limite salva il byte array pb.Contents su file .bin e spediscimelo, così
provo a guardarci.
-- 


 provo a guardarci.
Adesso vedo di prepararlo.
Bye,
Daniele.

 poi recuperandola, viene "ricostruita male"!
Sai che mi è venuto un dubbio!
Allora, il file icona inserito nella DLL è 1.406 byte, mentre il
contenuto di pb.Contents (e di conseguenza il file binario che ne
viene fuori) è di 524 byte!!!
Non mi spiego però perchè se anzichè passare lo stream passo l'oggetto
Picture diretto, viene visualizzato bene!
Qui mi sto perdendo un po...
Bye,
Daniele.


Secondo me in un passaggio l'icona viene trasformata a 16 colori...
Riesci a provare con una BMP anziché una ICO?


 Qui mi sto perdendo un po...
cosě a occhio direi che viene passato solo l'immagine "mask" dell'icona, per 
questo vedi nero anzichč trasparente.
puoi provare come trucchetto a caricare il res in una picture e poi buttare 
la picture nel pb.
Ciao 

 Riesci a provare con una BMP anziché una ICO?
Mi sa da'vero!
Ho anche delle BMP nella DLL...e quelle sembra che le carichi bene!
A sto punto....mi arrendo! :-(
Bye,
Daniele.

 la picture nel pb.
Mi sa dav'ero anche questo! :-(
Caricando l'immagine prima in una Picture e poi serializzando la
Picture1.Picture, il risultato non cambia!
Bye,
Daniele.

 Picture1.Picture, il risultato non cambia!
Ma se prima hai detto che arrivando da una StdPicture funziona?
Ciao


Io comunque non ho capito ancora come carichi le icone dal file di risorse e
tutti i passaggi per arrivare al byte array...
Per caso, non è che le carichi dal file RES in una imagelist e poi da queste le
trasferisci in qualche altra variabile?


 trasferisci in qualche altra variabile?
Allora, siccome si dice che un esempio vale più di mille parole, ho
preparato un test esplicativo!
http://digilander.libero.it/DBarzo/misc/ProvaImmagini.zip
Se avete voglia dateci un occhio.
Bye,
Daniele.

 Se avete voglia dateci un occhio.
Ok, a parte il navigare nel tuo codice che per caricare un'icona ha 80 
funzioni complesse... :)
Io le ho provate in tutti i modi.
res incluse nel progetto vb, caricamento via VB, via API, icona inclusa come 
nella dll come anonima risorsa personalizzata...
Non c'è verso, VB converte l'icona in un 16 colori.
Però alla fine mi è venuto un bel dubbio: ma perchè cavolo nella tua classe 
CPicture non ci pianti un form nascosto che contenga l'imagelist con le 
icone e la tua property Pic non restituisce un banale 
ImageList1.Images(nomeIcona), buttando via tutta 'sta storia di PropertyBag, 
serializzazione degli array di byte, funzioni allucinogene per le risorse...
Vuoi mantenere le risorse?
Prova a fare la tua LoadImage e farla passare dalle ImageList (non ho 
provato) e vedi se questo evita il problema, ma non credo.
P.S.: per la cronaca, con la LoadResource e dietro a una CopyMemory sono 
riuscito a beccare l'array di byte che definiscono il file (nota: il *file*, 
non l'immagine) se è stato messo nella dll di risorse come risorsa 
personalizzata (id "#101", tipo "CUSTOM"), qui vedi se nella tua pazzia puoi 
pigliare 'sto array, salvarlo temporaneamente come file .ico e fare una 
LoadPicture del file. :)
Ciao 

 serializzazione degli array di byte, funzioni allucinogene per le risorse...
Si si...lo so, ma quando mi scappano fuori ste cose "strane" mi piace
scoprire se sono io che sbaglio o se la strada che ho preso è un
vicolo cieco! (Anche se a volte vado un po' troppo oltre)
Adesso che ho capito che è meglio evitare 'ste robe.....le evito!
Tnx!
Daniele.