Sign in to follow this  
cambalinho

c++ - GDIPLUS::Image: how save an Image object on stream way?

Recommended Posts

cambalinho    230

i have:

Image *img;

how can i save the img in stream way for overloading the ostream << operator?

 i have these code, but don't works :(

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes

   ImageCodecInfo* pImageCodecInfo = NULL;

   GetImageEncodersSize(&num, &size);
   if(size == 0)
      return -1;  // Failure

   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL)
      return -1;  // Failure

   GetImageEncoders(num, size, pImageCodecInfo);

   for(UINT j = 0; j < num; ++j)
   {
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
      {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }
   }

   free(pImageCodecInfo);
   return -1;  // Failure
}
////////////////////////////




IStorage* pIStorage = NULL;
            IStream* pIStream1 = NULL;
            HRESULT hr;
            Status stat = Ok;
            hr = CoInitialize(NULL);

            hr = StgCreateDocfile( L"CompoundFile.cmp", STGM_READWRITE|STGM_CREATE|STGM_SHARE_EXCLUSIVE,0, &pIStorage);

            CLSID jpgClsid;
            GetEncoderClsid(L"image/gif", &jpgClsid);
            pIStorage->CreateStream(L"StreamImage1", STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, 0,&pIStream1);

            rhs.img->Save(pIStream1, &jpgClsid, NULL);
            //lhs<< pIStream1;
            pIStream1->Release();
            pIStorage->Release();

i don't get the image on file. or isnt read correctly :(

IStorage* pIStorage = NULL;
            IStream* pIStream1 = NULL;
            //IStream* pIStream2 = NULL;
            HRESULT hr;
            Status stat = Ok;
            hr = CoInitialize(NULL);

            hr = StgCreateDocfile( L"CompoundFile.cmp", STGM_READWRITE|STGM_CREATE|STGM_SHARE_EXCLUSIVE,0, &pIStorage);
            pIStorage->CreateStream(L"StreamImage1", STGM_READWRITE|STGM_SHARE_EXCLUSIVE, 0, 0,&pIStream1);
            //lhs>> (char*)pIStream1;
            rhs.img->FromStream(pIStream1,FALSE);

            pIStream1->Release();
            pIStorage->Release();

anyone can advice me?

 

Share this post


Link to post
Share on other sites
phil_t    8084

