// ========================================================== // Memory Input/Output functions // // Design and implementation by // - Ryan Rubley // - Hervé Drolon (drolon@infonie.fr) // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at your own risk! // ========================================================== #include "../stdafx.h" // ===================================================================== // ===================================================================== // Open and close a memory handle // ===================================================================== FIMEMORY * DLL_CALLCONV FreeImage_OpenMemory(uint8_t *data, uint32_t size_in_bytes) { // allocate a memory handle FIMEMORY *stream = (FIMEMORY*)malloc(sizeof(FIMEMORY)); if(stream) { stream->data = (uint8_t*)malloc(sizeof(FIMEMORYHEADER)); if(stream->data) { FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); // initialize the memory header memset(mem_header, 0, sizeof(FIMEMORYHEADER)); if(data && size_in_bytes) { // wrap a user buffer mem_header->delete_me = FALSE; mem_header->data = (uint8_t*)data; mem_header->data_length = mem_header->file_length = size_in_bytes; } else { mem_header->delete_me = TRUE; } return stream; } free(stream); } return NULL; } void DLL_CALLCONV FreeImage_CloseMemory(FIMEMORY *stream) { if(stream && stream->data) { FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); if(mem_header->delete_me) { free(mem_header->data); } free(mem_header); free(stream); } } // ===================================================================== // Memory stream load/save functions // ===================================================================== FIBITMAP * DLL_CALLCONV FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) { if (stream && stream->data) { FreeImageIO io; SetMemoryIO(&io); return FreeImage_LoadFromHandle(fif, &io, (fi_handle)stream, flags); } return NULL; } BOOL DLL_CALLCONV FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags) { if (stream) { FreeImageIO io; SetMemoryIO(&io); FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); if(mem_header->delete_me == TRUE) { return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)stream, flags); } else { // do not save in a user buffer FreeImage_OutputMessageProc(fif, "Memory buffer is read only"); } } return FALSE; } // ===================================================================== // Memory stream buffer access // ===================================================================== BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream, uint8_t **data, uint32_t *size_in_bytes) { if (stream) { FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data); *data = (uint8_t*)mem_header->data; *size_in_bytes = mem_header->file_length; return TRUE; } return FALSE; } // ===================================================================== // Seeking in Memory stream // ===================================================================== /** Moves the memory pointer to a specified location @param stream Pointer to FIMEMORY structure @param offset Number of bytes from origin @param origin Initial position @return Returns TRUE if successful, returns FALSE otherwise */ BOOL DLL_CALLCONV FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin) { FreeImageIO io; SetMemoryIO(&io); if (stream != NULL) { int success = io.seek_proc((fi_handle)stream, offset, origin); return (success == 0) ? TRUE : FALSE; } return FALSE; } /** Gets the current position of a memory pointer @param stream Target FIMEMORY structure @return Returns the current file position if successful, -1 otherwise */ long DLL_CALLCONV FreeImage_TellMemory(FIMEMORY *stream) { FreeImageIO io; SetMemoryIO(&io); if (stream != NULL) { return io.tell_proc((fi_handle)stream); } return -1L; } // ===================================================================== // Reading or Writing in Memory stream // ===================================================================== /** Reads data from a memory stream @param buffer Storage location for data @param size Item size in bytes @param count Maximum number of items to be read @param stream Pointer to FIMEMORY structure @return Returns the number of full items actually read, which may be less than count if an error occurs */ unsigned DLL_CALLCONV FreeImage_ReadMemory(void *buffer, unsigned size, unsigned count, FIMEMORY *stream) { FreeImageIO io; SetMemoryIO(&io); if (stream != NULL) { return io.read_proc(buffer, size, count, stream); } return 0; } /** Writes data to a memory stream. @param buffer Pointer to data to be written @param size Item size in bytes @param count Maximum number of items to be written @param stream Pointer to FIMEMORY structure @return Returns the number of full items actually written, which may be less than count if an error occurs */ unsigned DLL_CALLCONV FreeImage_WriteMemory(const void *buffer, unsigned size, unsigned count, FIMEMORY *stream) { if (stream != NULL) { FreeImageIO io; SetMemoryIO(&io); FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)stream)->data); if(mem_header->delete_me == TRUE) { return io.write_proc((void *)buffer, size, count, stream); } else { // do not write in a user buffer FreeImage_OutputMessageProc(FIF_UNKNOWN, "Memory buffer is read only"); } } return 0; }