backported imago from eradicate
[dosdemo] / libs / imago / src / conv.c
index 334fe35..94fb87f 100644 (file)
@@ -1,6 +1,6 @@
 /*
 libimago - a multi-format image file input/output library.
-Copyright (C) 2010 John Tsiombikas <nuclear@member.fsf.org>
+Copyright (C) 2010-2020 John Tsiombikas <nuclear@member.fsf.org>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <string.h>
 #include "imago2.h"
+#include "inttypes.h"
 
 /* pixel-format conversions are sub-optimal at the moment to avoid
  * writing a lot of code. optimize at some point ?
@@ -31,25 +32,31 @@ struct pixel {
 static void unpack_grey8(struct pixel *unp, void *pptr, int count);
 static void unpack_rgb24(struct pixel *unp, void *pptr, int count);
 static void unpack_rgba32(struct pixel *unp, void *pptr, int count);
+static void unpack_bgra32(struct pixel *unp, void *pptr, int count);
 static void unpack_greyf(struct pixel *unp, void *pptr, int count);
 static void unpack_rgbf(struct pixel *unp, void *pptr, int count);
 static void unpack_rgbaf(struct pixel *unp, void *pptr, int count);
+static void unpack_rgb565(struct pixel *unp, void *pptr, int count);
 
 static void pack_grey8(void *pptr, struct pixel *unp, int count);
 static void pack_rgb24(void *pptr, struct pixel *unp, int count);
 static void pack_rgba32(void *pptr, struct pixel *unp, int count);
+static void pack_bgra32(void *pptr, struct pixel *unp, int count);
 static void pack_greyf(void *pptr, struct pixel *unp, int count);
 static void pack_rgbf(void *pptr, struct pixel *unp, int count);
 static void pack_rgbaf(void *pptr, struct pixel *unp, int count);
+static void pack_rgb565(void *pptr, struct pixel *unp, int count);
 
 /* XXX keep in sync with enum img_fmt at imago2.h */
 static void (*unpack[])(struct pixel*, void*, int) = {
        unpack_grey8,
        unpack_rgb24,
        unpack_rgba32,
+       unpack_bgra32,
        unpack_greyf,
        unpack_rgbf,
-       unpack_rgbaf
+       unpack_rgbaf,
+       unpack_rgb565
 };
 
 /* XXX keep in sync with enum img_fmt at imago2.h */
@@ -57,9 +64,11 @@ static void (*pack[])(void*, struct pixel*, int) = {
        pack_grey8,
        pack_rgb24,
        pack_rgba32,
+       pack_bgra32,
        pack_greyf,
        pack_rgbf,
-       pack_rgbaf
+       pack_rgbaf,
+       pack_rgb565
 };
 
 
@@ -140,6 +149,20 @@ static void unpack_rgba32(struct pixel *unp, void *pptr, int count)
        }
 }
 
+static void unpack_bgra32(struct pixel *unp, void *pptr, int count)
+{
+       int i;
+       unsigned char *pix = pptr;
+
+       for(i=0; i<count; i++) {
+               unp->a = (float)*pix++ / 255.0;
+               unp->r = (float)*pix++ / 255.0;
+               unp->g = (float)*pix++ / 255.0;
+               unp->b = (float)*pix++ / 255.0;
+               unp++;
+       }
+}
+
 static void unpack_greyf(struct pixel *unp, void *pptr, int count)
 {
        int i;
@@ -180,6 +203,28 @@ static void unpack_rgbaf(struct pixel *unp, void *pptr, int count)
        }
 }
 
+static void unpack_rgb565(struct pixel *unp, void *pptr, int count)
+{
+       int i;
+       uint16_t *pix = pptr;
+
+       for(i=0; i<count; i++) {
+               uint16_t r, g, b, p = *pix++;
+               b = (p & 0x1f) << 3;
+               if(b & 8) b |= 7;       /* fill LSbits with whatever bit 0 was */
+               g = (p >> 2) & 0xfc;
+               if(g & 4) g |= 3;       /* ditto */
+               r = (p >> 8) & 0xf8;
+               if(r & 8) r |= 7;       /* same */
+
+               unp->r = (float)r / 255.0f;
+               unp->g = (float)g / 255.0f;
+               unp->b = (float)b / 255.0f;
+               unp->a = 1.0f;
+               unp++;
+       }
+}
+
 
 static void pack_grey8(void *pptr, struct pixel *unp, int count)
 {
@@ -229,6 +274,25 @@ static void pack_rgba32(void *pptr, struct pixel *unp, int count)
        }
 }
 
+static void pack_bgra32(void *pptr, struct pixel *unp, int count)
+{
+       int i;
+       unsigned char *pix = pptr;
+
+       for(i=0; i<count; i++) {
+               int r = (int)(unp->r * 255.0);
+               int g = (int)(unp->g * 255.0);
+               int b = (int)(unp->b * 255.0);
+               int a = (int)(unp->a * 255.0);
+
+               *pix++ = CLAMP(b, 0, 255);
+               *pix++ = CLAMP(g, 0, 255);
+               *pix++ = CLAMP(r, 0, 255);
+               *pix++ = CLAMP(a, 0, 255);
+               unp++;
+       }
+}
+
 static void pack_greyf(void *pptr, struct pixel *unp, int count)
 {
        int i;
@@ -258,3 +322,20 @@ static void pack_rgbaf(void *pptr, struct pixel *unp, int count)
        memcpy(pptr, unp, count * sizeof *unp);
 }
 
+
+static void pack_rgb565(void *pptr, struct pixel *unp, int count)
+{
+       int i;
+       uint16_t p, *pix = pptr;
+
+       for(i=0; i<count; i++) {
+               uint16_t r = (uint16_t)(unp->r * 31.0f);
+               uint16_t g = (uint16_t)(unp->g * 63.0f);
+               uint16_t b = (uint16_t)(unp->b * 31.0f);
+               if(r > 31) r = 31;
+               if(g > 63) g = 63;
+               if(b > 31) b = 31;
+               *pix++ = (r << 11) | (g << 5) | b;
+               unp++;
+       }
+}