Your code doesn't check *any* of the values returned by the functions you're calling (even the function you wrote, GetEncoderClsid (which has a memory leak in it, btw).

 

The first thing I would do is step through it in the debugger and check the return values of all the gdi+ and compound storage API calls you're making, and make sure they are what you expect.

Edited by phil_t

Share this post


Link to post
Share on other sites
cambalinho    230

Your code doesn't check *any* of the values returned by the functions you're calling (even the function you wrote, GetEncoderClsid (which has a memory leak in it, btw).

 

The first thing I would do is step through it in the debugger and check the return values of all the gdi+ and compound storage API calls you're making, and make sure they are what you expect.

now i'm doing it:

friend std::ostream& operator << (std::ostream& lhs, const image& rhs)
    {

        //Create an empty IStream:
        IStream* pIStream = nullptr;
        HGLOBAL hg=NULL;
        if(CreateStreamOnHGlobal(hg, FALSE, (LPSTREAM*)&pIStream)!=S_OK)
            DebugText("error on creating an empty IStream");

        //choose image format for save it on IStream:
        // Get encoder class id for jpg compression
        // for other compressions use
        //    image/bmp
        //    image/jpeg
        //    image/gif
        //    image/tiff
        //    image/png
        CLSID pngClsid;
        GetEncoderClsid(L"image/gif", &pngClsid);

        // Setup encoder parameters
        EncoderParameters encoderParameters;
        encoderParameters.Count = 1;
        encoderParameters.Parameter[0].Guid = EncoderQuality;
        encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
        encoderParameters.Parameter[0].NumberOfValues = 1;

        // setup compression level
        ULONG quality = 50;
        encoderParameters.Parameter[0].Value = &quality;

        //  Save the image to the stream

        if(rhs.img->Save(pIStream, &pngClsid, &encoderParameters) != Ok)
        {
            pIStream->Release();
            DebugText("error on saving to IStream");
        }

        //getting the stream size:
        int buffsize=GlobalSize(&hg);

        char *pBuff = new char[buffsize];
        ULONG ulBytesRead;

        //Read the stream to pBuff
        if(pIStream->Read(pBuff,buffsize, &ulBytesRead)!=S_OK)
            DebugText("error on saving IStream to buffer");

        //write the stream size on file
        lhs << buffsize;

        //write pBuff data on file
        lhs << pBuff;

        //clean resources
        delete pBuff;
        pIStream->Release();

        return lhs;
    }

    friend std::istream& operator >> (std::istream& lhs, image& rhs)
    {
        //getting IStream size:
        int streamsize;
        lhs.read(reinterpret_cast<char*>(&streamsize), sizeof(streamsize));

        IStream* pIStream = nullptr;

        // Create stream with 0 size
        HGLOBAL hg= ::GlobalAlloc(GMEM_MOVEABLE,streamsize);
        GlobalLock(hg);
        lhs.read(reinterpret_cast<char*>(&hg),sizeof(streamsize));
        GlobalUnlock(hg);

        if(CreateStreamOnHGlobal(&hg, TRUE, (LPSTREAM*)&pIStream)!=S_OK)
            DebugText("error on creating an empty IStream");

        //reading IStream on Image class:
        if(rhs.img->FromStream(pIStream,TRUE)!=S_OK)
            DebugText("error reading stream to Image");

        //realease resources:
        pIStream->Release();
        GlobalFree(hg);
        return lhs;
    }

when i do: pIStream, i don't get any results, and the error message is showed.

(DebugText() it's my own function for avoid the message box)

i'm complete new with IStream. i'm totaly confused sad.png

PS: the GetEncoderClsid() is from MSDN.

Edited by cambalinho

Share this post


Link to post
Share on other sites
cambalinho    230

now i can save the image object on IStream:

bool blnSaveFile=false;
    void save(string filename)
    {
        blnSaveFile=true;
        ofstream WriteOnFile(filename.c_str(), ios::out | ios::binary);
        WriteOnFile<<*this;
        WriteOnFile.close();
        blnSaveFile=false;
    }

friend std::ostream& operator << (std::ostream& lhs, image& rhs)
    {
        //Create an empty IStream:
        IStream* pIStream = nullptr;
        if(CreateStreamOnHGlobal(NULL, FALSE, (LPSTREAM*)&pIStream)!=S_OK)
            DebugText("error on creating an empty IStream");

        //Create the Encoder way:
        //choose image format for save it on IStream:
        // Get encoder class id for jpg compression
        // for other compressions use
        //    image/bmp
        //    image/jpeg
        //    image/gif
        //    image/tiff
        //    image/png
        CLSID pngClsid;
        GetEncoderClsid(L"image/gif", &pngClsid);

        // Setup encoder parameters
        EncoderParameters* encoderParameters = (EncoderParameters*)malloc(sizeof(EncoderParameters) +  (rhs.framecount-1)* sizeof(EncoderParameter));
        encoderParameters->Count = 1;
        ULONG parameterValue = 50;
       // the for loop is pointless and does nothing
        encoderParameters->Parameter[0].Guid = EncoderSaveFlag;
        encoderParameters->Parameter[0].Type = EncoderParameterValueTypeLong;
        encoderParameters->Parameter[0].NumberOfValues = 1;
        encoderParameters->Parameter[0].Value = &parameterValue;

        //save the 1st frame:
        parameterValue = EncoderValueMultiFrame;
        Status            stat;
        rhs.img->SetPalette(rhs.imgPallet);
        if(rhs.img->Save(pIStream, &pngClsid, encoderParameters) != Ok)
        {
            pIStream->Release();
            MessageBox("error on saving to IStream");
        }

        for(int i=1; i<rhs.framecount;i++)
        {
            //create a new Image for save the selected frame:
            rhs.img->SetPalette(rhs.imgPallet);
            Image *img2= rhs.img;

            //Selecte the frame:
            UINT count = 0;
            count = img2->GetFrameDimensionsCount();
            vector<GUID> pDimensionIDs;
            pDimensionIDs.resize(count);
            img2->GetFrameDimensionsList(pDimensionIDs.data(), pDimensionIDs.size());
            img2->SelectActiveFrame(&pDimensionIDs[0],i);

            //save the next frames, from img2, on stream:

            if(i==rhs.framecount-1)
                parameterValue = EncoderValueLastFrame;
            else
                parameterValue = EncoderValueFrameDimensionTime;
            stat = rhs.img->SaveAdd(img2, encoderParameters);
        }
        //closing the stream:
        parameterValue = EncoderValueFlush;
        stat = rhs.img->SaveAdd(encoderParameters);

        //getting the stream size:
        STATSTG sts;
        pIStream->Stat(&sts, STATFLAG_DEFAULT);
        ULARGE_INTEGER uli = sts.cbSize;
        LARGE_INTEGER zero;
        zero.QuadPart = 0;
        int size = (int)uli.QuadPart;

        //save the stream to char*
        char* bits = new char[size];
        ULONG written;
        pIStream->Seek(zero, STREAM_SEEK_SET, NULL);
        pIStream->Read(bits, size, &written);

        if(rhs.blnSaveFile!=true)
        {
            //write the stream size on file
            lhs.write(reinterpret_cast<char*>(&size),sizeof(int));
        }

        //write pBuff data on file
        lhs.write(reinterpret_cast<char*>(bits),size);

        //clean resources
        delete[] bits;
        pIStream->Release();
        free(encoderParameters);
        return lhs;
    }

the image is saved on file, but with 1 little diferent from the original:

[url=https://postimg.org/image/c4gbcvdar/]my_istream_images.gif[/url]

why the backcolor is changed from white to black?

if the problem is the transparency, i'm trying use the Palette without sucess :(

Edited by cambalinho

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this