コード例 #1
0
ファイル: Surface.cpp プロジェクト: Arvek/SOLARME
/**
 * \brief Creates a surface from the specified image file name.
 *
 * An assertion error occurs if the file cannot be loaded.
 *
 * \param file_name Name of the image file to load, relative to the base directory specified.
 * \param base_directory The base directory to use.
 */
Surface::Surface(const std::string& file_name, ImageDirectory base_directory):
  Drawable(),
  internal_surface(NULL),
  owns_internal_surface(true),
  with_colorkey(false),
  colorkey(0) {

  std::string prefix = "";
  bool language_specific = false;

  if (base_directory == DIR_SPRITES) {
    prefix = "sprites/";
  }
  else if (base_directory == DIR_LANGUAGE) {
    language_specific = true;
    prefix = "images/";
  }
  std::string prefixed_file_name = prefix + file_name;

  size_t size;
  char* buffer;
  FileTools::data_file_open_buffer(prefixed_file_name, &buffer, &size, language_specific);
  SDL_RWops* rw = SDL_RWFromMem(buffer, int(size));
  this->internal_surface = IMG_Load_RW(rw, 0);
  FileTools::data_file_close_buffer(buffer);
  SDL_RWclose(rw);

  Debug::check_assertion(internal_surface != NULL, StringConcat() <<
      "Cannot load image '" << prefixed_file_name << "'");
    
  with_colorkey = SDL_GetColorKey(internal_surface, &colorkey) == 0;
}
コード例 #2
0
ファイル: blitter.cpp プロジェクト: Tkachov/ceu_pingus
SDL_Surface*
Blitter::create_surface_from_format(SDL_Surface* surface, int w, int h)
{
  SDL_Surface* new_surface = SDL_CreateRGBSurface(0, w, h,
                                                  surface->format->BitsPerPixel, 
                                                  surface->format->Rmask,
                                                  surface->format->Gmask,
                                                  surface->format->Bmask,
                                                  surface->format->Amask);

  Uint8 alpha;
  if (SDL_GetSurfaceAlphaMod(surface, &alpha) == 0)
    SDL_SetSurfaceAlphaMod(new_surface, alpha);

  SDL_BlendMode blend_mode;
  if (SDL_GetSurfaceBlendMode(surface, &blend_mode) == 0)
    SDL_SetSurfaceBlendMode(new_surface, blend_mode);

  Uint8 r, g, b;
  if (SDL_GetSurfaceColorMod(surface, &r, &g, &b) == 0)
    SDL_SetSurfaceColorMod(new_surface, r, g, b);

  if (surface->format->palette)
    SDL_SetSurfacePalette(new_surface, surface->format->palette);

  Uint32 colorkey;
  if (SDL_GetColorKey(surface, &colorkey) == 0)
    SDL_SetColorKey(new_surface, SDL_TRUE, colorkey);

  return new_surface;
}
コード例 #3
0
ファイル: Surface.cpp プロジェクト: Arvek/SOLARME
/**
 * \brief Creates a surface form the specified SDL surface.
 *
 * This constructor must be used only by lowlevel classes that manipulate directly
 * SDL dependent surfaces.
 *
 * \param internal_surface The internal surface data. It won't be copied.
 * It must remain valid during the lifetime of this surface.
 * The destructor will not free it.
 */
Surface::Surface(SDL_Surface* internal_surface):
  Drawable(),
  internal_surface(internal_surface),
  owns_internal_surface(false),
  with_colorkey(false),
  colorkey(0) {

  with_colorkey = SDL_GetColorKey(internal_surface, &colorkey) == 0;
}
コード例 #4
0
ファイル: surface.cpp プロジェクト: soulik/LuaSDL-2.0
	int inline Surface::getColorKey(State & state, SDL_Surface  * surface){
		Uint32 colorKey;
		if (SDL_GetColorKey(surface, &colorKey) == 0){
			state.stack->push<int>(colorKey);
			return 1;
		}
		else{
			return 0;
		}
	}
コード例 #5
0
ファイル: sdl2_surface.c プロジェクト: asfluido/mruby-sdl2
static mrb_value
mrb_sdl2_video_surface_get_color_key(mrb_state *mrb, mrb_value self)
{
    uint32_t key;
    SDL_Surface *s = mrb_sdl2_video_surface_get_ptr(mrb, self);
    if (0 != SDL_GetColorKey(s, &key)) {
        mruby_sdl2_raise_error(mrb);
    }
    return mrb_fixnum_value(key);
}
コード例 #6
0
ファイル: IMG_savepng.cpp プロジェクト: binakot/caesaria-game
/** Write out the PLTE (and possibly tRNS) chunk to the png. This will create the
 *  palette data to set in the PLTE chunk and set it, and if the colorkey is set
 *  for the surface an appropriate tRNS chunk is generated.
 *
 *  \param png_ptr  A pointer to the png write structure.
 *  \param info_ptr A pointer to the png info structure.
 *  \param surf     The surface that is being written to the png.
 *  \return -1 on error, 0 if the palette chunk was written without problems.
 */
