Пример #1
0
static BOOL 
mng_InsertChunk(FIMEMORY *hPngMemory, BYTE *inNextChunkName, BYTE *inInsertChunk, unsigned chunk_length) {
	BOOL bResult = FALSE;

	DWORD start_pos = 0;
	DWORD next_pos = 0;
	
	bResult = mng_FindChunk(hPngMemory, inNextChunkName, 8, &start_pos, &next_pos);
	if(!bResult) return FALSE;

	bResult = mng_CopyInsertChunks(hPngMemory, inNextChunkName, inInsertChunk, chunk_length, start_pos, next_pos);
	if(!bResult) return FALSE;

	return TRUE;
}
Пример #2
0
static BOOL 
mng_RemoveChunk(FIMEMORY *hPngMemory, BYTE *chunk_name) {
	BOOL bResult = FALSE;

	DWORD start_pos = 0;
	DWORD next_pos = 0;
	
	bResult = mng_FindChunk(hPngMemory, chunk_name, 8, &start_pos, &next_pos);
	if(!bResult) return FALSE;

	bResult = mng_CopyRemoveChunks(hPngMemory, start_pos, next_pos);
	if(!bResult) return FALSE;

	return TRUE;
}
Пример #3
0
/**
   Write a FIBITMAP to a JNG stream
   @param format_id ID of the caller
   @param io Stream i/o functions
   @param dib Image to be saved
   @param handle Stream handle
   @param flags Saving flags
   @return Returns TRUE if successful, returns FALSE otherwise
*/
BOOL
mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags) {
    DWORD jng_width = 0;
    DWORD jng_height = 0;
    BYTE jng_color_type = 0;
    BYTE jng_image_sample_depth = 8;
    BYTE jng_image_compression_method = 8;  //  8: ISO-10918-1 Huffman-coded baseline JPEG.
    BYTE jng_image_interlace_method = 0;

    BYTE jng_alpha_sample_depth = 0;
    BYTE jng_alpha_compression_method = 0;
    BYTE jng_alpha_filter_method = 0;
    BYTE jng_alpha_interlace_method = 0;

    BYTE buffer[16];

    FIMEMORY *hJngMemory = NULL;
    FIMEMORY *hJpegMemory = NULL;
    FIMEMORY *hPngMemory = NULL;

    FIBITMAP *dib_rgb = NULL;
    FIBITMAP *dib_alpha = NULL;

    if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
        return FALSE;
    }

    unsigned bpp = FreeImage_GetBPP(dib);

    switch(bpp) {
        case 8:
            if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
                dib_rgb = dib;
                jng_color_type = MNG_COLORTYPE_JPEGGRAY;
            } else {
                // JPEG plugin will convert other types (FIC_MINISWHITE, FIC_PALETTE) to 24-bit on the fly
                //dib_rgb = FreeImage_ConvertTo24Bits(dib);
                dib_rgb = dib;
                jng_color_type = MNG_COLORTYPE_JPEGCOLOR;

            }
            break;
        case 24:
            dib_rgb = dib;
            jng_color_type = MNG_COLORTYPE_JPEGCOLOR;
            break;
        case 32:
            dib_rgb = FreeImage_ConvertTo24Bits(dib);
            jng_color_type = MNG_COLORTYPE_JPEGCOLORA;
            jng_alpha_sample_depth = 8;
            break;
        default:
            return FALSE;
    }

    jng_width = (DWORD)FreeImage_GetWidth(dib);
    jng_height = (DWORD)FreeImage_GetHeight(dib);

    try {
        hJngMemory = FreeImage_OpenMemory();

        // --- write JNG file signature ---
        FreeImage_WriteMemory(g_jng_signature, 1, 8, hJngMemory);

        // --- write a JHDR chunk ---
        SwapLong(&jng_width);
        SwapLong(&jng_height);
        memcpy(&buffer[0], &jng_width, 4);
        memcpy(&buffer[4], &jng_height, 4);
        SwapLong(&jng_width);
        SwapLong(&jng_height);
        buffer[8] = jng_color_type;
        buffer[9] = jng_image_sample_depth;
        buffer[10] = jng_image_compression_method;
        buffer[11] = jng_image_interlace_method;
        buffer[12] = jng_alpha_sample_depth;
        buffer[13] = jng_alpha_compression_method;
        buffer[14] = jng_alpha_filter_method;
        buffer[15] = jng_alpha_interlace_method;
        mng_WriteChunk(mng_JHDR, &buffer[0], 16, hJngMemory);

        // --- write a sequence of JDAT chunks ---
        hJpegMemory = FreeImage_OpenMemory();
        flags |= JPEG_BASELINE;
        if(!FreeImage_SaveToMemory(FIF_JPEG, dib_rgb, hJpegMemory, flags)) {
            throw (const char*)NULL;
        }
        if(dib_rgb != dib) {
            FreeImage_Unload(dib_rgb);
            dib_rgb = NULL;
        }
        {
            BYTE *jpeg_data = NULL;
            DWORD size_in_bytes = 0;

            // get a pointer to the stream buffer
            FreeImage_AcquireMemory(hJpegMemory, &jpeg_data, &size_in_bytes);
            // write chunks
            for(DWORD k = 0; k < size_in_bytes;) {
                DWORD bytes_left = size_in_bytes - k;
                DWORD chunk_size = MIN(JPEG_CHUNK_SIZE, bytes_left);
                mng_WriteChunk(mng_JDAT, &jpeg_data[k], chunk_size, hJngMemory);
                k += chunk_size;
            }
        }
        FreeImage_CloseMemory(hJpegMemory);
        hJpegMemory = NULL;

        // --- write alpha layer as a sequence of IDAT chunk ---
        if((bpp == 32) && (jng_color_type == MNG_COLORTYPE_JPEGCOLORA)) {
            dib_alpha = FreeImage_GetChannel(dib, FICC_ALPHA);

            hPngMemory = FreeImage_OpenMemory();
            if(!FreeImage_SaveToMemory(FIF_PNG, dib_alpha, hPngMemory, PNG_DEFAULT)) {
                throw (const char*)NULL;
            }
            FreeImage_Unload(dib_alpha);
            dib_alpha = NULL;
            // get the IDAT chunk
            {
                BOOL bResult = FALSE;
                DWORD start_pos = 0;
                DWORD next_pos = 0;
                long offset = 8;

                do {
                    // find the next IDAT chunk from 'offset' position
                    bResult = mng_FindChunk(hPngMemory, mng_IDAT, offset, &start_pos, &next_pos);
                    if(!bResult) break;

                    BYTE *png_data = NULL;
                    DWORD size_in_bytes = 0;

                    // get a pointer to the stream buffer
                    FreeImage_AcquireMemory(hPngMemory, &png_data, &size_in_bytes);
                    // write the IDAT chunk
                    mng_WriteChunk(mng_IDAT, &png_data[start_pos+8], next_pos - start_pos - 12, hJngMemory);

                    offset = next_pos;

                } while(bResult);
            }

            FreeImage_CloseMemory(hPngMemory);
            hPngMemory = NULL;
        }

        // --- write a IEND chunk ---
        mng_WriteChunk(mng_IEND, NULL, 0, hJngMemory);

        // write the JNG on output stream
        {
            BYTE *jng_data = NULL;
            DWORD size_in_bytes = 0;
            FreeImage_AcquireMemory(hJngMemory, &jng_data, &size_in_bytes);
            io->write_proc(jng_data, 1, size_in_bytes, handle);
        }

        FreeImage_CloseMemory(hJngMemory);
        FreeImage_CloseMemory(hJpegMemory);
        FreeImage_CloseMemory(hPngMemory);

        return TRUE;

    } catch(const char *text) {
        FreeImage_CloseMemory(hJngMemory);
        FreeImage_CloseMemory(hJpegMemory);
        FreeImage_CloseMemory(hPngMemory);
        if(dib_rgb && (dib_rgb != dib)) {
            FreeImage_Unload(dib_rgb);
        }
        FreeImage_Unload(dib_alpha);
        if(text) {
            FreeImage_OutputMessageProc(format_id, text);
        }
        return FALSE;
    }
}