diff --git a/.gitignore b/.gitignore
index a0ebbd68..d06a2a8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,5 +114,7 @@ ui_*.h
/ext/ffmpeg/libavutil/libavutil.a
/ext/ffmpeg/libswresample/libswresample.a
/ext/ffmpeg/libswscale/libswscale.a
+/liboavideo/test_oaconvert
+/liboavideo/test_oaconvert.txt
/oacapture/oacapture
/oalive/oalive
diff --git a/include/openastro/video.h b/include/openastro/video.h
index 73e39813..e6314743 100644
--- a/include/openastro/video.h
+++ b/include/openastro/video.h
@@ -27,6 +27,7 @@
#ifndef OPENASTRO_VIDEO_H
#define OPENASTRO_VIDEO_H
-extern int oaconvert ( void*, void*, int, int, int, int );
+extern int oaconvert ( const void*, void*, int, int, int, int );
+extern int oaconvert_greyscale ( const void*, void*, int, int, int, int );
#endif /* OPENASTRO_VIDEO_H */
diff --git a/liboavideo/Makefile.am b/liboavideo/Makefile.am
index b81c812d..04dee9e4 100644
--- a/liboavideo/Makefile.am
+++ b/liboavideo/Makefile.am
@@ -27,7 +27,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
lib_LTLIBRARIES = liboavideo.la
liboavideo_la_SOURCES = \
- oavideo.c yuv.c fits.c
+ oavideo.c yuv.c grey.c fits.c
WARNINGS = -g -O -Wall -Werror -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wno-pointer-sign $(OSX_WARNINGS)
@@ -38,3 +38,11 @@ warnings:
verbose-warnings:
$(MAKE) V=1 CFLAGS='$(WARNINGS)' CXXFLAGS='$(WARNINGS)'
$(MAKE) V=1 CFLAGS='$(WARNINGS)' CXXFLAGS='$(WARNINGS)' $(check_PROGRAMS)
+
+test:
+ @gcc --std=c99 -g3 -O0 -I./ -I../include test_oaconvert.c yuv.c grey.c oavideo.c -o test_oaconvert
+ @./test_oaconvert 2>&1 | tee test_oaconvert.txt
+ @if grep -q "at line" test_oaconvert.txt; then \
+ echo;\
+ head -n `grep at\ line test_oaconvert.txt | sed -e 's/.* at line \(.*\) .*/\1/g'` test_oaconvert.c | tail -n 1; \
+ fi
diff --git a/liboavideo/grey.c b/liboavideo/grey.c
new file mode 100644
index 00000000..f1309e8f
--- /dev/null
+++ b/liboavideo/grey.c
@@ -0,0 +1,320 @@
+/*****************************************************************************
+ *
+ * grey.c -- convert any format to GREYxx
+ *
+ * Copyright 2014 James Fidell (james@openastroproject.org)
+ *
+ * License:
+ *
+ * This file is part of the Open Astro Project.
+ *
+ * The Open Astro Project is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Open Astro Project is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Open Astro Project. If not, see
+ * .
+ *
+ *****************************************************************************/
+
+#include
+#include
+
+#include "grey.h"
+
+void
+oaGreyscale_8to16LE( const uint8_t* source, uint8_t* target, int len )
+{
+ int i;
+ uint8_t* t = target + (len-1)*2;
+ const uint8_t* s = source + (len-1);
+
+ for ( i = len; i > 0; i--, s-=1, t-=2 ) {
+ *(t+1) = *s;
+ *t = 0x00;
+ }
+}
+
+void
+oaGreyscale_8to16BE( const uint8_t* source, uint8_t* target, int len )
+{
+ int i;
+ uint8_t v;
+ uint8_t* t = target + (len-1)*2;
+ const uint8_t* s = source + (len-1);
+
+ for ( i = len; i > 0; i--, s-=1, t-=2 ) {
+ *t = *s;
+ *(t+1) = 0x00;
+ }
+}
+
+/* FIXME awaiting OA_PIX_FMT_XXXX10X
+void
+oaGreyscale_10to8( const uint8_t* s, uint8_t* t, int len, bool packed )
+{
+ int i;
+ uint16_t p;
+
+ if ( packed ) {
+ for ( i = 0; i < len; i += 5, s += 5 ) {
+ *t++ = *s;
+ *t++ = *(s+1);
+ *t++ = *(s+2);
+ *t++ = *(s+3);
+ // ignore 5th byte
+ }
+ }
+ else {
+ for ( i = 0; i < len; i += 2, s+=2 ) {
+ p = (*s << 6) + ((*(s+1)&0x03) << 14);
+ *t++ = (p & 0xff00) >> 8;
+ }
+ }
+}
+
+void
+oaGreyscale_10to16( const uint8_t* source, uint8_t* target, int len, bool packed, bool little_endian )
+{
+ int i;
+ const uint8_t* s;
+ uint8_t* t;
+ uint16_t p1, p2, p3, p4;
+
+ const int numPixels = len / ( packed ? 1.25 : 2 );
+
+ if ( packed ) {
+ t = target + (numPixels-4) * 2;
+ s = source + (numPixels-4) * 5/4;
+
+ for ( i=0; i < len; i += 5, s -= 5, t -= 8)
+ {
+ uint8_t lsb = *(s+4);
+
+ uint16_t p1 = (*(s) << 8) + ((lsb&0x03) << 6);
+ uint16_t p2 = (*(s+1) << 8) + ((lsb&0x0c) << 4);
+ uint16_t p3 = (*(s+2) << 8) + ((lsb&0x30) << 2);
+ uint16_t p4 = (*(s+3) << 8) + (lsb&0xc0);
+
+ if (little_endian) {
+ *t = p1 & 0x00ff;
+ *(t+1) = (p1 & 0xff00) >> 8;
+ *(t+2) = p2 & 0x00ff;
+ *(t+3) = (p2 & 0xff00) >> 8;
+ *(t+4) = p3 & 0x00ff;
+ *(t+5) = (p3 & 0xff00) >> 8;
+ *(t+6) = p4 & 0x00ff;
+ *(t+7) = (p4 & 0xff00) >> 8;
+ }
+ else {
+ *t = (p1 & 0xff00) >> 8;
+ *(t+1) = p1 & 0x00ff;
+ *(t+2) = (p2 & 0xff00) >> 8;
+ *(t+3) = p2 & 0x00ff;
+ *(t+4) = (p3 & 0xff00) >> 8;
+ *(t+5) = p3 & 0x00ff;
+ *(t+6) = (p4 & 0xff00) >> 8;
+ *(t+7) = p4 & 0x00ff;
+ }
+ }
+ }
+ else {
+ t = target + (numPixels-1)*2;
+ s = source + (numPixels-1)*2;
+
+ for ( i=0; i < len; i += 2, s-=2, t-=2)
+ {
+ p1 = (*s << 6) + ((*(s+1)&0x03) << 14);
+ if (little_endian) {
+ *t = p1 & 0x00ff;
+ *(t+1) = (p1 & 0xff00) >> 8;
+ }
+ else {
+ *t = (p1 & 0xff00) >> 8;
+ *(t+1) = p1 & 0x00ff;
+ }
+ }
+ }
+}
+
+void
+oaGreyscale_10to16LE( const uint8_t* s, uint8_t* t, int len, bool packed )
+{
+ oaGreyscale_10to16( s, t, len, packed, true );
+}
+
+void
+oaGreyscale_10to16BE( const uint8_t* s, uint8_t* t, int len, bool packed )
+{
+ oaGreyscale_10to16( s, t, len, packed, false );
+}
+*/
+
+void
+oaGreyscale_16LEto8( const uint8_t* s, uint8_t* t, int len )
+{
+ int i;
+ for ( i = 0; i < len; i+=2, s+=2, t++ ) {
+ *t = *(s+1);
+ }
+}
+
+void
+oaGreyscale_16BEto8( const uint8_t* s, uint8_t* t, int len )
+{
+ int i;
+ for ( i = 0; i < len; i+=2, s+=2, t++ ) {
+ *t = *s;
+ }
+}
+
+void
+oaGreyscale_16swap( const uint8_t* s, uint8_t* t, int len )
+{
+ int i;
+ for ( i = 0; i < len; i+=2, s+=2, t+=2 ) {
+ uint8_t v = *s;
+ *t = *(s+1);
+ *(t+1) = v;
+ }
+}
+
+void
+oaGreyscale_RGB24to8( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint8_t R, G, B;
+ for ( i = 0; i < len; i += 3, s += 3, t += 1 ) {
+ R = swapRB ? *(s+2) : *s; G = *(s+1); B = swapRB ? *s : *(s+2);
+ *t = .2126 * R + .7152 * G + .0722 * B;
+ }
+}
+
+void
+oaGreyscale_RGB24to16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 3, s += 3, t += 2 ) {
+ R = swapRB ? *(s+2) : *s; G = *(s+1); B = swapRB ? *s : *(s+2);
+ Y = .2126 * (R<<8) + .7152 * (G<<8) + .0722 * (B<<8);
+ *t = Y & 0x00ff;
+ *(t+1) = (Y & 0xff00) >> 8;
+ }
+}
+
+void
+oaGreyscale_RGB24to16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 3, s += 3, t += 2 ) {
+ R = swapRB ? *(s+2) : *s; G = *(s+1); B = swapRB ? *s : *(s+2);
+ Y = .2126 * (R<<8) + .7152 * (G<<8) + .0722 * (B<<8);
+ *t = (Y & 0xff00) >> 8;
+ *(t+1) = Y & 0x00ff;
+ }
+}
+
+void
+oaGreyscale_RGB48LEto8( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 1 ) {
+ R = swapRB ? ((*(s+5)<<8) + *(s+4)) : (((*(s+1))<<8) + *s);
+ G = (*(s+3)<<8) + *(s+2);
+ B = swapRB ? ((*(s+1)<<8) + *s) : ((*(s+5)<<8) + *(s+4));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = (Y & 0xff00) >> 8;
+ }
+}
+
+void
+oaGreyscale_RGB48LEto16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 2 ) {
+ R = swapRB ? ((*(s+5)<<8) + *(s+4)) : ((*(s+1)<<8) + *s);
+ G = (*(s+3)<<8) + *(s+2);
+ B = swapRB ? ((*(s+1)<<8) + *s) : ((*(s+5)<<8) + *(s+4));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = Y & 0x00ff;
+ *(t+1) = (Y & 0xff00) >> 8;
+ }
+}
+
+void
+oaGreyscale_RGB48LEto16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 2 ) {
+ R = swapRB ? ((*(s+5)<<8) + *(s+4)) : ((*(s+1)<<8) + *s);
+ G = (*(s+3)<<8) + *(s+2);
+ B = swapRB ? ((*(s+1)<<8) + *s) : ((*(s+5)<<8) + *(s+4));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = (Y & 0xff00) >> 8;
+ *(t+1) = Y & 0x00ff;
+ }
+}
+
+void
+oaGreyscale_RGB48BEto8( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 1 ) {
+ R = swapRB ? ((*(s+4)<<8) + *(s+5)) : ((*s<<8) + *(s+1));
+ G = (*(s+2)<<8) + *(s+3);
+ B = swapRB ? ((*s<<8) + *(s+1)) : ((*(s+4)<<8) + *(s+5));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = (Y & 0xff00) >> 8;
+ }
+}
+
+void
+oaGreyscale_RGB48BEto16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 2 ) {
+ R = swapRB ? ((*(s+4)<<8) + *(s+5)) : ((*s<<8) + *(s+1));
+ G = (*(s+2)<<8) + *(s+3);
+ B = swapRB ? ((*s<<8) + *(s+1)) : ((*(s+4)<<8) + *(s+5));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = Y & 0x00ff;
+ *(t+1) = (Y & 0xff00) >> 8;
+ }
+}
+
+void
+oaGreyscale_RGB48BEto16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB )
+{
+ int i;
+ uint16_t R, G, B;
+ uint16_t Y;
+ for ( i = 0; i < len; i += 6, s += 6, t += 2 ) {
+ R = swapRB ? ((*(s+4)<<8) + *(s+5)) : ((*s<<8) + *(s+1));
+ G = (*(s+2)<<8) + *(s+3);
+ B = swapRB ? ((*s<<8) + *(s+1)) : ((*(s+4)<<8) + *(s+5));
+ Y = .2126 * R + .7152 * G + .0722 * B;
+ *t = (Y & 0xff00) >> 8;
+ *(t+1) = Y & 0x00ff;
+ }
+}
diff --git a/liboavideo/grey.h b/liboavideo/grey.h
new file mode 100644
index 00000000..f9542060
--- /dev/null
+++ b/liboavideo/grey.h
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ *
+ * grey.h -- convert any format to GREYxx header
+ *
+ * Copyright 2017 ...
+ *
+ * License:
+ *
+ * This file is part of the Open Astro Project.
+ *
+ * The Open Astro Project is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Open Astro Project is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Open Astro Project. If not, see
+ * .
+ *
+ *****************************************************************************/
+
+#ifndef OPENASTRO_VIDEO_GREY_H
+#define OPENASTRO_VIDEO_GREY_H
+
+#include
+typedef enum { false, true } bool;
+
+extern void oaGreyscale_8to16LE( const uint8_t* s, uint8_t* t, int len );
+extern void oaGreyscale_8to16BE( const uint8_t* s, uint8_t* t, int len );
+
+/* FIXME awaiting OA_PIX_FMT_XXXX10X
+extern void oaGreyscale_10to8( const uint8_t* s, uint8_t* t, int len, bool packed );
+extern void oaGreyscale_10to16LE( const uint8_t* s, uint8_t* t, int len, bool packed );
+extern void oaGreyscale_10to16BE( const uint8_t* s, uint8_t* t, int len, bool packed );
+*/
+
+extern void oaGreyscale_16LEto8( const uint8_t* s, uint8_t* t, int len );
+extern void oaGreyscale_16BEto8( const uint8_t* s, uint8_t* t, int len );
+extern void oaGreyscale_16swap( const uint8_t* s, uint8_t* t, int len );
+
+extern void oaGreyscale_RGB24to8( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB24to16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB24to16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+
+extern void oaGreyscale_RGB48LEto8( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB48LEto16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB48LEto16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+
+extern void oaGreyscale_RGB48BEto8( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB48BEto16LE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+extern void oaGreyscale_RGB48BEto16BE( const uint8_t* s, uint8_t* t, int len, bool swapRB );
+
+#endif /* OPENASTRO_VIDEO_GREY_H */
diff --git a/liboavideo/oavideo.c b/liboavideo/oavideo.c
index 1cd2f1e0..b37362fb 100644
--- a/liboavideo/oavideo.c
+++ b/liboavideo/oavideo.c
@@ -28,13 +28,20 @@
#include
#include
-#include "yuv.h"
+#include
+#include "yuv.h"
+#include "grey.h"
int
-oaconvert ( void* source, void* target, int xSize, int ySize, int sourceFormat,
+oaconvert ( const void* source, void* target, int xSize, int ySize, int sourceFormat,
int targetFormat )
{
+ if ( OA_ISGREYSCALE( targetFormat ) ) {
+ oaconvert_greyscale( source, target, xSize, ySize,
+ sourceFormat, targetFormat );
+ }
+
if ( targetFormat != OA_PIX_FMT_RGB24 ) {
// FIX ME -- set errno
return -1;
@@ -66,3 +73,202 @@ oaconvert ( void* source, void* target, int xSize, int ySize, int sourceFormat,
return 0;
}
+
+
+
+int
+oaconvert_greyscale ( const void* source, void* target, int xSize, int ySize, int sourceFormat,
+ int targetFormat )
+{
+ int length;
+ bool swapRB;
+
+ if ( !OA_ISGREYSCALE( targetFormat ) ) {
+ // FIX ME -- set errno
+ return -1;
+ }
+
+ if ( !source || !target )
+ {
+ // FIX ME -- set errno
+ return -1;
+ }
+
+ switch ( sourceFormat ) {
+ case OA_PIX_FMT_GREY8:
+ case OA_PIX_FMT_BGGR8:
+ case OA_PIX_FMT_RGGB8:
+ case OA_PIX_FMT_GBRG8:
+ case OA_PIX_FMT_GRBG8:
+ length = xSize * ySize;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ if ( target != source ) memcpy( target, source, length );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_8to16LE( source, target, length );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_8to16BE( source, target, length );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+/* FIXME awaiting OA_PIX_FMTXXXX10X
+ //case OA_PIX_FMT_BGGR10P:
+ //case OA_PIX_FMT_RGGB10P:
+ //case OA_PIX_FMT_GBRG10P:
+ case OA_PIX_FMT_GRBG10P:
+ length = xSize * ySize * 1.25;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_10to8( source, target, length, true );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_10to16LE( source, target, length, true );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_10to16BE( source, target, length, true );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ //case OA_PIX_FMT_BGGR10:
+ //case OA_PIX_FMT_RGGB10:
+ //case OA_PIX_FMT_GBRG10:
+ case OA_PIX_FMT_GRBG10:
+ length = xSize * ySize * 2;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_10to8( source, target, length, false );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_10to16LE( source, target, length, false );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_10to16BE( source, target, length, false );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+*/
+ case OA_PIX_FMT_GREY16LE:
+ case OA_PIX_FMT_BGGR16LE:
+ case OA_PIX_FMT_RGGB16LE:
+ case OA_PIX_FMT_GBRG16LE:
+ case OA_PIX_FMT_GRBG16LE:
+ length = xSize * ySize * 2;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_16LEto8( source, target, length );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ if ( target != source) memcpy( target, source, length );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_16swap( source, target, length );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ case OA_PIX_FMT_GREY16BE:
+ case OA_PIX_FMT_BGGR16BE:
+ case OA_PIX_FMT_RGGB16BE:
+ case OA_PIX_FMT_GBRG16BE:
+ case OA_PIX_FMT_GRBG16BE:
+ length = xSize * ySize * 2;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_16BEto8( source, target, length );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_16swap( source, target, length );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ if ( target != source ) memcpy( target, source, length );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ case OA_PIX_FMT_RGB24:
+ case OA_PIX_FMT_BGR24:
+ length = xSize * ySize * 3;
+ swapRB = sourceFormat == OA_PIX_FMT_BGR24;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_RGB24to8( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_RGB24to16LE( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_RGB24to16BE( source, target, length, swapRB );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ case OA_PIX_FMT_RGB48LE:
+ case OA_PIX_FMT_BGR48LE:
+ length = xSize * ySize * 6;
+ swapRB = sourceFormat == OA_PIX_FMT_BGR48LE;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_RGB48LEto8( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_RGB48LEto16LE( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_RGB48LEto16BE( source, target, length, swapRB );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ case OA_PIX_FMT_RGB48BE:
+ case OA_PIX_FMT_BGR48BE:
+ length = xSize * ySize * 6;
+ swapRB = sourceFormat == OA_PIX_FMT_BGR48BE;
+ switch ( targetFormat ) {
+ case OA_PIX_FMT_GREY8:
+ oaGreyscale_RGB48BEto8( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16LE:
+ oaGreyscale_RGB48BEto16LE( source, target, length, swapRB );
+ break;
+ case OA_PIX_FMT_GREY16BE:
+ oaGreyscale_RGB48BEto16BE( source, target, length, swapRB );
+ break;
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ break;
+
+ //FIXME TODO
+ case OA_PIX_FMT_YUV444P:
+ case OA_PIX_FMT_YUV422P:
+ case OA_PIX_FMT_YUV420P:
+ case OA_PIX_FMT_YUV410P:
+ case OA_PIX_FMT_YUYV:
+ case OA_PIX_FMT_UYVY:
+ case OA_PIX_FMT_YUV420:
+ case OA_PIX_FMT_YUV411:
+ case OA_PIX_FMT_YUV410:
+ default:
+ return -1; // FIX ME -- set errno
+ }
+ return 0;
+}
+
diff --git a/liboavideo/rgb_to_grey.ods b/liboavideo/rgb_to_grey.ods
new file mode 100644
index 00000000..d4566b56
Binary files /dev/null and b/liboavideo/rgb_to_grey.ods differ
diff --git a/liboavideo/test_oaconvert.c b/liboavideo/test_oaconvert.c
new file mode 100644
index 00000000..734075da
--- /dev/null
+++ b/liboavideo/test_oaconvert.c
@@ -0,0 +1,250 @@
+//gcc --std=c99 -g3 -O0 -I./ -I../include test_oaconvert.c yuv.c grey.c oavideo.c -o test_oaconvert
+//or `head -n 1 test_oaconvert.c | cut -c 3-`
+// ./test_oaconvert 2>&1 | tee test_oaconvert.txt; LINE=`grep at\ line test_oaconvert.txt | sed -e 's/.* at line //g'`; head -n $LINE test_oaconvert.c | tail -n 1
+#include
+#include
+#include
+
+#include
+#include
+#include "yuv.h"
+#include "grey.h"
+
+
+#define TARGET_LENGTH 24
+
+uint8_t source[] = { 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef,
+ 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0xab, 0xcd, 0xef };
+
+uint8_t empty[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+
+void print_array(uint8_t* buf, int len, int sep)
+{
+ int i;
+ for ( i = 0; i < len; ++i )
+ {
+ if (i == sep)
+ fprintf(stderr, " ... ");
+ fprintf(stderr, "%02x ", *(buf+i));
+ }
+ fprintf(stderr, "\n");
+}
+
+void assert(int fmt, uint8_t expected[], uint8_t* target, int length, int check_nulls, int LINE)
+{
+ fprintf(stderr, ".");
+ if (0 != memcmp(target, expected, length)) {
+ fprintf(stderr, "F\n");
+ fprintf(stderr, "Conversion does not match expected at line %d (fmt==%d)\n", LINE, fmt);
+ fprintf(stderr, "Expected: "); print_array(expected, length, -1);
+ fprintf(stderr, "Actual: "); print_array(target, length, -1);
+ exit(-1);
+ }
+ if (check_nulls && 0 != memcmp(empty, target+length, TARGET_LENGTH-length)) {
+ fprintf(stderr, "F\n");
+ fprintf(stderr, "Conversion exceeds length of expected (%d) at line %d (fmt==%d)\n", length, LINE, fmt);
+ print_array(target, TARGET_LENGTH, length);
+ exit(-1);
+ }
+}
+
+/**
+ * Test a conversion from pixel format S to pixel format T
+ *
+ * fmt - an index if running in a loop, to provide useful debug on failure
+ * S - source pixel format
+ * T - target pixel format
+ * e - pointer to array of expected result
+ * l - length of expected result
+ * L - line at which the function (macro) was invokved
+ */
+void test_convert(int fmt, int S, int T, uint8_t* e, int l, int L)
+{
+ uint8_t* t = (uint8_t*) malloc(TARGET_LENGTH);
+
+ // Test conversion from one buffer to another
+ memset(t, 0, TARGET_LENGTH);
+ oaconvert(source, t, 2, 2, S, T);
+ assert(fmt, e, t, l, 1, L);
+
+ // Test in-place conversion
+ memcpy(t, source, TARGET_LENGTH);
+ oaconvert(t, t, 2, 2, S, T);
+ assert(fmt, e, t, l, 0, L);
+
+ free(t);
+}
+
+#define EXPECTED(...) __VA_ARGS__
+#define TEST_CONVERT(fmt, S, T, expected) \
+do {\
+ uint8_t e[] = expected;\
+ test_convert(fmt, S, T, e, sizeof(e), __LINE__);\
+} while (0);
+
+
+
+/* FIXME - no routines and hence no tests exist for the following formats
+#define OA_PIX_FMT_YUV444P 22
+#define OA_PIX_FMT_YUV422P 23
+#define OA_PIX_FMT_YUV420P 24
+#define OA_PIX_FMT_YUV410P 25
+#define OA_PIX_FMT_YUYV 27
+#define OA_PIX_FMT_UYVY 28
+#define OA_PIX_FMT_YUV420 29
+#define OA_PIX_FMT_YUV411 30
+#define OA_PIX_FMT_YUV410 31
+*/
+
+
+void test_8()
+{
+ int fmt;
+ uint8_t FORMATS_8[] = { OA_PIX_FMT_GREY8,
+ OA_PIX_FMT_BGGR8,
+ OA_PIX_FMT_RGGB8,
+ OA_PIX_FMT_GBRG8,
+ OA_PIX_FMT_GRBG8 };
+
+ fprintf(stderr, "Running tests in %s", __FUNCTION__);
+
+ // 8bit
+ for ( fmt=0; fmt < sizeof(FORMATS_8); ++fmt ) {
+ TEST_CONVERT(fmt, FORMATS_8[fmt], OA_PIX_FMT_GREY8, EXPECTED({0x01, 0x23, 0x45, 0x67}));
+ TEST_CONVERT(fmt, FORMATS_8[fmt], OA_PIX_FMT_GREY16LE, EXPECTED({0x00, 0x01, 0x00, 0x23, 0x00, 0x45, 0x00, 0x67}));
+ TEST_CONVERT(fmt, FORMATS_8[fmt], OA_PIX_FMT_GREY16BE, EXPECTED({0x01, 0x00, 0x23, 0x00, 0x45, 0x00, 0x67, 0x00}));
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void test_10()
+{
+/* FIXME awaiting OA_PIX_FMT_XXXX10X
+
+ int fmt;
+ uint8_t FORMATS_10P[] = { //OA_PIX_FMT_BGGR10P,
+ //OA_PIX_FMT_RGGB10P,
+ //OA_PIX_FMT_GBRG10P,
+ OA_PIX_FMT_GRBG10P };
+
+ uint8_t FORMATS_10[] = { //OA_PIX_FMT_BGGR10,
+ //OA_PIX_FMT_RGGB10,
+ //OA_PIX_FMT_GBRG10,
+ OA_PIX_FMT_GRBG10 };
+
+ fprintf(stderr, "Running tests in %s", __FUNCTION__);
+
+ // 10bit packed
+ for ( fmt=0; fmt < sizeof(FORMATS_10P); ++fmt ) {
+ TEST_CONVERT(fmt, FORMATS_10P[fmt], OA_PIX_FMT_GREY8, EXPECTED({0x01, 0x23, 0x45, 0x67}));
+ TEST_CONVERT(fmt, FORMATS_10P[fmt], OA_PIX_FMT_GREY16LE, EXPECTED({0x40, 0x01, 0x80, 0x23, 0x00, 0x45, 0x80, 0x67}));
+ TEST_CONVERT(fmt, FORMATS_10P[fmt], OA_PIX_FMT_GREY16BE, EXPECTED({0x01, 0x40, 0x23, 0x80, 0x45, 0x00, 0x67, 0x80}));
+ }
+
+ // 10bit
+ for ( fmt=0; fmt < sizeof(FORMATS_10); ++fmt ) {
+ TEST_CONVERT(fmt, FORMATS_10[fmt], OA_PIX_FMT_GREY8, EXPECTED({0xc0, 0xd1, 0xe2, 0xf3}));
+ TEST_CONVERT(fmt, FORMATS_10[fmt], OA_PIX_FMT_GREY16LE, EXPECTED({0x40, 0xc0, 0x40, 0xd1, 0x40, 0xe2, 0x40, 0xf3}));
+ TEST_CONVERT(fmt, FORMATS_10[fmt], OA_PIX_FMT_GREY16BE, EXPECTED({0xc0, 0x40, 0xd1, 0x40, 0xe2, 0x40, 0xf3, 0x40}));
+ }
+
+ fprintf(stderr, "\n");
+*/
+}
+
+void test_16 ()
+{
+ int fmt;
+ uint8_t FORMATS_16LE[] = { OA_PIX_FMT_GREY16LE,
+ OA_PIX_FMT_BGGR16LE,
+ OA_PIX_FMT_RGGB16LE,
+ OA_PIX_FMT_GBRG16LE,
+ OA_PIX_FMT_GRBG16LE };
+
+ uint8_t FORMATS_16BE[] = { OA_PIX_FMT_GREY16BE,
+ OA_PIX_FMT_BGGR16BE,
+ OA_PIX_FMT_RGGB16BE,
+ OA_PIX_FMT_GBRG16BE,
+ OA_PIX_FMT_GRBG16BE };
+
+ fprintf(stderr, "Running tests in %s", __FUNCTION__);
+
+ // 16bit LE
+ for ( fmt=0; fmt < sizeof(FORMATS_16LE); ++fmt ) {
+ TEST_CONVERT(fmt, FORMATS_16LE[fmt], OA_PIX_FMT_GREY8, EXPECTED({0x23, 0x67, 0xab, 0xef}));
+ TEST_CONVERT(fmt, FORMATS_16LE[fmt], OA_PIX_FMT_GREY16LE, EXPECTED({0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}));
+ TEST_CONVERT(fmt, FORMATS_16LE[fmt], OA_PIX_FMT_GREY16BE, EXPECTED({0x23, 0x01, 0x67, 0x45, 0xab, 0x89, 0xef, 0xcd}));
+ }
+
+ // 16bit BE
+ for ( fmt=0; fmt < sizeof(FORMATS_16BE); ++fmt ) {
+ TEST_CONVERT(fmt, FORMATS_16BE[fmt], OA_PIX_FMT_GREY8, EXPECTED({0x01, 0x45, 0x89, 0xcd}));
+ TEST_CONVERT(fmt, FORMATS_16BE[fmt], OA_PIX_FMT_GREY16LE, EXPECTED({0x23, 0x01, 0x67, 0x45, 0xab, 0x89, 0xef, 0xcd}));
+ TEST_CONVERT(fmt, FORMATS_16BE[fmt], OA_PIX_FMT_GREY16BE, EXPECTED({0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}));
+ }
+
+ fprintf(stderr, "\n");
+}
+
+
+void test_rgb24()
+{
+ fprintf(stderr, "Running tests in %s", __FUNCTION__);
+
+ // RGB24
+ TEST_CONVERT(0, OA_PIX_FMT_RGB24, OA_PIX_FMT_GREY8, EXPECTED({0x1e, 0x84, 0xd6, 0x40}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB24, OA_PIX_FMT_GREY16LE, EXPECTED({0x39, 0x1e, 0x39, 0x84, 0x96, 0xd6, 0x39, 0x40}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB24, OA_PIX_FMT_GREY16BE, EXPECTED({0x1e, 0x39, 0x84, 0x39, 0xd6, 0x96, 0x40, 0x39}));
+
+ // BGR24
+ TEST_CONVERT(0, OA_PIX_FMT_BGR24, OA_PIX_FMT_GREY8, EXPECTED({0x27, 0x8d, 0xb9, 0x49}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR24, OA_PIX_FMT_GREY16LE, EXPECTED({0xc6, 0x27, 0xc6, 0x8d, 0xf2, 0xb9, 0xc6, 0x49}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR24, OA_PIX_FMT_GREY16BE, EXPECTED({0x27, 0xc6, 0x8d, 0xc6, 0xb9, 0xf2, 0x49, 0xc6}));
+
+ fprintf(stderr, "\n");
+}
+
+void test_rgb48()
+{
+ fprintf(stderr, "Running tests in %s", __FUNCTION__);
+
+ // RGB48
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48LE, OA_PIX_FMT_GREY8, EXPECTED({0x5d, 0x53, 0xd2, 0xa1}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48LE, OA_PIX_FMT_GREY16LE, EXPECTED({0xaf, 0x5d, 0x78, 0x53, 0x80, 0xd2, 0xf3, 0xa1}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48LE, OA_PIX_FMT_GREY16BE, EXPECTED({0x5d, 0xaf, 0x53, 0x78, 0xd2, 0x80, 0xa1, 0xf3}));
+
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48BE, OA_PIX_FMT_GREY8, EXPECTED({0x3b, 0x31, 0xb0, 0x80}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48BE, OA_PIX_FMT_GREY16LE, EXPECTED({0xd1, 0x3b, 0x9a, 0x31, 0xa2, 0xb0, 0x15, 0x80}));
+ TEST_CONVERT(0, OA_PIX_FMT_RGB48BE, OA_PIX_FMT_GREY16BE, EXPECTED({0x3b, 0xd1, 0x31, 0x9a, 0xb0, 0xa2, 0x80, 0x15}));
+
+ // BGR48
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48LE, OA_PIX_FMT_GREY8, EXPECTED({0x70, 0x40, 0xbf, 0xb5}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48LE, OA_PIX_FMT_GREY16LE, EXPECTED({0xda, 0x70, 0x4d, 0x40, 0x55, 0xbf, 0x1e, 0xb5}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48LE, OA_PIX_FMT_GREY16BE, EXPECTED({0x70, 0xda, 0x40, 0x4d, 0xbf, 0x55, 0xb5, 0x1e}));
+
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48BE, OA_PIX_FMT_GREY8, EXPECTED({0x4e, 0x1e, 0x9d, 0x93}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48BE, OA_PIX_FMT_GREY16LE, EXPECTED({0xfc, 0x4e, 0x6f, 0x1e, 0x77, 0x9d, 0x40, 0x93}));
+ TEST_CONVERT(0, OA_PIX_FMT_BGR48BE, OA_PIX_FMT_GREY16BE, EXPECTED({0x4e, 0xfc, 0x1e, 0x6f, 0x9d, 0x77, 0x93, 0x40}));
+
+ fprintf(stderr, "\n");
+}
+
+int main()
+{
+ test_8();
+ test_10();
+ test_16();
+ test_rgb24();
+ test_rgb48();
+}
+
diff --git a/liboavideo/yuv.c b/liboavideo/yuv.c
index 8d2b3bb1..e49c0834 100644
--- a/liboavideo/yuv.c
+++ b/liboavideo/yuv.c
@@ -27,6 +27,8 @@
#include
#include
+#include
+
#include "yuv.h"
#include "yuvlut.h"
@@ -34,13 +36,13 @@
void
-oaYUV444PtoRGB888 ( void* source, void* target, unsigned int xSize,
+oaYUV444PtoRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
- uint8_t* ys = source;
- uint8_t* us = ( uint8_t* ) source + len;
- uint8_t* vs = ( uint8_t* ) source + 2 * len;
+ const uint8_t* ys = source;
+ const uint8_t* us = ( uint8_t* ) source + len;
+ const uint8_t* vs = ( uint8_t* ) source + 2 * len;
uint8_t* t = ( uint8_t* ) target;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y, u, v;
@@ -64,13 +66,13 @@ oaYUV444PtoRGB888 ( void* source, void* target, unsigned int xSize,
void
-oaYUV422PtoRGB888 ( void* source, void* target, unsigned int xSize,
+oaYUV422PtoRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
- uint8_t* ys = ( uint8_t* ) source;
- uint8_t* us = ( uint8_t* ) source + len;
- uint8_t* vs = us + len / 2;
+ const uint8_t* ys = ( uint8_t* ) source;
+ const uint8_t* us = ( uint8_t* ) source + len;
+ const uint8_t* vs = us + len / 2;
uint8_t* t = ( uint8_t* ) target;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y1, y2, u, v;
@@ -113,7 +115,7 @@ oaYUV422PtoRGB888 ( void* source, void* target, unsigned int xSize,
void
-oaYUV420PtoRGB888 ( void* source, void* target, unsigned int xSize,
+oaYUV420PtoRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
@@ -121,7 +123,7 @@ oaYUV420PtoRGB888 ( void* source, void* target, unsigned int xSize,
unsigned int c, r;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y, u, v;
- uint8_t* ys = ( uint8_t* ) source;
+ const uint8_t* ys = ( uint8_t* ) source;
uint8_t* u_off;
uint8_t* v_off;
uint8_t* t = ( uint8_t* ) target;
@@ -152,11 +154,11 @@ oaYUV420PtoRGB888 ( void* source, void* target, unsigned int xSize,
void
-oaYUYVtoRGB888 ( void* source, void* target, unsigned int xSize,
+oaYUYVtoRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
- uint8_t* s = ( uint8_t* ) source;
+ const uint8_t* s = ( uint8_t* ) source;
uint8_t* t = ( uint8_t* ) target;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y1, y2, u, v;
@@ -199,11 +201,11 @@ oaYUYVtoRGB888 ( void* source, void* target, unsigned int xSize,
void
-oaUYVYtoRGB888 ( void* source, void* target, unsigned int xSize,
+oaUYVYtoRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
- uint8_t* s = ( uint8_t* ) source;
+ const uint8_t* s = ( uint8_t* ) source;
uint8_t* t = ( uint8_t* ) target;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y1, y2, u, v;
@@ -246,11 +248,11 @@ oaUYVYtoRGB888 ( void* source, void* target, unsigned int xSize,
void
-oaYUV411toRGB888 ( void* source, void* target, unsigned int xSize,
+oaYUV411toRGB888 ( const void* source, void* target, unsigned int xSize,
unsigned int ySize )
{
unsigned int len = xSize * ySize;
- uint8_t* s = ( uint8_t* ) source;
+ const uint8_t* s = ( uint8_t* ) source;
uint8_t* t = ( uint8_t* ) target;
int32_t r32, g32, b32;
uint8_t r8, g8, b8, y1, y2, y3, y4, u, v;
diff --git a/liboavideo/yuv.h b/liboavideo/yuv.h
index 64b5a8fc..a734797a 100644
--- a/liboavideo/yuv.h
+++ b/liboavideo/yuv.h
@@ -27,10 +27,10 @@
#ifndef OPENASTRO_VIDEO_YUV_H
#define OPENASTRO_VIDEO_YUV_H
-extern void oaYUV444PtoRGB888 ( void*, void*, unsigned int, unsigned int );
-extern void oaYUV422PtoRGB888 ( void*, void*, unsigned int, unsigned int );
-extern void oaYUV411toRGB888 ( void*, void*, unsigned int, unsigned int );
-extern void oaYUYVtoRGB888 ( void*, void*, unsigned int, unsigned int );
-extern void oaUYVYtoRGB888 ( void*, void*, unsigned int, unsigned int );
+extern void oaYUV444PtoRGB888 ( const void*, void*, unsigned int, unsigned int );
+extern void oaYUV422PtoRGB888 ( const void*, void*, unsigned int, unsigned int );
+extern void oaYUV411toRGB888 ( const void*, void*, unsigned int, unsigned int );
+extern void oaYUYVtoRGB888 ( const void*, void*, unsigned int, unsigned int );
+extern void oaUYVYtoRGB888 ( const void*, void*, unsigned int, unsigned int );
#endif /* OPENASTRO_VIDEO_YUV_H */