Ejemplo n.º 1
0
void hqx_scale(gdImagePtr srcIm, int factor, gdImagePtr* result)
{
    gdImagePtr dstIm;
    uint32_t *srcBuffer, *dstBuffer;
    size_t srcSize, dstSize;
    uint32_t w, h;
    uint32_t x, y;

    w = gdImageSX(srcIm);
    h = gdImageSY(srcIm);

    srcSize = sizeof(uint32_t) * w * h;
    dstSize = sizeof(uint32_t) * factor * w * factor * h;

    // Unfortunately it doesn't work to simply pass the gd buffer from the
    // gdImage struct to hqx, and the gd documentation explicitly says
    // not to access member fields directly. Thus we allocate two buffers
    // and copy the data back and forth as a workaround.

    srcBuffer = (uint32_t*)emalloc(srcSize);
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            srcBuffer[w*y + x] = gdImageGetPixel(srcIm, x, y);
        }
    }

    dstBuffer = (uint32_t*)emalloc(dstSize);
    if (factor == 4) {
        hq4x_32_rb(srcBuffer, sizeof(uint32_t)*w,
                   dstBuffer, sizeof(uint32_t)*factor*w,
                   w, h);
    } else if (factor == 3) {
        hq3x_32_rb(srcBuffer, sizeof(uint32_t)*w,
                   dstBuffer, sizeof(uint32_t)*factor*w,
                   w, h);
    } else if (factor == 2) {
        hq2x_32_rb(srcBuffer, sizeof(uint32_t)*w,
                   dstBuffer, sizeof(uint32_t)*factor*w,
                   w, h);
    }

    dstIm = gdImageCreateTrueColor(factor*w, factor*h);
    gdImageAlphaBlending(dstIm, 0);
    gdImageSaveAlpha(dstIm, 1);

    for (y = 0; y < factor*h; y++) {
        for (x = 0; x < factor*w; x++) {
            gdImageSetPixel(dstIm, x, y, dstBuffer[factor*w*y + x]);
        }
    }

    efree(srcBuffer);
    efree(dstBuffer);

    *result = dstIm;
}
Ejemplo n.º 2
0
/**
 * Internal 8-bit Zoomer without smoothing.
 * Source code originally from SDL_gfx (LGPL) with permission by author.
 *
 * Zooms 8bit palette/Y 'src' surface to 'dst' surface.
 * Assumes src and dst surfaces are of 8-bit depth.
 * Assumes dst surface was allocated with the correct dimensions.
 *
 * @param src The surface to zoom (input).
 * @param dst The zoomed surface (output).
 * @param flipx Flag indicating if the image should be horizontally flipped.
 * @param flipy Flag indicating if the image should be vertically flipped.
 * @return 0 for success or -1 for error.
 */