static int write_palette_chunk(png_structp png_ptr, png_infop info_ptr, SDL_Surface *surf)
{
    png_colorp palette;
    Uint8     *alphas;
    int        slot;

    SDL_PixelFormat *fmt = surf -> format;
    SDL_Color *sourcepal = fmt -> palette -> colors;

    // Write the image header first...
    png_set_IHDR(png_ptr, info_ptr, surf -> w, surf -> h, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    // now sort out the palette
    if(!(palette = (png_colorp)malloc(fmt -> palette -> ncolors * sizeof(png_color)))) {
        SDL_SetError("Unable to create memory for palette storage");
        return -1;
    }

    // Copy the palette over. Can't just use a straight 
    // memcpy as sdl palettes have pad bytes.
    for(slot = 0; slot < fmt -> palette -> ncolors; ++slot) {
        memcpy(&palette[slot], &sourcepal[slot], 3);
    }
    
    // Set it...
    png_set_PLTE(png_ptr, info_ptr, palette, fmt -> palette -> ncolors);

    // Done with the palette now
    free(palette);

    Uint32 colorkey;
    int ck = SDL_GetColorKey(surf, &colorkey);

    // If we have a colour key, we need to set up the alphas for each palette colour
    if(ck == 0) {
        // According the the PNG spec (section 4.2.1.1) we only need enough entries
        // to store transparencies up to the transparent pixel.
        if(!(alphas = (Uint8 *)malloc((colorkey + 1) * sizeof(Uint8)))) {
            SDL_SetError("Unable to create memory for transparency storage");
            return -1;
        }

        // Set all of the alpha values to full
        memset(alphas, 255, (colorkey + 1) * sizeof(Uint8));

        // And handle the transparent pixel
        alphas[colorkey] = 0;

        // Write the chunk, and then we're done with the transparencies
        png_set_tRNS(png_ptr, info_ptr, alphas, colorkey + 1, NULL);
        free(alphas);
    }

    return 0;
}
コード例 #7
0
/*!
\brief Returns colorkey info for a surface
*/
Uint32 _colorkey(SDL_Surface *src)
{
	Uint32 key = 0; 
#if (SDL_MINOR_VERSION == 3)
 	SDL_GetColorKey(src, &key);
#else
 	if (src) 
 	{
 		key = src->format->colorkey;
	}
#endif
 	return key;
}
コード例 #8
0
ファイル: surface.cpp プロジェクト: gerstrong/fheroes2plus
u32 Surface::GetColorKey(void) const
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
    if(isValid() && ! amask())
    {
        u32 res = 0;
        SDL_GetColorKey(surface, &res);
        return res;
    }
    return 0;
#else
    return isValid() && (surface->flags & SDL_SRCCOLORKEY) ? surface->format->colorkey : 0;
#endif
}
コード例 #9
0
ファイル: Image.cpp プロジェクト: i8degrees/nomlib
const Color4i Image::colorkey ( void ) const
{
  SDL_Surface* buffer = this->image();
  uint32 transparent_color = 0;
  Color4i key;

  if ( SDL_GetColorKey ( this->image(), &transparent_color ) != 0 )
  {
    NOM_LOG_ERR ( NOM, SDL_GetError() );
    return key; // NULL (-1)
  }

  return nom::pixel ( transparent_color, buffer->format ); // SDL_helper function
}
コード例 #10
0
ファイル: surface.cpp プロジェクト: mastermind-/free-heroes
u32 Surface::GetColorKey(void) const
{
    if(isValid())
    {
#if SDL_VERSION_ATLEAST(1, 3, 0)
	u32 res = 0;
	SDL_GetColorKey(surface, &res);
	return res;
#else
	return (surface->flags & SDL_SRCCOLORKEY) ? surface->format->colorkey : 0;
#endif
    }
    return 0;
}
コード例 #11
0
ファイル: Surface.cpp プロジェクト: Maxs1789/solarus
/**
 * \brief Returns whether a pixel is transparent.
 *
 * A pixel is transparent if it corresponds to the colorkey
 * or if its alpha channel is equal to 0.
 *
 * \param index The index of the pixel to test.
 * \return \c true if the pixel is transparent.
 */
