This looks like a lot but its a few small changes.
[blender.git] / source / blender / imbuf / intern / png.c
similarity index 52%
rename from source/blender/imbuf/intern/png_decode.c
rename to source/blender/imbuf/intern/png.c
index 3f9f393627080111a5af6f1a87bb0a6e15416cd0..d8ec1a293dc5addc94b2f60bf423160f60ea6cc0 100644 (file)
  * $Id$
  */
 
+
 #include "png.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#ifdef _WIN32
+#ifdef WIN32
 #include "BLI_winstuff.h"
 #endif
 #include "BLI_blenlib.h"
 #include "IMB_cmap.h"
 #include "IMB_png.h"
 
+typedef struct PNGReadStruct {
+        unsigned char *data;
+        unsigned int size;
+        unsigned int seek;
+}PNGReadStruct;
 
+static void ReadData( png_structp png_ptr, png_bytep data, png_size_t length);
+static void WriteData( png_structp png_ptr, png_bytep data, png_size_t length);
+static void Flush( png_structp png_ptr);
 
-static int checkpng(unsigned char *mem)
+int imb_is_a_png(void *mem)
 {
-       int ret_val = 0;
+        int ret_val = 0;
 
-       if (mem) {
-               ret_val = !png_sig_cmp(mem, 0, 8);
-       }
+        if (mem) {
+                ret_val = !png_sig_cmp(mem, 0, 8);
+        }
 
-       return(ret_val);        
+        return(ret_val);
 }
 
-int imb_is_a_png(void *buf) {
-       
-       return checkpng(buf);
+static void Flush(png_structp png_ptr) 
+{ 
 }
 
-typedef struct PNGReadStruct {
-       unsigned char *data;
-       unsigned int size;
-       unsigned int seek;
-}PNGReadStruct;
+static void WriteData( png_structp png_ptr, png_bytep data, png_size_t length)
+{
+       ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr);
+
+       // if buffer is to small increase it.
+       while (ibuf->encodedsize + length > ibuf->encodedbuffersize) {
+               imb_enlargeencodedbufferImBuf(ibuf);
+       }
+
+       memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length);
+       ibuf->encodedsize += length;
+}
 
