Commits

marcus  committed cef1663

Added (untested) SDL_RWops surface saving support.
Minor cleanups.

  • Participants
  • Parent commits 31383e1
  • Branches pgreloaded

Comments (0)

Files changed (15)

File config/config_win.py

                 incs.append (d.replace ("freetype2\\freetype", "freetype2"))
             else:
                 incs.append (d)
-        self.incdirs = incs
+        self.incdirs = incs

File src/sdl/imagemod.c

     SDL_RWops *rw;
     int autoclose;
     PyObject *sf, *file;
-    char *filename;
 
     if (!PyArg_ParseTuple (args, "O:load_bmp", &file))
         return NULL;
 {
     PyObject *surface, *file;
     SDL_RWops *rw;
-    char *filename;
     int _stat, autoclose;
     
     if (!PyArg_ParseTuple (args, "OO:save_bmp", &surface, &file))

File src/sdl/jpg.c

 #include "jpg.h"
 #include <jpeglib.h>
 
-static int _write_jpeg (char *file_name, unsigned char** image_buffer,
+#define OUTPUT_SIZE 4096
+
+struct dest_mgr
+{
+    struct jpeg_destination_mgr  pub;
+    SDL_RWops                   *rw;
+    Uint8                       buf[OUTPUT_SIZE];
+};
+
+static void _init_jpegdest (j_compress_ptr cinfo);
+static boolean _empty_jpegbuffer (j_compress_ptr cinfo);
+static void _term_jpegdest (j_compress_ptr cinfo);
+static int _write_jpeg (SDL_RWops *rw, unsigned char** image_buffer,
     int image_width, int image_height, int quality);
 
+static void
+_init_jpegdest (j_compress_ptr cinfo)
+{
+    struct dest_mgr *dest = (struct dest_mgr *) cinfo->dest;
+    dest->pub.next_output_byte = dest->buf;
+    dest->pub.free_in_buffer = OUTPUT_SIZE;
+}
+
+static boolean
+_empty_jpegbuffer (j_compress_ptr cinfo)
+{
+    struct dest_mgr *dest = (struct dest_mgr *) cinfo->dest;
+    int size;
+    
+    size = SDL_RWwrite (dest->rw, dest->buf, 1, OUTPUT_SIZE);
+    if (size != OUTPUT_SIZE)
+        return FALSE;
+    dest->pub.next_output_byte = dest->buf;
+    dest->pub.free_in_buffer = OUTPUT_SIZE;
+    return TRUE;
+}
+
+static void
+_term_jpegdest (j_compress_ptr cinfo)
+{
+    struct dest_mgr *dest = (struct dest_mgr *) cinfo->dest;
+    SDL_RWwrite (dest->rw, dest->buf, 1,
+        OUTPUT_SIZE - dest->pub.free_in_buffer);
+}
+
 static int
-_write_jpeg (char *file_name, unsigned char** image_buffer,  int image_width,
+_write_jpeg (SDL_RWops *rw, unsigned char** image_buffer, int image_width,
     int image_height, int quality)
 {
     struct jpeg_compress_struct cinfo;
     struct jpeg_error_mgr jerr;
-    FILE * outfile;
+    struct dest_mgr *dest;
     JSAMPROW row_pointer[1];
     int row_stride;
 
     cinfo.err = jpeg_std_error (&jerr);
     jpeg_create_compress (&cinfo);
 
-    if ((outfile = fopen (file_name, "wb")) == NULL)
-    {
-        SDL_SetError ("could not open %s", file_name);
-        return 0;
-    }
-    jpeg_stdio_dest (&cinfo, outfile);
+    /*jpeg_stdio_dest (&cinfo, outfile);*/
 
     cinfo.image_width = image_width;
     cinfo.image_height = image_height;
     cinfo.input_components = 3;
     cinfo.in_color_space = JCS_RGB;
-  
+
     jpeg_set_defaults (&cinfo);
     jpeg_set_quality (&cinfo, quality, TRUE);
 
+    cinfo.dest = (struct jpeg_destination_mgr *)
+        (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
+            sizeof(struct dest_mgr));
+    if (!cinfo.dest)
+        return 0;
+
+    dest = (struct dest_mgr *) cinfo.dest;
+    dest->pub.init_destination = _init_jpegdest;
+    dest->pub.term_destination = _term_jpegdest;
+    dest->pub.empty_output_buffer = _empty_jpegbuffer;
+    dest->rw = rw;
+    dest->pub.free_in_buffer = 0;
+    dest->pub.next_output_byte = NULL;
+
     jpeg_start_compress (&cinfo, TRUE);
     row_stride = image_width * 3;
 
     }
 
     jpeg_finish_compress (&cinfo);
-    fclose (outfile);
     jpeg_destroy_compress (&cinfo);
     return 1;
 }
 int
 pyg_save_jpeg (SDL_Surface *surface, char *file)
 {
+    SDL_RWops *out;
+
+    if (!surface)
+    {
+        SDL_SetError ("surface argument NULL");
+        return 0;
+    }
+    if (!file)
+    {
+        SDL_SetError ("file argument NULL");
+        return 0;
+    }
+
+    out = SDL_RWFromFile (file, "wb");
+    if (!out)
+        return 0;
+    return pyg_save_jpeg_rw (surface, out, 1);
+}
+
+int
+pyg_save_jpeg_rw (SDL_Surface *surface, SDL_RWops *rw, int freerw)
+{
     static unsigned char** ss_rows;
     static int ss_size;
     static int ss_w, ss_h;
         SDL_SetError ("surface argument NULL");
         return 0;
     }
-    if (!file)
+    if (!rw)
     {
-        SDL_SetError ("file argument NULL");
+        SDL_SetError ("rw argument NULL");
         return 0;
     }
 
         ss_rows[i] = ((unsigned char*)ss_surface->pixels) +
             i * ss_surface->pitch;
     }
-    r = _write_jpeg (file, ss_rows, surface->w, surface->h, 85);
+    r = _write_jpeg (rw, ss_rows, surface->w, surface->h, 85);
 
     free (ss_rows);
     SDL_FreeSurface (ss_surface);
     ss_surface = NULL;
+    if (freerw)
+        SDL_RWclose (rw);
     return r;
 }
 