bool Surface::is_pixel_transparent(int index) const {

  uint32_t pixel = get_pixel(index);
  uint32_t colorkey;
  bool with_colorkey = SDL_GetColorKey(internal_surface.get(), &colorkey) == 0;

  if (with_colorkey && pixel == colorkey) {
    // The pixel has the transparency color.
    return true;
  }

  if (internal_surface->format->Amask != 0               // There exists an alpha channel.
      && (pixel & internal_surface->format->Amask) == 0  // The pixel is fully transparent.
  ) {
    return true;
  }

  return false;
}
コード例 #12
0
void blitMaskedSprite(SDL_Surface *dst, SDL_Surface *src, Uint32 color)
{
	if(SDL_MUSTLOCK(dst)) SDL_LockSurface(dst);
	if(SDL_MUSTLOCK(src)) SDL_LockSurface(src);
	
	const int bytePPdst = dst->format->BytesPerPixel;
	const int pitchdst = dst->pitch;
	const int bytePPsrc = src->format->BytesPerPixel;
	const int pitchsrc = src->pitch;

    Uint32 colorkey;

#if SDL_VERSION_ATLEAST(2, 0, 0)
    SDL_GetColorKey(dst, &colorkey);
#else
    colorkey = dst->format->colorkey;
#endif
	
	for(int y=0;y<dst->h;y++)
	{
		for(int x=0;x<dst->w;x++)
		{
			Uint8 r,g,b,a;
			
			r = g = b = a = 255;
			
			byte *srcPtr = (byte*)src->pixels;
			srcPtr += (pitchsrc*y+x*bytePPsrc);
			
            if(colorkey == *srcPtr)
			{			
			  Uint32 newValue = SDL_MapRGBA(dst->format, r, g, b, a);
			
			  byte *dstPtr = (byte*)dst->pixels;
			  dstPtr += (pitchdst*y+x*bytePPdst);
			
			  memcpy( dstPtr, &newValue, bytePPdst );			  
			}
		}
	}
	if(SDL_MUSTLOCK(src)) SDL_UnlockSurface(src);
	if(SDL_MUSTLOCK(dst)) SDL_UnlockSurface(dst);
}
コード例 #13
0
ファイル: BSurfaceSDL.cpp プロジェクト: somaen/Wintermute-git
void CBSurfaceSDL::GenAlphaMask(SDL_Surface *surface) {
	delete[] m_AlphaMask;
	m_AlphaMask = NULL;
	if (!surface) return;

	SDL_LockSurface(surface);

	bool hasColorKey;
	Uint32 colorKey;
	Uint8 ckRed, ckGreen, ckBlue;
	if (SDL_GetColorKey(surface, &colorKey) == 0) {
		hasColorKey = true;
		SDL_GetRGB(colorKey, surface->format, &ckRed, &ckGreen, &ckBlue);
	} else hasColorKey = false;

	m_AlphaMask = new byte[surface->w * surface->h];

	bool hasTransparency = false;
	for (int y = 0; y < surface->h; y++) {
		for (int x = 0; x < surface->w; x++) {
			Uint32 pixel = GetPixel(surface, x, y);

			Uint8 r, g, b, a;
			SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a);

			if (hasColorKey && r == ckRed && g == ckGreen && b == ckBlue)
				a = 0;

			m_AlphaMask[y * surface->w + x] = a;
			if (a < 255) hasTransparency = true;
		}
	}

	SDL_UnlockSurface(surface);

	if (!hasTransparency) {
		delete[] m_AlphaMask;
		m_AlphaMask = NULL;
	}
}
コード例 #14
0
ファイル: blitter.cpp プロジェクト: Tkachov/ceu_pingus
SDL_Surface*
Blitter::scale_surface(SDL_Surface* surface, int width, int height)
{
  int i;
  int j;
  unsigned char *pixels;
  unsigned char *new_pixels;
  int x;
  int bpp;
  int new_pitch;
  SDL_Surface* new_surface;

  bpp = surface->format->BytesPerPixel;
  if (bpp == 1) {
    SDL_Palette* pal = SDL_AllocPalette(256);

    Uint32 ckey;
    int useckey = 0;

    useckey = SDL_GetColorKey(surface, &ckey) == 0;

    new_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);

    SDL_LockSurface(surface);
    SDL_LockSurface(new_surface);

    pixels     = static_cast<unsigned char*>(surface->pixels);
    new_pixels = static_cast<unsigned char*>(new_surface->pixels);
    new_pitch  = new_surface->pitch;

    memcpy(pal->colors, surface->format->palette->colors, sizeof(SDL_Color) * 256);

    for (i = 0; i < height; ++i) {
      x = i * new_pitch;
      for (j = 0; j < width; ++j) {
        new_pixels[x] = pixels[(i * surface->h / height) * surface->pitch + j * surface->w / width];
        ++x;
      }
    }

    SDL_UnlockSurface(surface);
    SDL_UnlockSurface(new_surface);

    SDL_SetSurfacePalette(new_surface, pal);
    if (useckey) 
    {
      SDL_SetColorKey(new_surface, SDL_TRUE, ckey);
      SDL_SetSurfaceRLE(new_surface, SDL_TRUE);
    }
  } else {
    int ix, iy;
    float fx, fy, fz;
    unsigned char *p1, *p2, *p3, *p4;

    new_surface = SDL_CreateRGBSurface(0, width, height, surface->format->BitsPerPixel,
                                       surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);

    SDL_LockSurface(surface);
    SDL_LockSurface(new_surface);

    pixels     = static_cast<unsigned char*>(surface->pixels);
    new_pixels = static_cast<unsigned char*>(new_surface->pixels);
    new_pitch = new_surface->pitch;

    for (i = 0; i < height; ++i) {
      x = i * new_pitch;
      fy = static_cast<float>(i) * static_cast<float>(surface->h) / static_cast<float>(height);
      iy = static_cast<int>(fy);
      fy -= static_cast<float>(iy);
      for (j = 0; j < width; ++j) {
        fx = static_cast<float>(j) * static_cast<float>(surface->w) / static_cast<float>(width);
        ix = static_cast<int>(fx);
        fx -= static_cast<float>(ix);
        fz = (fx + fy) / 2;

        p1 = &pixels[iy * surface->pitch + ix * bpp];
        p2 = (iy != surface->h - 1) ?
          &pixels[(iy + 1) * surface->pitch + ix * bpp] : p1;
        p3 = (ix != surface->w - 1) ?
          &pixels[iy * surface->pitch + (ix + 1) * bpp] : p1;
        p4 = (iy != surface->h - 1 && ix != surface->w - 1) ?
          &pixels[(iy + 1) * surface->pitch + (ix + 1) * bpp] : p1;

        new_pixels[x + 0] = static_cast<unsigned char>(
          (static_cast<float>(p1[0]) * (1 - fy) + static_cast<float>(p2[0]) * fy +
           static_cast<float>(p1[0]) * (1 - fx) + static_cast<float>(p3[0]) * fx +
           static_cast<float>(p1[0]) * (1 - fz) + static_cast<float>(p4[0]) * fz) / 3.0 + .5);
        new_pixels[x + 1] = static_cast<unsigned char>(
          (static_cast<float>(p1[1]) * (1 - fy) + static_cast<float>(p2[1]) * fy +
           static_cast<float>(p1[1]) * (1 - fx) + static_cast<float>(p3[1]) * fx +
           static_cast<float>(p1[1]) * (1 - fz) + static_cast<float>(p4[1]) * fz) / 3.0 + .5);
        new_pixels[x + 2] = static_cast<unsigned char>(
          (static_cast<float>(p1[2]) * (1 - fy) + static_cast<float>(p2[2]) * fy +
           static_cast<float>(p1[2]) * (1 - fx) + static_cast<float>(p3[2]) * fx +
           static_cast<float>(p1[2]) * (1 - fz) + static_cast<float>(p4[2]) * fz) / 3.0 + .5);
        if (bpp == 4) {
          new_pixels[x + 3] = static_cast<unsigned char>(
            (static_cast<float>(p1[3]) * (1 - fy) + static_cast<float>(p2[3]) * fy +
             static_cast<float>(p1[3]) * (1 - fx) + static_cast<float>(p3[3]) * fx +
             static_cast<float>(p1[3]) * (1 - fz) + static_cast<float>(p4[3]) * fz) / 3.0 + .5);
        }
        x += bpp;
      }
    }

    SDL_UnlockSurface(surface);
    SDL_UnlockSurface(new_surface);
  }

  return new_surface;
}
コード例 #15
0
ファイル: SDL_render_sw.c プロジェクト: ifzz/exsdk
static int
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
                const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
{
    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
    SDL_Rect final_rect, tmp_rect;
    SDL_Surface *surface_rotated, *surface_scaled;
    Uint32 colorkey;
    int retval, dstwidth, dstheight, abscenterx, abscentery;
    double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;

    if (!surface) {
        return -1;
    }

    if (renderer->viewport.x || renderer->viewport.y) {
        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
    } else {
        final_rect.x = (int)dstrect->x;
        final_rect.y = (int)dstrect->y;
    }
    final_rect.w = (int)dstrect->w;
    final_rect.h = (int)dstrect->h;

    surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel,
                                          src->format->Rmask, src->format->Gmask,
                                          src->format->Bmask, src->format->Amask );
    if (surface_scaled) {
        SDL_GetColorKey(src, &colorkey);
        SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey);
        tmp_rect = final_rect;
        tmp_rect.x = 0;
        tmp_rect.y = 0;

        retval = SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect);
        if (!retval) {
            SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle);
            surface_rotated = SDLgfx_rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
            if(surface_rotated) {
                /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
                abscenterx = final_rect.x + (int)center->x;
                abscentery = final_rect.y + (int)center->y;
                /* Compensate the angle inversion to match the behaviour of the other backends */
                sangle = -sangle;

                /* Top Left */
                px = final_rect.x - abscenterx;
                py = final_rect.y - abscentery;
                p1x = px * cangle - py * sangle + abscenterx;
                p1y = px * sangle + py * cangle + abscentery;

                /* Top Right */
                px = final_rect.x + final_rect.w - abscenterx;
                py = final_rect.y - abscentery;
                p2x = px * cangle - py * sangle + abscenterx;
                p2y = px * sangle + py * cangle + abscentery;

                /* Bottom Left */
                px = final_rect.x - abscenterx;
                py = final_rect.y + final_rect.h - abscentery;
                p3x = px * cangle - py * sangle + abscenterx;
                p3y = px * sangle + py * cangle + abscentery;

                /* Bottom Right */
                px = final_rect.x + final_rect.w - abscenterx;
                py = final_rect.y + final_rect.h - abscentery;
                p4x = px * cangle - py * sangle + abscenterx;
                p4y = px * sangle + py * cangle + abscentery;

                tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
                tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
                tmp_rect.w = dstwidth;
                tmp_rect.h = dstheight;

                retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect);
                SDL_FreeSurface(surface_scaled);
                SDL_FreeSurface(surface_rotated);
                return retval;
            }
        }
        return retval;
    }

    return -1;
}
コード例 #16
0
ファイル: SDL_render_sw.c プロジェクト: 0-wiz-0/mame
static int
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
                const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
{
    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    SDL_Surface *src = (SDL_Surface *) texture->driverdata;
    SDL_Rect final_rect, tmp_rect;
    SDL_Surface *surface_rotated, *surface_scaled;
    int retval, dstwidth, dstheight, abscenterx, abscentery;
    double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;

    if (!surface) {
        return -1;
    }

    if (renderer->viewport.x || renderer->viewport.y) {
        final_rect.x = (int)(renderer->viewport.x + dstrect->x);
        final_rect.y = (int)(renderer->viewport.y + dstrect->y);
    } else {
        final_rect.x = (int)dstrect->x;
        final_rect.y = (int)dstrect->y;
    }
    final_rect.w = (int)dstrect->w;
    final_rect.h = (int)dstrect->h;

    /* SDLgfx_rotateSurface doesn't accept a source rectangle, so crop and scale if we need to */
    tmp_rect = final_rect;
    tmp_rect.x = 0;
    tmp_rect.y = 0;
    if (srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0) {
        surface_scaled = src; /* but if we don't need to, just use the original */
        retval = 0;
    } else {
        SDL_Surface *blit_src = src;
        Uint32 colorkey;
        SDL_BlendMode blendMode;
        Uint8 alphaMod, r, g, b;
        SDL_bool cloneSource = SDL_FALSE;

        surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel,
                                              src->format->Rmask, src->format->Gmask,
                                              src->format->Bmask, src->format->Amask );
        if (!surface_scaled) {
            return -1;
        }

        /* copy the color key, alpha mod, blend mode, and color mod so the scaled surface behaves like the source */
        if (SDL_GetColorKey(src, &colorkey) == 0) {
            SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey);
            cloneSource = SDL_TRUE;
        }
        SDL_GetSurfaceAlphaMod(src, &alphaMod); /* these will be copied to surface_scaled below if necessary */
        SDL_GetSurfaceBlendMode(src, &blendMode);
        SDL_GetSurfaceColorMod(src, &r, &g, &b);

        /* now we need to blit the src into surface_scaled. since we want to copy the colors from the source to
         * surface_scaled rather than blend them, etc. we'll need to disable the blend mode, alpha mod, etc.
         * but we don't want to modify src (in case it's being used on other threads), so we'll need to clone it
         * before changing the blend options
         */
        cloneSource |= blendMode != SDL_BLENDMODE_NONE || (alphaMod & r & g & b) != 255;
        if (cloneSource) {
            blit_src = SDL_ConvertSurface(src, src->format, src->flags); /* clone src */
            if (!blit_src) {
                SDL_FreeSurface(surface_scaled);
                return -1;
            }
            SDL_SetSurfaceAlphaMod(blit_src, 255); /* disable all blending options in blit_src */
            SDL_SetSurfaceBlendMode(blit_src, SDL_BLENDMODE_NONE);
            SDL_SetColorKey(blit_src, 0, 0);
            SDL_SetSurfaceColorMod(blit_src, 255, 255, 255);
            SDL_SetSurfaceRLE(blit_src, 0); /* don't RLE encode a surface we'll only use once */

            SDL_SetSurfaceAlphaMod(surface_scaled, alphaMod); /* copy blending options to surface_scaled */
            SDL_SetSurfaceBlendMode(surface_scaled, blendMode);
            SDL_SetSurfaceColorMod(surface_scaled, r, g, b);
        }

        retval = SDL_BlitScaled(blit_src, srcrect, surface_scaled, &tmp_rect);
        if (blit_src != src) {
            SDL_FreeSurface(blit_src);
        }
    }

    if (!retval) {
        SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
        surface_rotated = SDLgfx_rotateSurface(surface_scaled, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
        if(surface_rotated) {
            /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
            abscenterx = final_rect.x + (int)center->x;
            abscentery = final_rect.y + (int)center->y;
            /* Compensate the angle inversion to match the behaviour of the other backends */
            sangle = -sangle;

            /* Top Left */
            px = final_rect.x - abscenterx;
            py = final_rect.y - abscentery;
            p1x = px * cangle - py * sangle + abscenterx;
            p1y = px * sangle + py * cangle + abscentery;

            /* Top Right */
            px = final_rect.x + final_rect.w - abscenterx;
            py = final_rect.y - abscentery;
            p2x = px * cangle - py * sangle + abscenterx;
            p2y = px * sangle + py * cangle + abscentery;

            /* Bottom Left */
            px = final_rect.x - abscenterx;
            py = final_rect.y + final_rect.h - abscentery;
            p3x = px * cangle - py * sangle + abscenterx;
            p3y = px * sangle + py * cangle + abscentery;

            /* Bottom Right */
            px = final_rect.x + final_rect.w - abscenterx;
            py = final_rect.y + final_rect.h - abscentery;
            p4x = px * cangle - py * sangle + abscenterx;
            p4y = px * sangle + py * cangle + abscentery;

            tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
            tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
            tmp_rect.w = dstwidth;
            tmp_rect.h = dstheight;

            retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect);
            SDL_FreeSurface(surface_rotated);
        }
    }

    if (surface_scaled != src) {
        SDL_FreeSurface(surface_scaled);
    }
    return retval;
}
コード例 #17
0
ファイル: SDL_render.c プロジェクト: ryanzhao006/IOSAVDecode
SDL_Texture *
SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
{
    const SDL_PixelFormat *fmt;
    SDL_bool needAlpha;
    Uint32 i;
    Uint32 format;
    SDL_Texture *texture;

    CHECK_RENDERER_MAGIC(renderer, NULL);

    if (!surface) {
        SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
        return NULL;
    }

    /* See what the best texture format is */
    fmt = surface->format;
    if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
        needAlpha = SDL_TRUE;
    } else {
        needAlpha = SDL_FALSE;
    }
    format = renderer->info.texture_formats[0];
    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
        if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
                SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
            format = renderer->info.texture_formats[i];
            break;
        }
    }

    texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
                                surface->w, surface->h);
    if (!texture) {
        return NULL;
    }

    if (format == surface->format->format) {
        if (SDL_MUSTLOCK(surface)) {
            SDL_LockSurface(surface);
            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
            SDL_UnlockSurface(surface);
        } else {
            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
        }
    } else {
        SDL_PixelFormat *dst_fmt;
        SDL_Surface *temp = NULL;

        /* Set up a destination surface for the texture update */
        dst_fmt = SDL_AllocFormat(format);
        temp = SDL_ConvertSurface(surface, dst_fmt, 0);
        SDL_FreeFormat(dst_fmt);
        if (temp) {
            SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
            SDL_FreeSurface(temp);
        } else {
            SDL_DestroyTexture(texture);
            return NULL;
        }
    }

    {
        Uint8 r, g, b, a;
        SDL_BlendMode blendMode;

        SDL_GetSurfaceColorMod(surface, &r, &g, &b);
        SDL_SetTextureColorMod(texture, r, g, b);

        SDL_GetSurfaceAlphaMod(surface, &a);
        SDL_SetTextureAlphaMod(texture, a);

        if (SDL_GetColorKey(surface, NULL) == 0) {
            /* We converted to a texture with alpha format */
            SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
        } else {
            SDL_GetSurfaceBlendMode(surface, &blendMode);
            SDL_SetTextureBlendMode(texture, blendMode);
        }
    }
    return texture;
}
コード例 #18
0
ファイル: colour_key_conversion_test.c プロジェクト: ejrh/hex
int main(int argc, char *argv[]) {
    int w = 5, h = 5;
    SDL_Window *window;
    SDL_Renderer *renderer;
    SDL_Surface *background;
    SDL_Rect bg_rect = { 0, 0, 12, 12 };
    SDL_Surface *surface;
    SDL_Rect tgt_rect = { 0, 0, 5, 5 };
    Uint32 pf;
    SDL_Surface *new_surface;
    SDL_Rect tgt_rect2 = { 6, 0, 5, 5 };
    SDL_Texture *bg_tex;
    Uint32 first_pixel;
    Uint8 r,g,b,a;
    Uint32 colour_key;
    int waiting;

    SDL_Init(SDL_INIT_VIDEO);

    window = SDL_CreateWindow("Color key conversion test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 100, 100, 0);
    renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_RenderSetScale(renderer, 8, 8);

    // create green background surface
    background = SDL_CreateRGBSurface(0, 12, 12, 32, 0,0,0,0);
    SDL_FillRect(background, &bg_rect, SDL_MapRGB(background->format, 100,200,100));

    // create 16-bit surface
    surface = SDL_CreateRGBSurfaceFrom(pixel_data, w, h, 16, w*2, 0x0000f800,0x000007e0,0x0000001f,0);
    SDL_SetColorKey(surface, SDL_TRUE, 0xB54A);

    // blit original surface to left hand side of background
    SDL_BlitSurface(surface, NULL, background, &tgt_rect);

    // convert surface to 32-bit (suitable for window)
    pf = SDL_GetWindowPixelFormat(window);
    new_surface = SDL_ConvertSurfaceFormat(surface, pf, 0);

    // blit converted surface to right hand side
    SDL_BlitSurface(new_surface, NULL, background, &tgt_rect2);

    // show everything
    bg_tex = SDL_CreateTextureFromSurface(renderer, background);
    SDL_RenderCopy(renderer, bg_tex, NULL, &bg_rect);
    SDL_RenderPresent(renderer);

    // print value of first pixel
    first_pixel = ((Uint32 *) new_surface->pixels)[0];
    SDL_GetRGBA(first_pixel, new_surface->format, &r,&g,&b,&a);
    printf("First pixel = %08x (%d,%d,%d alpha %d)\n", first_pixel, r,g,b,a);
    // print value of colour key
    SDL_GetColorKey(new_surface, &colour_key);
    SDL_GetRGB(colour_key, new_surface->format, &r,&g,&b);
    printf("colour key  = %08x (%d,%d,%d)\n", colour_key, r,g,b);

    waiting = 1;
    while (waiting) {
        SDL_Event evt;
        SDL_WaitEvent(&evt);
        if (evt.type == SDL_QUIT)
            waiting = 0;
    }

    SDL_FreeSurface(new_surface);
    SDL_FreeSurface(surface);
    SDL_DestroyTexture(bg_tex);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}
コード例 #19
0
ファイル: save.c プロジェクト: beoran/eruta
/* Saves an SDL surface to a png file.
* TODO: support screen formats. 
*/
int sdl_surface_savepng(SDL_Surface * surf, const char * filename) {
  png_bytep       * rows  = NULL;
  png_colorp        pale  = NULL; 
  FILE            * fout  = NULL;
  png_structp       png   = NULL;
  png_infop         info  = NULL;
  int               colortype;
  int               i     = 0;
  Uint8           * tran  = NULL;
  SDL_PixelFormat * fmt   = NULL;
  SDL_Surface     * temp  = NULL;
  
  if (!surf) { return save_fail("Surface was NULL."); }
  if (!filename) { return save_fail("Filename was NULL."); }
    
  rows  =  gymalloc(sizeof(png_bytep)*surf->h);
  if (!rows) { return save_fail("Out of memory."); }
  
  for (i = 0; i < surf->h; i++) { 
    rows[i] = ((Uint8 *)surf->pixels) + i*surf->pitch;
  }
  
  /* Create palette and transparency table if needed. */
  fmt = surf->format;
  if (fmt->palette) {
    pale = malloc(fmt->palette->ncolors * sizeof(png_color));
    if (!pale) {
      savepng_done(rows, fout, png, info, temp, pale, tran);
      return save_fail("Out of memory in saving palette.");
    }    
    for (i = 0; i < fmt->palette->ncolors; i++) {
      pale[i].red    = fmt->palette->colors[i].r;
      pale[i].green  = fmt->palette->colors[i].g;
      pale[i].blue   = fmt->palette->colors[i].b;
    }
    
    if (surf->flags & SDL_SRCCOLORKEY) {
      Uint32 colorkey = 0; 
      SDL_GetColorKey(surf, &colorkey);
      tran = malloc(fmt->palette->ncolors * sizeof(Uint8));
      if(!tran) {
        savepng_done(rows, fout, png, info, temp, pale, tran);
        return save_fail("Out of memory in saving palette transparency.");
      }
      for (i = 0; i < fmt->palette->ncolors; i++) {
        tran[i] = (((unsigned)i) == colorkey) ? 255 : 0;
      }
    }
  }
    
  fout = fopen(filename, "wb");
  if(!fout) {
    savepng_done(rows, fout, png, info, temp, pale, tran);    
    return save_fail("Couldn't open file for writing."); 
  }
  
  png  = png_create_write_struct(PNG_LIBPNG_VER_STRING,  NULL, NULL, NULL);
  if (!png) {
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Couldn't create png_structp");
  }  
  
  info = png_create_info_struct(png);
  if (!info) {
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Couldn't create png_infop");
  }
  
  /* libpng rudely uses longjump to terminate on errors. 
    This in turns causes warning of pissbli clobered variables. Could it suck 
    more? */
  if (setjmp(png->jmpbuf)) {
    /* This give a warning, but it seems to be unavoidable. */
    savepng_done(rows, fout, png, info, temp, pale, tran);
    return save_fail("Error writing png file.");
  }
  
  /* Set file pointer. */
  png_init_io(png, fout);
  
  colortype = sdl_surface_pngcolortype(surf);
  png_set_IHDR(png, info, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, 
               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  
  /* Write palette if needed. */
  if(pale) { 
    png_set_PLTE(png, info, pale, fmt->palette->ncolors);
  }
    
  /* Write transparency table if needed. */
  if (tran) {  
    png_set_tRNS(png, info, tran, fmt->palette->ncolors, NULL);
  }
  
  /* Write the image. */
  png_write_info(png, info);
  png_set_packing(png);
  if(SDL_MUSTLOCK(surf)) {  SDL_LockSurface(surf);  }
  png_write_image(png, rows);
  if(SDL_MUSTLOCK(surf)) { SDL_UnlockSurface(surf); }
  png_write_end(png, info);
  
  
  /* Clean up. */
  savepng_done(rows, fout, png, info, temp, pale, tran);
  return 0;
}
コード例 #20
0
ファイル: ground_map.cpp プロジェクト: Tkachov/ceu_pingus
void
GroundMap::put_alpha_surface(Surface provider, Surface sprovider,
                             int x_pos, int y_pos, int real_x_arg, int real_y_arg)
{
  if (sprovider.get_surface()->format->BitsPerPixel != 8  &&
      sprovider.get_surface()->format->BitsPerPixel != 24 &&
      sprovider.get_surface()->format->BitsPerPixel != 32)
  {
    log_error("Image has wrong color depth: %1%", 
              static_cast<int>(sprovider.get_surface()->format->BitsPerPixel));
    return;
  }

  int swidth  = sprovider.get_width();
  int twidth  = provider.get_width();

  int spitch = sprovider.get_pitch();
  int tpitch = provider.get_pitch();

  int start_x = std::max(0, -x_pos);
  int start_y = std::max(0, -y_pos);

  int end_x = std::min(swidth,  twidth  - x_pos);
  int end_y = std::min(sprovider.get_height(), provider.get_height() - y_pos);

  if (end_x - start_x <= 0 || end_y - start_y <= 0)
    return;

  provider.lock();
  sprovider.lock();

  Uint8* target_buf = static_cast<Uint8*>(provider.get_data());
  Uint8* source_buf = static_cast<Uint8*>(sprovider.get_data());
  Uint32 colorkey;
  if (sprovider.get_surface()->format->BitsPerPixel == 32)
  {
    for (int y = start_y; y < end_y; ++y)
    {
      Uint8* tptr = target_buf + tpitch*(y+y_pos) + 4*(x_pos + start_x);
      Uint8* sptr = source_buf + spitch*y + 4*start_x;

      for (int x = start_x; x < end_x; ++x)
      { 
        if (sptr[3] == 255 && 
            colmap->getpixel(real_x_arg+x, real_y_arg+y) != Groundtype::GP_SOLID)
        {
          tptr[3] = 0;
        }

        tptr += 4;
        sptr += 4;
      }
    }
  }
  else if (SDL_GetColorKey(sprovider.get_surface(), &colorkey) == 0)
  {
    for (int y = start_y; y < end_y; ++y)
    {
      Uint8* tptr = target_buf + tpitch*(y+y_pos) + 4*(x_pos + start_x);
      Uint8* sptr = source_buf + spitch*y + start_x;

      for (int x = start_x; x < end_x; ++x)
      { 
        if (*sptr != colorkey && colmap->getpixel(real_x_arg+x, real_y_arg+y) != Groundtype::GP_SOLID)
        {
          tptr[3] = 0;
        }

        tptr += 4;
        sptr += 1;
      }
    }
  }
  else
  { 
    // opaque source surface, so we can use the same code for 24bpp and indexed
    for (int y = start_y; y < end_y; ++y)
    {
      Uint8* tptr = target_buf + tpitch*(y+y_pos) + 4*(x_pos + start_x);

      for (int x = start_x; x < end_x; ++x)
      { 
        if (colmap->getpixel(real_x_arg+x, real_y_arg+y) != Groundtype::GP_SOLID)
        {
          tptr[3] = 0;
        }
              
        tptr += 4;
      }
    }
  }
  
  sprovider.unlock();
  provider.unlock();
}
コード例 #21
0
ファイル: IMG_savepng.cpp プロジェクト: gradonly/frogatto
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
#ifdef IMPLEMENT_SAVE_PNG
	png_structp png_ptr;
	png_infop info_ptr;
	SDL_PixelFormat *fmt=NULL;
	SDL_Surface *tempsurf=NULL;
	int ret,funky_format;
	unsigned int i;
#if SDL_VERSION_ATLEAST(2, 0, 0)
	SDL_BlendMode temp_blend;
	bool used_blend = false;
#else
	Uint8 temp_alpha;
	bool used_alpha = false;
#endif
	png_colorp palette;
	Uint8 *palette_alpha=NULL;
	png_byte **row_pointers=NULL;
	png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1;
	funky_format=0;
	
	if( !src || !surf) {
		goto savedone; /* Nothing to do. */
	}

	row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*));
	if (!row_pointers) { 
		SDL_SetError("Couldn't allocate memory for rowpointers");
		goto savedone;
	}
	
	png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
	if (!png_ptr){
		SDL_SetError("Couldn't allocate memory for PNG file");
		goto savedone;
	}
	info_ptr= png_create_info_struct(png_ptr);
	if (!info_ptr){
		SDL_SetError("Couldn't allocate image information for PNG file");
		goto savedone;
	}
	/* setup custom writer functions */
	png_set_write_fn(png_ptr,(voidp)src,png_write_data,NULL);

	if (setjmp(png_jmpbuf(png_ptr))){
		SDL_SetError("Unknown error writing PNG");
		goto savedone;
	}

	if(compression>Z_BEST_COMPRESSION)
		compression=Z_BEST_COMPRESSION;

	if(compression == Z_NO_COMPRESSION) // No compression
	{
		png_set_filter(png_ptr,0,PNG_FILTER_NONE);
		png_set_compression_level(png_ptr,Z_NO_COMPRESSION);
	}
        else if(compression<0) // Default compression
		png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION);
        else
		png_set_compression_level(png_ptr,compression);

	fmt=surf->format;
	if(fmt->BitsPerPixel==8){ /* Paletted */
		png_set_IHDR(png_ptr,info_ptr,
			surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE,
			PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);
		palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color));
		if (!palette) {
			SDL_SetError("Couldn't create memory for palette");
			goto savedone;
		}
		for (i=0;i<fmt->palette->ncolors;i++) {
			palette[i].red=fmt->palette->colors[i].r;
			palette[i].green=fmt->palette->colors[i].g;
			palette[i].blue=fmt->palette->colors[i].b;
		}
		png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors);