-static void
-ReadData(
-    png_structp png_ptr,
-    png_bytep data,
-    png_size_t length);
-
-static void
-ReadData(
-    png_structp png_ptr,
-    png_bytep data,
-    png_size_t length)
+static void ReadData( png_structp png_ptr, png_bytep data, png_size_t length)
 {
        PNGReadStruct *rs= (PNGReadStruct *) png_get_io_ptr(png_ptr);
 
@@ -101,8 +106,161 @@ ReadData(
        longjmp(png_jmpbuf(png_ptr), 1);
 }
 
+short imb_savepng(struct ImBuf *ibuf, int file, int flags)
+{
+       png_structp png_ptr;
+       png_infop info_ptr;
+       unsigned char *pixels = 0;
+       unsigned char *from, *to;
+       png_bytepp row_pointers = 0;
+       int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
+       FILE *fp = 0;
+
+       bytesperpixel = (ibuf->depth + 7) >> 3;
+       if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
+               printf("imb_savepng: unsupported bytes per pixel: %d\n", bytesperpixel);
+               return (0);
+       }
+
+       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+               NULL, NULL, NULL);
+       if (png_ptr == NULL) {
+               printf("Cannot png_create_write_struct\n");
+               return 0;
+       }
+
+       info_ptr = png_create_info_struct(png_ptr);
+       if (info_ptr == NULL) {
+               png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+               printf("Cannot png_create_info_struct\n");
+               return 0;
+       }
+
+       if (setjmp(png_jmpbuf(png_ptr))) {
+               png_destroy_write_struct(&png_ptr, &info_ptr);
+               if (pixels) MEM_freeN(pixels);
+               if (row_pointers) MEM_freeN(row_pointers);
+               // printf("Aborting\n");
+               if (fp) {
+                       fflush(fp);
+                       fclose(fp);
+               }
+               return 0;
+       }
+
+       // copy image data
+
+       pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
+       if (pixels == NULL) {
+               printf("Cannot allocate pixels array\n");
+               return 0;
+       }
+
+       from = (unsigned char *) ibuf->rect;
+       to = pixels;
+
+       switch (bytesperpixel) {
+       case 4:
+               color_type = PNG_COLOR_TYPE_RGBA;
+               for (i = ibuf->x * ibuf->y; i > 0; i--) {
+                       to[0] = from[0];
+                       to[1] = from[1];
+                       to[2] = from[2];
+                       to[3] = from[3];
+                       to += 4; from += 4;
+               }
+               break;
+       case 3:
+               color_type = PNG_COLOR_TYPE_RGB;
+               for (i = ibuf->x * ibuf->y; i > 0; i--) {
+                       to[0] = from[0];
+                       to[1] = from[1];
+                       to[2] = from[2];
+                       to += 3; from += 4;
+               }
+               break;
+       case 1:
+               color_type = PNG_COLOR_TYPE_GRAY;
+               for (i = ibuf->x * ibuf->y; i > 0; i--) {
+                       to[0] = from[0];
+                       to++; from += 4;
+               }
+               break;
+       }
+
+       if (flags & IB_mem) {
+               // create image in memory
+               imb_addencodedbufferImBuf(ibuf);
+               ibuf->encodedsize = 0;
+
+               png_set_write_fn(png_ptr,
+                        (png_voidp) ibuf,
+                        WriteData,
+                        Flush);
+       } else {
+               fp = fdopen(file, "wb");
+               png_init_io(png_ptr, fp);
+       }
+
+       /*
+       png_set_filter(png_ptr, 0,
+               PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
+               PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
+               PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
+               PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
+               PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+               PNG_ALL_FILTERS);
+
+       png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+       */
+
+       // png image settings
+       png_set_IHDR(png_ptr,
+                info_ptr,
+                ibuf->x,
+                ibuf->y,
+                8,
+                color_type,
+                PNG_INTERLACE_NONE,
+                PNG_COMPRESSION_TYPE_DEFAULT,
+                PNG_FILTER_TYPE_DEFAULT);
+
+       // write the file header information
+       png_write_info(png_ptr, info_ptr);
+
+       // allocate memory for an array of row-pointers
+       row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
+       if (row_pointers == NULL) {
+                       printf("Cannot allocate row-pointers array\n");
+                       return 0;
+       }
+
+       // set the individual row-pointers to point at the correct offsets
+       for (i = 0; i < ibuf->y; i++) {
+               row_pointers[ibuf->y-1-i] = (png_bytep)
+                       ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
+       }
+
+       // write out the entire image data in one call
+       png_write_image(png_ptr, row_pointers);
+
+       // write the additional chunks to the PNG file (not really needed)
+       png_write_end(png_ptr, info_ptr);
+
+       // clean up
+       MEM_freeN(pixels);
+       MEM_freeN(row_pointers);
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+
+       if (fp) {
+               fflush(fp);
+               fclose(fp);
+       }
+
+       return(1);
+}
 
-struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags)
+struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags)
 {
        struct ImBuf *ibuf = 0;
        png_structp png_ptr;
@@ -116,7 +274,7 @@ struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags)
        unsigned char *from, *to;
        int i, bytesperpixel;
 
-       if (checkpng(mem) == 0) return(0);
+       if (imb_is_a_png(mem) == 0) return(0);
 
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                NULL, NULL, NULL);
@@ -127,7 +285,8 @@ struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags)
 
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL) {
-               png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+               png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
+                       (png_infopp)NULL);
                printf("Cannot png_create_info_struct\n");
                return 0;
        }
@@ -149,7 +308,8 @@ struct ImBuf *imb_png_decode(unsigned char *mem, int size, int flags)
        // png_set_sig_bytes(png_ptr, 8);
 
        png_read_info(png_ptr, info_ptr);
-       png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
+       png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
+               &color_type, NULL, NULL, NULL);
 
        if (bit_depth == 16) {
                png_set_strip_16(png_ptr);