File src/sdl/jpg.h

 int
 pyg_save_jpeg (SDL_Surface *surface, char *file);
 
+/**
+ * \brief Saves a SDL_Surface as JPG image.
+ *
+ * @param surface The SDL_Surface to save.
+ * @param rw The SDL_RWops to save the surface to.
+ * @param freerw Indicates, whether the SDL_RWops shall be freed.
+ * @return 0 on failure, !0 on success.
+ */
+int
+pyg_save_jpeg_rw (SDL_Surface *surface, SDL_RWops *rw, int freerw);
+
 #endif /* _PYGAME_JPG_H_ */

File src/sdl/pgpng.h

 int
 pyg_save_png (SDL_Surface *surface, char *file);
 
+/**
+ * \brief Saves a SDL_Surface as PNG image.
+ *
+ * @param surface The SDL_Surface to save.
+ * @param rw The SDL_RWops to save the surface to.
+ * @param freerw Indicates, whether the SDL_RWops shall be freed.
+ * @return 0 on failure, !0 on success.
+ */
+int
+pyg_save_png_rw (SDL_Surface *surface, SDL_RWops *rw, int freerw);
+
 #endif /* _PYGAME_PNG_H_ */

File src/sdl/png.c

 #include <png.h>
 #include "pgpng.h"
 
-static int _write_png (char *file_name, png_bytep *rows, int w, int h,
+static void _write_data (png_structp png_ptr, png_bytep data,
+    png_size_t length);
+static int _write_png (SDL_RWops *rw, png_bytep *rows, int w, int h,
     int colortype, int bitdepth);
 
+static void
+_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+    SDL_RWops* dst = (SDL_RWops*) png_get_io_ptr (png_ptr);
+    SDL_RWwrite(dst, data, 1, length);
+} 
+
 static int