#if SDL_VERSION_ATLEAST(2, 0, 0)
		Uint32 colorkey; 
		if (SDL_GetColorKey(surf, &colorkey) == 0) {
#else
		if (surf->flags&SDL_SRCCOLORKEY) {
			Uint32 colorkey = fmt->colorkey; 
#endif
			palette_alpha=(Uint8 *)malloc((colorkey+1)*sizeof(Uint8));
			if (!palette_alpha) {
				SDL_SetError("Couldn't create memory for palette transparency");
				goto savedone;
			}
			/* FIXME: memset? */
			for (i=0;i<(colorkey+1);i++) {
				palette_alpha[i]=255;
			}
			palette_alpha[colorkey]=0;
			png_set_tRNS(png_ptr,info_ptr,palette_alpha,colorkey+1,NULL);
		}
	}else{ /* Truecolor */
		if (fmt->Amask) {
			png_set_IHDR(png_ptr,info_ptr,
				surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA,
				PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
		} else {
			png_set_IHDR(png_ptr,info_ptr,
				surf->w,surf->h,8,PNG_COLOR_TYPE_RGB,
				PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,
				PNG_FILTER_TYPE_DEFAULT);
		}
	}
	png_write_info(png_ptr, info_ptr);

	if (fmt->BitsPerPixel==8) { /* Paletted */
		for(i=0;i<surf->h;i++){
			row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
		}
		if(SDL_MUSTLOCK(surf)){
			SDL_LockSurface(surf);
		}
		png_write_image(png_ptr, row_pointers);
		if(SDL_MUSTLOCK(surf)){
			SDL_UnlockSurface(surf);
		}
	}else{ /* Truecolor */
		if(fmt->BytesPerPixel==3){
			if(fmt->Amask){ /* check for 24 bit with alpha */
				funky_format=1;
			}else{
				/* Check for RGB/BGR/GBR/RBG/etc surfaces.*/
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				if(fmt->Rmask!=0xFF0000 
				|| fmt->Gmask!=0x00FF00
				|| fmt->Bmask!=0x0000FF){
#else
				if(fmt->Rmask!=0x0000FF 
				|| fmt->Gmask!=0x00FF00
				|| fmt->Bmask!=0xFF0000){
#endif
					funky_format=1;
				}
			}
		}else if (fmt->BytesPerPixel==4){
			if (!fmt->Amask) { /* check for 32bit but no alpha */
				funky_format=1; 
			}else{
				/* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
				if(fmt->Rmask!=0xFF000000
				|| fmt->Gmask!=0x00FF0000
				|| fmt->Bmask!=0x0000FF00
				|| fmt->Amask!=0x000000FF){
#else
				if(fmt->Rmask!=0x000000FF
				|| fmt->Gmask!=0x0000FF00
				|| fmt->Bmask!=0x00FF0000
				|| fmt->Amask!=0xFF000000){
#endif
					funky_format=1;
				}
			}
		}else{ /* 555 or 565 16 bit color */
			funky_format=1;
		}
		if (funky_format) {
			/* Allocate non-funky format, and copy pixeldata in*/
			if(fmt->Amask){
#if SDL_VERSION_ATLEAST(2, 0, 0)
				tempsurf = SDL_CreateRGBSurface(0, surf->w, surf->h, 24, SURFACE_MASK_WITH_ALPHA);
#else
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, SURFACE_MASK_WITH_ALPHA);
#endif
			}else{
#if SDL_VERSION_ATLEAST(2, 0, 0)
				tempsurf = SDL_CreateRGBSurface(0, surf->w, surf->h, 24, SURFACE_MASK_WITHOUT_ALPHA);
#else
				tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, SURFACE_MASK_WITHOUT_ALPHA);
#endif
			}
			if(!tempsurf){
				SDL_SetError("Couldn't allocate temp surface");
				goto savedone;
			}
#if SDL_VERSION_ATLEAST(2, 0, 0)
			if(SDL_GetSurfaceBlendMode(surf, &temp_blend) == 0){
				used_blend = true;
				SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
			}
#else
			if(surf->flags&SDL_SRCALPHA) {
				temp_alpha = fmt->alpha;
					used_alpha = true;
					SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */
			}
#endif
			if(SDL_BlitSurface(surf, NULL, tempsurf, NULL)!=0){
				SDL_SetError("Couldn't blit surface to temp surface");
				SDL_FreeSurface(tempsurf);
				goto savedone;
			}
#if SDL_VERSION_ATLEAST(2, 0, 0)
			if (used_blend) {
				SDL_SetSurfaceBlendMode(surf, temp_blend); /* Restore blend settings*/
			}
#else
			if(used_alpha) {
					SDL_SetAlpha(surf, SDL_SRCALPHA, (Uint8)temp_alpha); /* Restore alpha settings*/
			}
#endif
			for(i=0;i<tempsurf->h;i++){
				row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch;
			}
			if(SDL_MUSTLOCK(tempsurf)){
				SDL_LockSurface(tempsurf);
			}
			png_write_image(png_ptr, row_pointers);
			if(SDL_MUSTLOCK(tempsurf)){
				SDL_UnlockSurface(tempsurf);
			}
			SDL_FreeSurface(tempsurf);
		} else {
			for(i=0;i<surf->h;i++){
				row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch;
			}
			if(SDL_MUSTLOCK(surf)){
				SDL_LockSurface(surf);
			}
			png_write_image(png_ptr, row_pointers);
			if(SDL_MUSTLOCK(surf)){
				SDL_UnlockSurface(surf);
			}
		}
	}

	png_write_end(png_ptr, NULL);
	ret=0; /* got here, so nothing went wrong. YAY! */

savedone: /* clean up and return */
	png_destroy_write_struct(&png_ptr,&info_ptr);
	if (palette) {
		free(palette);
	}
	if (palette_alpha) {
		free(palette_alpha);
	}
	if (row_pointers) {
		free(row_pointers);
	}
	return ret;
#else
	return -1;
#endif
}