예제 #1
0
bool ReadLatLongConstructor(FloatPixMapRef sourceImage, RenderFlags flags, SphericalPixelSourceFunction *source, void **context)
{
	if (sourceImage == NULL || context == NULL)  return false;
	
	ReadLatLongContext *cx = malloc(sizeof (ReadLatLongContext));
	if (cx == NULL)  return false;
	
	cx->pm = FPMRetain(sourceImage);
	cx->pwidth = FPMGetWidth(sourceImage);
	cx->width = (float)cx->pwidth / (2.0f * kPiF);
	cx->height = (float)FPMGetHeight(sourceImage) / kPiF;
	
	if (flags & kRenderFast)  *source = ReadLatLongFast;
	else  *source = ReadLatLong;
	
	*context = cx;
	return true;
}
예제 #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;
    }
}