Thread: GDIPLUS::Image: how save it on a file in stream way?

  1. #16
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    >>char *pBuff = new char[buffsize];
    Use a vector, e.g.:
    std::vectpr<char> Buffer(buffsize);
    new [] shall also be paired with delete [], not delete.

    >>lhs.write(reinterpret_cast<char*>(&buffsize),siz eof(int));
    Type of variable buffsize can change; use sizeof(buffsize) instead.

    >>lhs.write(pBuff,sizeof(pBuff));
    sizeof of a pointer is 4 or 8 bytes. Use a vector and use vector.size(), e.g. Buff.size(). You are writing the incorrect amount of characters.

    >>lhs.read(reinterpret_cast<char*>(&streamsize), sizeof(ULONG));
    You wrote an int and now you are reading an ULONG? That's asking for trouble. If you write an int, read an int.

    >>lhs.read(reinterpret_cast<char*>(&hg),sizeof(str eamsize));
    Why do you think this will work? hg is not a buffer. Furthermore, the number of characters to read is NOT sizeof(streamsize). You are guessing! You need to stop guessing. If you write 4 + N bytes, you need to read 4 + N bytes back. It's that simple. Try a simple example first to see that what you get back is what you wrote!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #17
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Elysia View Post
    >>char *pBuff = new char[buffsize];
    Use a vector, e.g.:
    std::vectpr<char> Buffer(buffsize);
    new [] shall also be paired with delete [], not delete.

    >>lhs.write(reinterpret_cast<char*>(&buffsize),siz eof(int));
    Type of variable buffsize can change; use sizeof(buffsize) instead.

    >>lhs.write(pBuff,sizeof(pBuff));
    sizeof of a pointer is 4 or 8 bytes. Use a vector and use vector.size(), e.g. Buff.size(). You are writing the incorrect amount of characters.

    >>lhs.read(reinterpret_cast<char*>(&streamsize), sizeof(ULONG));
    You wrote an int and now you are reading an ULONG? That's asking for trouble. If you write an int, read an int.

    >>lhs.read(reinterpret_cast<char*>(&hg),sizeof(str eamsize));
    Why do you think this will work? hg is not a buffer. Furthermore, the number of characters to read is NOT sizeof(streamsize). You are guessing! You need to stop guessing. If you write 4 + N bytes, you need to read 4 + N bytes back. It's that simple. Try a simple example first to see that what you get back is what you wrote!
    i'm trying
    now i get a memory leak:
    Code:
    friend std::ostream& operator << (std::ostream& lhs, const image& rhs)
        {
    
            //Create an empty IStream:
            IStream* pIStream = nullptr;
            HGLOBAL hg=NULL;
            if(CreateStreamOnHGlobal(hg, TRUE, (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;
            if(GetEncoderClsid(L"image/gif", &pngClsid)!=S_OK)
                DebugText("error on image format");
    
            // 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
            Status SaveStatus = rhs.img->Save(pIStream, &pngClsid, &encoderParameters);
            if(SaveStatus != Ok)
            {
                pIStream->Release();
                DebugText("error on saving to IStream");
            }
    
            //getting the stream size:
            if(GetHGlobalFromStream(pIStream,&hg)!=S_OK)
                DebugText("error on IStream information");
    
            int buffsize=GlobalSize(&hg);
    
            std::vector<char> pBuff(buffsize);
            ULONG ulBytesRead;
    
            //Read the stream to pBuff
            if(pIStream->Read(pBuff.data(),buffsize, &ulBytesRead)!=S_OK)
                DebugText("error on saving IStream to buffer");
    
            //write the stream size on file
            lhs.write(reinterpret_cast<char*>(&buffsize),sizeof(buffsize));
    
            //write pBuff data on file
            lhs.write(pBuff.data(),pBuff.size());
    
            //clean resources
            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=NULL;
            lhs.read(reinterpret_cast<char*>(&hg),sizeof(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,FALSE)!=S_OK)
                DebugText("error reading stream to Image");
    
            //realease resources:
            pIStream->Release();
            return lhs;
        }

  3. #18
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Line 76 - No. Read the documentation on how to use an HGLOBAL.

    HGLOBAL is just a handle. I makes not sense to try and read/write a handle value.

    Why don't you just read it into a vector buffer and get it working? Once working, then work on removing the vector on both sides and use the memory represented by the the HGLOBAL directly.

    >>theres 2 things that i didn't understand:
    eg. "rhs.pngClsid" and "rhs.encoderParameters" - where these have been pre-configured by the caller before calling operator<<.


    gg

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    joaquim, what is it you fail to grasp? We already told you hg is not a buffer and yet you read into it anyway.

    Like I said, start with a simpler example. Write a string, read it back. Make sure you read it back correctly. Then you can tackle this problem.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Elysia View Post
    joaquim, what is it you fail to grasp? We already told you hg is not a buffer and yet you read into it anyway.

    Like I said, start with a simpler example. Write a string, read it back. Make sure you read it back correctly. Then you can tackle this problem.
    using the string, like you have seen on other thread it's easy... but not these

    Code:
    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;
        }
    i'm sorry, but i'm trying, but these continues confused
    i'm sorry

  6. #21
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> but these continues confused
    What are you confused about?

    gg

  7. #22
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Codeplug View Post
    >> but these continues confused
    What are you confused about?

    gg
    you(both) told me for i do in these way:
    (for save it on file)
    1 - create an empty IStream:
    Code:
    IStream* pIStream = nullptr;
            HGLOBAL hg=NULL;
            if(CreateStreamOnHGlobal(hg, FALSE, (LPSTREAM*)&pIStream)!=S_OK)
    2 - save the Image to IStream:
    Code:
    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)
    3 - getting IStream size:
    Code:
    int buffsize=GlobalSize(&hg);
    4 - i must save the IStream on a buffer:
    Code:
    char *pBuff = new char[buffsize];
            ULONG ulBytesRead;
    
            //Read the stream to pBuff
            if(pIStream->Read(pBuff,buffsize, &ulBytesRead)!=S_OK)
    5 -now save the buffer size on file and the buffer:
    Code:
    //write the stream size on file
            lhs << buffsize;
    
            //write pBuff data on file
            lhs << pBuff;
    6 - we must delete the resources:
    Code:
    //clean resources
            delete[] pBuff;
            pIStream->Release();
    PS: i know the file it's created, what i don't have sure if the data it's right on file.

    now for read it from a file:

    1 - create an empty IStream:
    Code:
    IStream* pIStream = nullptr;
            HGLOBAL hg=NULL;
            if(CreateStreamOnHGlobal(hg, FALSE, (LPSTREAM*)&pIStream)!=S_OK)
    2 - read the buffer(inclued the buffer size) from the file to a new IStream:
    Code:
    /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");
    (i don't get any error)
    3 - reading IStream to Image class:
    Code:
    if(rhs.img->FromStream(pIStream,TRUE)!=S_OK)
                DebugText("error reading stream to Image");
    4 - clean resources:
    Code:
    //realease resources:
            pIStream->Release();
            GlobalFree(hg);
    i see what i must do(unless i miss something). but if the FromStream() give me an error, means the IStream isn't right. i don't understand why.. i'm totaly confused.
    sorry to all, but i'm trying to understand and see what isn't right

  8. #23
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    This:
    Code:
    GlobalLock(hg);        
    lhs.read(reinterpret_cast<char*>(&hg),sizeof(streamsize));
    wants to be something like this. Otherwise all you're doing is overwriting the HGLOBAL.
    Code:
    void* p = GlobalLock(hg);        
    lhs.read(static_cast<char*>(p), streamsize);
    This
    Code:
    if(CreateStreamOnHGlobal(&hg, TRUE, (LPSTREAM*)&pIStream)!=S_OK)
    Also wants to lose the first ampersand since it only takes a HGLOBAL, not a pointer to one
    Code:
    if(CreateStreamOnHGlobal(hg, TRUE, (LPSTREAM*)&pIStream)!=S_OK)

  9. #24
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> if(GetHGlobalFromStream(pIStream,&hg)!=S_OK)
    Why was that removed?

    >> int buffsize=GlobalSize(&hg);
    That does not take a pointer to HGLOBAL either.

    gg

  10. #25
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    thanks to both about correct me.
    but Codeplug(thanks for that. i'm confused and sometimes i can do mistakes.. sorry about that) how can i get the IStream size?
    i'm reading these: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
    but: "error: 'IStream_Size' was not declared in this scope"
    i had include the Shlwapi.h file, but seems not be used with GNU or something

  11. #26
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    In my SDK, you only get the IStream_Size declaration if:
    #if (_WIN32_IE >= _WIN32_IE_IE501)

    But you don't need it. When writing, GlobalSize() give you the size of the stream. When reading, the istream itself contains the size.

    gg

  12. #27
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Quote Originally Posted by Codeplug View Post
    In my SDK, you only get the IStream_Size declaration if:
    #if (_WIN32_IE >= _WIN32_IE_IE501)

    But you don't need it. When writing, GlobalSize() give you the size of the stream. When reading, the istream itself contains the size.

    gg
    see what i did now:
    Code:
    //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);
            if(buffsize==0)
                DebugText("error on getting IStream size");
    i get that message... maybe i miss something on CreateStreamOnHGlobal()

  13. #28
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    yes i did another mistake. the hg was not correctly created:
    Code:
    friend std::ostream& operator << (std::ostream& lhs, const image& rhs)
        {
    
            //Create an empty IStream:
            IStream* pIStream = nullptr;
            HGLOBAL hg=GlobalAlloc(GMEM_MOVEABLE,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:
            if(GlobalFlags(hg)== GMEM_INVALID_HANDLE)
                DebugText("error: invalid handle");
            int buffsize=GlobalSize(hg);
            if(buffsize==0)
                DebugText("error on getting IStream size");
            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;
        }
    here i don't have errors, but i don't have sure if is correctly on file.
    now see the read code:
    Code:
    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,NULL);
            void* p =GlobalLock(hg);
            lhs.read(reinterpret_cast<char*>(p),sizeof(streamsize));
            GlobalUnlock(hg);
    
            if(CreateStreamOnHGlobal(hg, TRUE, (LPSTREAM*)&pIStream)!=S_OK)
                DebugText("error on creating an empty IStream");
            GetHGlobalFromStream(pIStream,&hg);
            //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;
        }
    i don't see the image, but i get a memory leak

  14. #29
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Write:
    Line 6: remove
    Line 7: pass NULL for HGLOBAL
    Line 39: call GetHGlobalFromStream() to get the value of hg
    Line 54, 57: stop using formatted output. Use lhs.write()

    Read:
    Line 10: second parameter is incorrect
    Line 17: remove
    Line 24: remove, or change the second parameter to CreateStreamOnHGlobal()

    gg

  15. #30
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Memory leak in Write:
    Line 7: pass TRUE to second parameter, or call GlobalFree()

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Displaying Image from stream
    By NetCoder in forum C++ Programming
    Replies: 5
    Last Post: 02-25-2013, 03:04 AM
  2. How can I save an image to file.
    By vmars316 in forum Windows Programming
    Replies: 1
    Last Post: 12-26-2010, 09:44 AM
  3. Low level program to save a mjpeg stream
    By Rufe0 in forum Linux Programming
    Replies: 6
    Last Post: 09-22-2009, 05:53 AM
  4. how to save one svg image by programing
    By sfguofen in forum C++ Programming
    Replies: 9
    Last Post: 09-04-2009, 08:11 PM
  5. How to get image from the screen and then save it to a file?
    By nomer in forum Windows Programming
    Replies: 2
    Last Post: 05-25-2006, 08:46 AM