コード例 #1
0
FloatPixMapRef FPMCopySub(FloatPixMapRef pm, FPMRect rect)
{
	FloatPixMapRef sub = FPMCreateSub(pm, rect);
	FloatPixMapRef result = FPMCopy(sub);
	FPMRelease(&sub);
	return result;
}
コード例 #2
0
bool FPMWritePNGCustom(FloatPixMapRef srcPM, png_voidp ioPtr, png_rw_ptr writeDataFn, png_flush_ptr flushDataFn, FPMWritePNGFlags options, FPMGammaFactor sourceGamma, FPMGammaFactor fileGamma, FPMPNGErrorHandler errorHandler)
{
    if (srcPM != NULL)
    {
        bool				success = false;
        png_structp			png = NULL;
        png_infop			pngInfo = NULL;
        FloatPixMapRef		pm = NULL;

        // Prepare data.
        FPMDimension width = FPMGetWidth(srcPM);
        FPMDimension height = FPMGetHeight(srcPM);
        if (width > UINT32_MAX || height > UINT32_MAX)
        {
            if (errorHandler != NULL)  errorHandler("image is too large for PNG format.", true);
            return false;
        }

        pm = FPMCopy(srcPM);
        if (pm == NULL)  return false;

        unsigned steps = (options & kFPMWritePNG16BPC) ? 0x10000 : 0x100;
        FPMApplyGamma(pm, sourceGamma, fileGamma, steps);
        FPMQuantize(pm, 0.0f, 1.0f, 0.0f, steps - 1, steps, (options & kFPMQuantizeDither & kFPMQuantizeJitter) | kFMPQuantizeClip | kFMPQuantizeAlpha);

        png = png_create_write_struct(PNG_LIBPNG_VER_STRING, errorHandler, PNGError, PNGWarning);
        if (png == NULL)  goto FAIL;

        pngInfo = png_create_info_struct(png);
        if (pngInfo == NULL)  goto FAIL;

        if (setjmp(png_jmpbuf(png)))
        {
            // libpng will jump here on error.
            goto FAIL;
        }

        png_set_write_fn(png, ioPtr, writeDataFn, flushDataFn);

        png_set_IHDR(png, pngInfo, width, height, (options & kFPMWritePNG16BPC) ? 16 : 8,PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

        if (fileGamma == kFPMGammaSRGB)
        {
            png_set_sRGB_gAMA_and_cHRM(png, pngInfo, PNG_sRGB_INTENT_PERCEPTUAL);
        }
        else
        {
            png_set_gAMA(png, pngInfo, fileGamma);
        }

        /*	Select function used to transform a row of data to PNG-friendly
        	format. NOTE: these work in place,and overwrite the data in pm,
        	which is OK since we copied it.
        */
        RowTransformer transformer = NULL;
        if (options & kFPMWritePNG16BPC)
        {
            transformer = TransformRow16;
        }
        else
        {
            transformer = TransformRow8;
        }

        png_write_info(png, pngInfo);

        size_t i;
        size_t rowOffset = FPMGetRowByteCount(pm);
        png_bytep row = (png_bytep)FPMGetBufferPointer(pm);
        for (i = 0; i < height; i++)
        {
            transformer(row, width);
            png_write_row(png, row);
            row += rowOffset;
        }
        png_write_end(png, pngInfo);
        success = true;

FAIL:
        if (png != NULL)  png_destroy_write_struct(&png, &pngInfo);
        FPMRelease(&pm);

        return success;
    }
    else
    {
        return false;
    }
}