int Zoom::_zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
{
	int x, y;
	static Uint32 *sax, *say;
	Uint32 *csax, *csay;
	int csx, csy;
	Uint8 *sp, *dp, *csp;
	int dgap;
	static bool proclaimed = false;

	if (Screen::is32bitEnabled())
	{
		if (Options::useXBRZFilter)
		{
			// check the resolution to see which scale we need
			for (size_t factor = 2; factor <= 5; factor++)
			{
				if (dst->w == src->w * (int)factor && dst->h == src->h * (int)factor)
				{
					xbrz::scale(factor, (uint32_t*)src->pixels, (uint32_t*)dst->pixels, src->w, src->h, xbrz::RGB);
					return 0;
				}
			}
		}

		if (Options::useHQXFilter)
		{
			static bool initDone = false;

			if (!initDone)
			{
				hqxInit();
				initDone = true;
			}

			// HQX_API void HQX_CALLCONV hq2x_32_rb( uint32_t * src, uint32_t src_rowBytes, uint32_t * dest, uint32_t dest_rowBytes, int width, int height );

			if (dst->w == src->w * 2 && dst->h == src->h * 2)
			{
				hq2x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);
				return 0;
			}

			if (dst->w == src->w * 3 && dst->h == src->h * 3)
			{
				hq3x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);
				return 0;
			}

			if (dst->w == src->w * 4 && dst->h == src->h * 4)
			{
				hq4x_32_rb((uint32_t*)src->pixels, src->pitch, (uint32_t*)dst->pixels, dst->pitch, src->w, src->h);
				return 0;
			}
		}
	}

	if (Options::useScaleFilter)
	{
		// check the resolution to see which of scale2x, scale3x, etc. we need
		for (size_t factor = 2; factor <= 4; factor++)
		{
			if (dst->w == src->w * (int)factor && dst->h == src->h * (int)factor && !scale_precondition(factor, src->format->BytesPerPixel, src->w, src->h))
			{
				scale(factor, dst->pixels, dst->pitch, src->pixels, src->pitch, src->format->BytesPerPixel, src->w, src->h);
				return 0;
			}
		}
	}

	// if we're scaling by a factor of 2 or 4, try to use a more efficient function
	/*
	if (src->format->BytesPerPixel == 1 && dst->format->BytesPerPixel == 1)
	{

#ifdef __SSE2__
		static bool _haveSSE2 = haveSSE2();

		if (_haveSSE2 &&
			!((ptrdiff_t)src->pixels % 16) &&
			!((ptrdiff_t)dst->pixels % 16)) // alignment check
		{
			if (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_SSE2(src, dst);
			else if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_SSE2(src, dst);
		} else
		{
			static bool complained = false;

			if (!complained)
			{
				complained = true;
				Log(LOG_ERROR) << "Misaligned surface buffers.";
			}
		}
#endif

// __WORDSIZE is defined on Linux, SIZE_MAX on Windows
#if defined(__WORDSIZE) && (__WORDSIZE == 64) || defined(SIZE_MAX) && (SIZE_MAX > 0xFFFFFFFF)
		if (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_64bit(src, dst);
		else if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_64bit(src, dst);
#else
		if (sizeof(void *) == 8)
		{
			if (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_64bit(src, dst);
			else if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_64bit(src, dst);
		}
		else
		{
			if (dst->w == src->w * 2 && dst->h == src->h * 2) return  zoomSurface2X_32bit(src, dst);
			else if (dst->w == src->w * 4 && dst->h == src->h * 4) return  zoomSurface4X_32bit(src, dst);
		}
#endif

		// maybe X is scaled by 2 or 4 but not Y?
		if (dst->w == src->w * 4) return zoomSurface4X_XAxis_32bit(src, dst);
		else if (dst->w == src->w * 2) return zoomSurface2X_XAxis_32bit(src, dst);
	}
	*/
	if (!proclaimed)
	{
		Log(LOG_INFO) << "Using software scaling routine. For best results, try an OpenGL filter.";
		proclaimed = true;
	}
	
	/*
	* Allocate memory for row increments
	*/
	if ((sax = (Uint32 *) realloc(sax, (dst->w + 1) * sizeof(Uint32))) == NULL) {
		sax = 0;
		return (-1);
	}
	if ((say = (Uint32 *) realloc(say, (dst->h + 1) * sizeof(Uint32))) == NULL) {
		say = 0;
		//free(sax);
		return (-1);
	}

	/*
	* Pointer setup
	*/
	sp = csp = (Uint8 *) src->pixels;
	dp = (Uint8 *) dst->pixels;
	dgap = dst->pitch - dst->w;

	if (flipx) csp += (src->w-1);
	if (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );

	/*
	* Precalculate row increments
	*/
	csx = 0;
	csax = sax;
	for (x = 0; x < dst->w; x++) {
		csx += src->w;
		*csax = 0;
		while (csx >= dst->w) {
			csx -= dst->w;
			(*csax)++;
		}
		(*csax) *= (flipx ? -1 : 1);
		csax++;
	}
	csy = 0;
	csay = say;
	for (y = 0; y < dst->h; y++) {
		csy += src->h;
		*csay = 0;
		while (csy >= dst->h) {
			csy -= dst->h;
			(*csay)++;
		}
		(*csay) *= src->pitch * (flipy ? -1 : 1);
		csay++;
	}
	/*
	* Draw
	*/
	csay = say;
	for (y = 0; y < dst->h; y++) {
		csax = sax;
		sp = csp;
		for (x = 0; x < dst->w; x++) {
			/*
			* Draw
			*/
			*dp = *sp;
			/*
			* Advance source pointers
			*/
			sp += (*csax);
			csax++;
			/*
			* Advance destination pointer
			*/
			dp++;
		}
		/*
		* Advance source pointer (for row)
		*/
		csp += (*csay);
		csay++;

		/*
		* Advance destination pointers
		*/
		dp += dgap;
	}

	/*
	* Never remove temp arrays
	*/
	//free(sax);
	//free(say);

	return 0;
}