in_sdl: give names to gamepad buttons
[libpicofe.git] / readpng.c
index cad1217..500e81c 100644 (file)
--- a/readpng.c
+++ b/readpng.c
@@ -5,6 +5,7 @@
  * (at your option):
  *  - GNU GPL, version 2 or later.
  *  - GNU LGPL, version 2.1 or later.
+ *  - MAME license.
  * See the COPYING file in the top-level directory.
  */
 
@@ -12,6 +13,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <png.h>
+#include "plat.h"
 #include "readpng.h"
 #include "lprintf.h"
 
@@ -60,37 +62,78 @@ int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req
                goto done;
        }
 
-       // lprintf("%s: %ix%i @ %ibpp\n", fname, (int)info_ptr->width, (int)info_ptr->height, info_ptr->pixel_depth);
+       // lprintf("%s: %ix%i @ %ibpp\n", fname, (int)png_get_image_width(png_ptr, info_ptr),
+       //      (int)png_get_image_height(png_ptr, info_ptr), png_get_bit_depth(png_ptr, info_ptr));
 
        switch (what)
        {
+               case READPNG_SCALE:
+               {
+                       int height, width, x_ofs = 0, y_ofs = 0;
+                       unsigned short *dst = dest;
+                       int x_scale, y_scale, x_pos, y_pos; // Q16
+
+                       if (png_get_bit_depth(png_ptr, info_ptr) != 8)
+                       {
+                               lprintf(__FILE__ ": scaled image uses %ibpc, needed 8bpc\n", png_get_bit_depth(png_ptr, info_ptr));
+                               goto done;
+                       }
+                       width = png_get_image_width(png_ptr, info_ptr);
+                       x_scale = width*65536 / req_w;
+                       height = png_get_image_height(png_ptr, info_ptr);
+                       y_scale = height*65536 / req_h;
+                       if (x_scale < y_scale)
+                               x_scale = y_scale;
+                       else    y_scale = x_scale;
+                       x_ofs = req_w - width*65536 / x_scale;
+                       y_ofs = req_h - height*65536 / y_scale;
+
+                       dst += y_ofs/2*req_w + x_ofs/2;
+                       for (y_pos = 0; y_pos < height*65536; y_pos += y_scale+1)
+                       {
+                               unsigned char *src = row_ptr[y_pos >> 16];
+                               int len = 0;
+                               for (x_pos = 0; x_pos < width*65536; x_pos += x_scale+1, len++)
+                               {
+                                       int o = 3*(x_pos >> 16);
+                                       // TODO: could use bilinear if upsampling?
+                                       *dst++ = PXMAKE(src[o], src[o+1], src[o+2]);
+                               }
+                               dst += req_w - len;
+                       }
+                       break;
+               }
+
                case READPNG_BG:
                {
-                       int height, width, h;
+                       int height, width, h, x_ofs = 0, y_ofs = 0;
                        unsigned short *dst = dest;
-                       if (info_ptr->pixel_depth != 24)
+
+                       if (png_get_bit_depth(png_ptr, info_ptr) != 8)
                        {
-                               lprintf(__FILE__ ": bg image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
-                               break;
+                               lprintf(__FILE__ ": bg image uses %ibpc, needed 8bpc\n", png_get_bit_depth(png_ptr, info_ptr));
+                               goto done;
                        }
-                       height = info_ptr->height;
-                       if (height > req_h)
-                               height = req_h;
-                       width = info_ptr->width;
-                       if (width > req_w)
+                       width = png_get_image_width(png_ptr, info_ptr);
+                       if (width > req_w) {
+                               x_ofs = (width - req_w) / 2;
                                width = req_w;
+                       } else
+                               dst += (req_w - width) / 2;
+                       height = png_get_image_height(png_ptr, info_ptr);
+                       if (height > req_h) {
+                               y_ofs = (height - req_h) / 2;
+                               height = req_h;
+                       } else
+                               dst += (req_h - height) / 2 * req_w;
 
                        for (h = 0; h < height; h++)
                        {
-                               unsigned char *src = row_ptr[h];
+                               unsigned char *src = row_ptr[h + y_ofs] + x_ofs * 3;
                                int len = width;
                                while (len--)
                                {
-#ifdef PSP
-                                       *dst++ = ((src[2]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[0] >> 3); // BGR
-#else
-                                       *dst++ = ((src[0]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[2] >> 3); // RGB
-#endif
+                                       *dst++ = PXMAKE(src[0], src[1], src[2]);
                                        src += 3;
                                }
                                dst += req_w - width;
@@ -102,16 +145,16 @@ int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req
                {
                        int x, y, x1, y1;
                        unsigned char *dst = dest;
-                       if (info_ptr->width != req_w || info_ptr->height != req_h)
+                       if (png_get_image_width(png_ptr, info_ptr) != req_w || png_get_image_height(png_ptr, info_ptr) != req_h)
                        {
                                lprintf(__FILE__ ": unexpected font image size %dx%d, needed %dx%d\n",
-                                       (int)info_ptr->width, (int)info_ptr->height, req_w, req_h);
-                               break;
+                                       (int)png_get_image_width(png_ptr, info_ptr), (int)png_get_image_height(png_ptr, info_ptr), req_w, req_h);
+                               goto done;
                        }
-                       if (info_ptr->pixel_depth != 8)
+                       if (png_get_bit_depth(png_ptr, info_ptr) != 8)
                        {
-                               lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
-                               break;
+                               lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", png_get_bit_depth(png_ptr, info_ptr));
+                               goto done;
                        }
                        for (y = 0; y < 16; y++)
                        {
@@ -135,16 +178,16 @@ int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req
                {
                        int x1, y1;
                        unsigned char *dst = dest;
-                       if (info_ptr->width != req_w || info_ptr->height != req_h)
+                       if (png_get_image_width(png_ptr, info_ptr) != req_w || png_get_image_height(png_ptr, info_ptr) != req_h)
                        {
                                lprintf(__FILE__ ": unexpected selector image size %ix%i, needed %dx%d\n",
-                                       (int)info_ptr->width, (int)info_ptr->height, req_w, req_h);
-                               break;
+                                       (int)png_get_image_width(png_ptr, info_ptr), (int)png_get_image_height(png_ptr, info_ptr), req_w, req_h);
+                               goto done;
                        }
-                       if (info_ptr->pixel_depth != 8)
+                       if (png_get_bit_depth(png_ptr, info_ptr) != 8)
                        {
-                               lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
-                               break;
+                               lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", png_get_bit_depth(png_ptr, info_ptr));
+                               goto done;
                        }
                        for (y1 = 0; y1 < req_h; y1++)
                        {
@@ -159,17 +202,17 @@ int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req
                {
                        int height, width, h;
                        unsigned char *dst = dest;
-                       if (info_ptr->pixel_depth != 24)
+                       if (png_get_bit_depth(png_ptr, info_ptr) != 8)
                        {
-                               lprintf(__FILE__ ": image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
-                               break;
+                               lprintf(__FILE__ ": image uses %ibpc, needed 8bpc\n", png_get_bit_depth(png_ptr, info_ptr));
+                               goto done;
                        }
-                       height = info_ptr->height;
-                       if (height > req_h)
-                               height = req_h;
-                       width = info_ptr->width;
+                       width = png_get_image_width(png_ptr, info_ptr);
                        if (width > req_w)
                                width = req_w;
+                       height = png_get_image_height(png_ptr, info_ptr);
+                       if (height > req_h)
+                               height = req_h;
 
                        for (h = 0; h < height; h++)
                        {
@@ -191,7 +234,7 @@ done:
        return ret;
 }
 
-int writepng(const char *fname, unsigned short *src, int w, int h)
+int writepngpp(const char *fname, unsigned short *src, int w, int h, int pitch)
 {
        png_structp png_ptr = NULL;
        png_infop info_ptr = NULL;
@@ -215,10 +258,11 @@ int writepng(const char *fname, unsigned short *src, int w, int h)
                        goto end2;
                row_pointers[i] = dst;
                for (j = 0; j < w; j++, src++, dst += 3) {
-                       dst[0] = (*src & 0xf800) >> 8;
-                       dst[1] = (*src & 0x07e0) >> 3;
-                       dst[2] = (*src & 0x001f) << 3;
+                       dst[0] = PXGETR(*src);
+                       dst[1] = PXGETG(*src);
+                       dst[2] = PXGETB(*src);
                }
+               src += pitch-w;
        }
 
        /* initialize stuff */
@@ -264,3 +308,7 @@ end1:
        return ret;
 }
 
+int writepng(const char *fname, unsigned short *src, int w, int h)
+{
+       return writepngpp(fname, src, w, h, w);
+}