Jump to content
  • Advertisement
Sign in to follow this  
cambalinho

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

This topic is 658 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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
Advertisement

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

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

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:

my_istream_images.gif

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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!