-_write_png (char *file_name, png_bytep *rows, int w, int h, int colortype,
+_write_png (SDL_RWops *rw, png_bytep *rows, int w, int h, int colortype,
     int bitdepth)
 {
     png_structp png_ptr;
     png_infop info_ptr;
-    FILE *fp = NULL;
     char *doing = "open for writing";
 
-    if (!(fp = fopen (file_name, "wb")))
-        goto fail;
-
     doing = "create png write struct";
     if (!(png_ptr = png_create_write_struct
           (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
-    {
-        fclose (fp);
         goto fail;
-    }
+
     doing = "create png info struct";
     if (!(info_ptr = png_create_info_struct (png_ptr)))
-    {
-        fclose (fp);
         goto fail;
-    }
+
     if (setjmp (png_jmpbuf (png_ptr)))
-    {
-        fclose (fp);
         goto fail;
-    }
+
     doing = "init IO";
-    png_init_io (png_ptr, fp);
+    png_set_write_fn (png_ptr, rw, png_write_data, NULL);
 
     doing = "write header";
     png_set_IHDR (png_ptr, info_ptr, (png_uint_32)w, (png_uint_32)h,
     png_write_end (png_ptr, NULL);
 
     doing = "closing file";
-    if(0 != fclose (fp))
-        goto fail;
-    return 0;
+    return 1;
 
 fail:
     SDL_SetError ("could not %s", doing);
 int
 pyg_save_png (SDL_Surface *surface, char *file)
 {
+    SDL_RWops *out;
+
+    if (!surface)
+    {
+        SDL_SetError ("surface argument NULL");
+        return 0;
+    }
+    if (!file)
+    {
+        SDL_SetError ("file argument NULL");
+        return 0;
+    }
+    out = SDL_RWFromFile (file, "wb");
+    if (!out)
+        return 0;
+    return pyg_save_png_rw (surface, out, 1);
+}
+
+int
+pyg_save_png_rw (SDL_Surface *surface, SDL_RWops *rw, int freerw)
+{
     static unsigned char** ss_rows;
     static int ss_size;
     static int ss_w, ss_h;
         SDL_SetError ("surface argument NULL");
         return 0;
     }
-    if (!file)
+    if (!rw)
     {
-        SDL_SetError ("file argument NULL");
+        SDL_SetError ("rw argument NULL");
         return 0;
     }
 
     free (ss_rows);
     SDL_FreeSurface (ss_surface);
     ss_surface = NULL;
+    if (freerw)
+        SDL_RWclose (rw);
     return r;
 }
 

File src/sdl/surface.c

 {
     SDL_Surface *surface;
     PyObject *file;
-    char *filename, *type = NULL;
+    char *type = NULL;
     int retval;
+    SDL_RWops *rw;
+    int autoclose;
 
     if (!PyArg_ParseTuple (args, "O|s", &file, &type))
         return NULL;
 
     surface = ((PySDLSurface*)self)->surface;
 
-    /* TODO: full RWops support for all types! */
-    if (IsTextObj (file))
-    {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return NULL;
+    rw = PyRWops_NewRW (file, &autoclose);
+    if (!rw)
+        return NULL;
+    
+    Py_BEGIN_ALLOW_THREADS;
+    retval = pyg_sdlsurface_save_rw (surface, rw, type, autoclose);
+    Py_END_ALLOW_THREADS;
         
-        Py_BEGIN_ALLOW_THREADS;
-        retval = pyg_sdlsurface_save (surface, filename, type);
-        Py_END_ALLOW_THREADS;
-        
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops* rw;
-        int autoclose;
-        
-        /* If the type is NULL, we assume TGA saving. */
-        if (!type)
-            type = "TGA";
-
-        rw = PyRWops_NewRW (file, &autoclose);
-        if (!rw)
-            return NULL;
-        Py_BEGIN_ALLOW_THREADS;
-        retval = pyg_sdlsurface_save_rw (surface, rw, type);
-        Py_END_ALLOW_THREADS;
-        
-        if (!autoclose)
-            PyRWops_Close (rw, autoclose);
-    }
-    else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by PyObject_AsFileDescriptor() */
-#endif
-        PyErr_SetString (PyExc_TypeError,
-            "file must be file-like object or a string");
-        return NULL;
-    }
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
     
     if (!retval)
     {

File src/sdl/surface.h

     int blendargs);
 
 int pyg_sdlsurface_save (SDL_Surface *surface, char *filename, char *type);
-int pyg_sdlsurface_save_rw (SDL_Surface *surface, SDL_RWops *rw, char *type);
+int pyg_sdlsurface_save_rw (SDL_Surface *surface, SDL_RWops *rw, char *type,
+    int freerw);
 
 int
 pyg_sdlsoftware_blit (SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst,

File src/sdl/surface_save.c

 pyg_sdlsurface_save (SDL_Surface *surface, char *filename, char *type)
 {    
     size_t len;
-    int retval;
     SDL_Surface *tmpsf = NULL;
+    SDL_RWops *rw;
 
     if (!surface)
     {
         }
         type = filename + (len - 3);
     }
-    
-    /* Convert an OpenGL surface on demand. */
-    if (surface->flags & SDL_OPENGL)
-    {
-        /* TODO: _convert_opengl_sdl() acquires the video surface -
-         * is this correct? */
-        tmpsf = _convert_opengl_sdl ();
-        if (!tmpsf)
-            return 0;
-        surface = tmpsf;
-    }
 
     len = strlen (type);
     if (len < 3 || len > 4)
             SDL_FreeSurface (tmpsf);
         return 0;
     }
-    
-    if (len == 3)
-    {
-        /* Can be BMP, TGA, PNG, JPG */
-        if ((type[0] == 'B' || type[0] == 'b') &&
-            (type[1] == 'M' || type[1] == 'm') &&
-            (type[2] == 'P' || type[2] == 'p'))
-        {
-            retval = SDL_SaveBMP (surface, filename);
-        }
-        else if ((type[0] == 'T' || type[0] == 't') &&
-            (type[1] == 'G' || type[1] == 'g') &&
-            (type[2] == 'A' || type[2] == 'a'))
-        {
-            /* TGA saving */
-            retval = pyg_save_tga (surface, filename, 1);
-        }
-#ifdef HAVE_PNG
-        else if ((type[0] == 'P' || type[0] == 'p') &&
-            (type[1] == 'N' || type[1] == 'n') &&
-            (type[2] == 'G' || type[2] == 'g'))
-        {
-            /* PNG saving. */
-            retval = pyg_save_png (surface, filename);
-        }
-#endif /* HAVE_PNG */
-#ifdef HAVE_JPEG
-        else if ((type[0] == 'J' || type[0] == 'j') &&
-            (type[1] == 'P' || type[1] == 'p') &&
-            (type[2] == 'G' || type[2] == 'g'))
-        {
-            /* JPG saving */
-            retval = pyg_save_jpeg (surface, filename);
-        }
-#endif /* HAVE_JPEG */
-        else
-        {
-            SDL_SetError ("unknown file type");
-            if (tmpsf)
-                SDL_FreeSurface (tmpsf);
-            return 0;
-        }
-    }
-    else
-    {
-#ifdef HAVE_JPEG
-        /* JPEG */
-        if ((type[0] == 'J' || type[0] == 'j') &&
-            (type[1] == 'P' || type[1] == 'p') &&
-            (type[2] == 'E' || type[2] == 'e') &&
-            (type[3] == 'G' || type[3] == 'g'))
-        {
-            retval = pyg_save_jpeg (surface, filename);
-        }
-        else
-#endif /* HAVE_JPEG */
-        {
-            SDL_SetError ("unknown file type");
-            if (tmpsf)
-                SDL_FreeSurface (tmpsf);
-            return 0;
-        }
-    }
-    return retval;
+
+    rw = SDL_RWFromFile (filename, "wb");
+    if (!rw)
+        return 0;
+
+    return pyg_sdlsurface_save_rw (surface, rw, type, 1);
 }
 
 int
-pyg_sdlsurface_save_rw (SDL_Surface *surface, SDL_RWops *rw, char *type)
+pyg_sdlsurface_save_rw (SDL_Surface *surface, SDL_RWops *rw, char *type,
+    int freerw)
 {
     int retval;
     size_t len;
         SDL_SetError ("unknown file type");
         return 0;
     }
-
+    
     /* Convert an OpenGL surface on demand. */
     if (surface->flags & SDL_OPENGL)
     {
 
     if (len == 3)
     {
-        /* Can be TGA only at the moment :-/ */
-        if ((type[0] == 'T' || type[0] == 't') &&
+        /* Can be BMP, TGA, PNG, JPG */
+        if ((type[0] == 'B' || type[0] == 'b') &&
+            (type[1] == 'M' || type[1] == 'm') &&
+            (type[2] == 'P' || type[2] == 'p'))
+        {
+            retval = SDL_SaveBMP_RW (surface, rw, freerw);
+        }
+        else if ((type[0] == 'T' || type[0] == 't') &&
             (type[1] == 'G' || type[1] == 'g') &&
             (type[2] == 'A' || type[2] == 'a'))
         {
             /* TGA saving */
-            retval = pyg_save_tga_rw (surface, rw, 1);
+            retval = pyg_save_tga_rw (surface, rw, 1, freerw);
         }
+#ifdef HAVE_PNG
+        else if ((type[0] == 'P' || type[0] == 'p') &&
+            (type[1] == 'N' || type[1] == 'n') &&
+            (type[2] == 'G' || type[2] == 'g'))
+        {
+            /* PNG saving. */
+            retval = pyg_save_png_rw (surface, rw, freerw);
+        }
+#endif /* HAVE_PNG */
+#ifdef HAVE_JPEG
+        else if ((type[0] == 'J' || type[0] == 'j') &&
+            (type[1] == 'P' || type[1] == 'p') &&
+            (type[2] == 'G' || type[2] == 'g'))
+        {
+            /* JPG saving */
+            retval = pyg_save_jpeg_rw (surface, rw, freerw);
+        }
+#endif /* HAVE_JPEG */
         else
         {
-            SDL_SetError ("unsupported file type for RWops saving");
+            SDL_SetError ("unknown file type");
             if (tmpsf)
                 SDL_FreeSurface (tmpsf);
             return 0;
     }
     else
     {
-        SDL_SetError ("unknown file type");
-        if (tmpsf)
-            SDL_FreeSurface (tmpsf);
-        return 0;
+#ifdef HAVE_JPEG
+        /* JPEG */
+        if ((type[0] == 'J' || type[0] == 'j') &&
+            (type[1] == 'P' || type[1] == 'p') &&
+            (type[2] == 'E' || type[2] == 'e') &&
+            (type[3] == 'G' || type[3] == 'g'))
+        {
+            retval = pyg_save_jpeg_rw (surface, rw, freerw);
+        }
+        else
+#endif /* HAVE_JPEG */
+        {
+            SDL_SetError ("unknown file type");
+            if (tmpsf)
+                SDL_FreeSurface (tmpsf);
+            return 0;
+        }
     }
+
     return retval;
 }

File src/sdl/tga.c

 }
 
 int
-pyg_save_tga_rw (SDL_Surface *surface, SDL_RWops *out, int rle)
+pyg_save_tga_rw (SDL_Surface *surface, SDL_RWops *out, int rle, int freerw)
 {
     SDL_Surface *linebuf = NULL;
     int alpha = 0;
     if (surf_flags & SDL_SRCCOLORKEY)
         SDL_SetColorKey (surface, SDL_SRCCOLORKEY, surface->format->colorkey);
 
+    if (freerw)
+        SDL_RWclose (out);
+
 error:
     if (rlebuf)
         free (rlebuf);
     SDL_FreeSurface (linebuf);
+    
     return 0;
 }
 
         return 0;
     }
 
-
     out = SDL_RWFromFile (file, "wb");
     if (!out)
         return 0;
 
-    ret = pyg_save_tga_rw (surface, out, rle);
+    ret = pyg_save_tga_rw (surface, out, rle, 1);
     SDL_RWclose (out);
     return ret;
 }

File src/sdl/tga.h

  * @param out The SDL_RWops to save the SDL_Surface to.
  * @param rle 0, if run length encoding should be disabled, !0, if it should
  * be used.
+ * @param freerw Indicates, whether the SDL_RWops shall be freed.
  * @return 0 on failure, !0 on success.
  */
 int
-pyg_save_tga_rw (SDL_Surface *surface, SDL_RWops *out, int rle);
+pyg_save_tga_rw (SDL_Surface *surface, SDL_RWops *out, int rle, int freerw);
 
 /**
  * \brief Saves a SDL_Surface as TGA image.

File src/sdlext/scrap_x11.c

      */
     if (!scrap_lost_x11 ())
     {
-        char *fmt, *value;
+        char *fmt;
 
         fmt = _atom_to_string (format);
         /* TODO */

File src/sdlimage/imagemod.c

 static PyObject*
 _image_load (PyObject *self, PyObject *args)
 {
-    char *filename, *type = NULL;
+    char *type = NULL;
     SDL_Surface *surface = NULL;
     PyObject *sf, *file;
     SDL_RWops *rw;
 
     rw = PyRWops_NewRO (file, &autoclose);
     if (!rw)
-        return -1;
+        return NULL;
 
     if (type)
     {

File src/sdlmixer/chunk.c

 static int
 _chunk_init (PyObject *self, PyObject *args, PyObject *kwds)
 {
-    char *filename;
     PyObject *file;
     Mix_Chunk *chunk;
     SDL_RWops *rw;

File src/sdlmixer/music.c

 _music_init (PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyObject *file;
-    char *filename;
     Mix_Music *music;
     SDL_RWops *rw;
     int autoclose;