Am 07.01.10, 10:09 -0500 schrieb Adam Jackson:
On Thu, 2010-01-07 at 14:38 +0100, Kai-Uwe Behrmann wrote:
The above library appears rather early in development.
Too early to come with patches for extending?
Not at all, please do.
Thanks for applying the previous two patches.
Attached is the colorimetry.patch and the changed test.c app.
The patch allowes the changed test application to print out the
colorimetric coordinates from inside a EDID block. These coordinates can
be further used to generate an ICC profile as is done in Oyranos git.
The patch corrects a mistake in edid.c:41.
"if (memcmp(block, header, 8) != 0)"
is needed to check for equality there, which means, the block is fine
and the function can continue with that EDID block and shall not return
at this point.
I marked the code taken from Soren in edid.c. I may better mention him in
the file header?
monitor.c:7 gets a small bugfix.
New public APIs are declared:
struct mt_doubles
mt_monitor_colorimetry_rgbwgamma
mt_destroy_doubles
Please note mt_destroy_doubles takes a pointer to a pointer and sets the
pointer to zero. That way the pointer can not be further used by accident.
The usage of already freed pointers is a common mistake in C. Hope that
makes sense in this context.
How is the documentation done to describe the declarations? Inline in
doxygen style or something else?
kind regards
Kai-Uwe Behrmann
--
developing for colour management
www.behrmann.name + www.oyranos.org
diff --git a/edid.c b/edid.c
index 443423a..6da725d 100644
--- a/edid.c
+++ b/edid.c
@@ -38,7 +38,7 @@ static uint32_t edid_probe(struct mt_monitor *mon)
if (blocks * 128 != mon->len)
return 0;
- if (memcmp(block, header, 8) == 0)
+ if (memcmp(block, header, 8) != 0)
return 0;
if (edid_version(block) != 1)
@@ -483,7 +483,81 @@ edid_modes(struct mt_monitor *mon)
return mode;
}
+/* BEGINN edid-parse.c_SECTION
+
+ Author: Soren Sandmann <[email protected]>
+
+ Should be MIT licensed.
+ */
+
+static int
+get_bit (int in, int bit)
+{
+ return (in & (1 << bit)) >> bit;
+}
+
+static int
+get_bits (int in, int begin, int end)
+{
+ int mask = (1 << (end - begin + 1)) - 1;
+
+ return (in >> begin) & mask;
+}
+
+static double
+decode_fraction (int high, int low)
+{
+ double result = 0.0;
+ int i;
+
+ high = (high << 2) | low;
+
+ for (i = 0; i < 10; ++i)
+ result += get_bit (high, i) * pow (2, i - 10);
+
+ return result;
+}
+
+static int
+decode_color_characteristics (const unsigned char *edid, double * c)
+{
+ c[0]/*red_x*/ = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
+ c[1]/*red_y*/ = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
+ c[2]/*green_x*/ = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
+ c[3]/*green_y*/ = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
+ c[4]/*blue_x*/ = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
+ c[5]/*blue_y*/ = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
+ c[6]/*white_x*/ = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
+ c[7]/*white_y*/ = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
+
+ return 1;
+}
+
+/* END edid-parse.c_SECTION */
+
+
+static struct mt_doubles *
+edid_colorimetry(struct mt_monitor *mon)
+{
+ struct mt_doubles * values = calloc( sizeof(struct mt_doubles) +
+ sizeof(double) * 8, 1 );
+ uint8_t *block = mon->block;
+
+ values->values = calloc( sizeof(double), 9 );
+ decode_color_characteristics( block, values->values );
+ /* Gamma */
+ if (block[23] == 0xFF)
+ values->values[8] = -1.0;
+ else
+ values->values[8] = (block[23] + 100.0) / 100.0;
+
+ values->count = 9;
+
+ return values;
+}
+
hidden struct mt_backend _mt_edid_backend = {
edid_probe,
edid_modes,
+ edid_colorimetry,
};
diff --git a/minitru-int.h b/minitru-int.h
index befb01f..b85af0f 100644
--- a/minitru-int.h
+++ b/minitru-int.h
@@ -15,10 +15,12 @@
#endif /* GNUC >= 4 */
struct mt_monitor;
+struct mt_doubles;
struct mt_backend {
uint32_t (*probe)(struct mt_monitor *monitor);
struct mt_mode *(*modes)(struct mt_monitor *monitor);
+ struct mt_doubles *(*colorimetry)(struct mt_monitor *monitor);
};
extern hidden struct mt_backend _mt_edid_backend;
diff --git a/minitru.h b/minitru.h
index db9dae3..ac63d68 100644
--- a/minitru.h
+++ b/minitru.h
@@ -71,6 +71,11 @@ struct mt_mode {
void *next;
};
+struct mt_doubles {
+ uint32_t count;
+ double * values;
+};
+
extern struct mt_mode *mt_monitor_mode_list(struct mt_monitor *monitor);
extern struct mt_mode *mt_dmt_mode_list(void);
extern struct mt_mode *mt_cvt_mode(uint32_t hdisplay, uint32_t vdisplay,
@@ -83,6 +88,7 @@ extern struct mt_mode *mt_mode_copy(const struct mt_mode *mode);
extern float mt_mode_hsync(const struct mt_mode *mode);
extern float mt_mode_vsync(const struct mt_mode *mode);
extern uint32_t mt_mode_is_reduced_blanking(struct mt_mode *mode);
-
+extern struct mt_doubles * mt_monitor_colorimetry_rgbwgamma(void * monitor);
+extern void mt_destroy_doubles(struct mt_doubles ** values);
#endif
diff --git a/monitor.c b/monitor.c
index 51ae20e..2dd2399 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4,7 +4,7 @@ static const struct mt_backend *backends[] = {
&_mt_edid_backend,
&_mt_displayid_backend,
};
-static const int num_backends = sizeof(backends) / sizeof(struct mt_backend);
+static const int num_backends = sizeof(backends) / sizeof(struct mt_backend*);
void *
mt_create_monitor(void *block, uint32_t len)
@@ -34,3 +34,26 @@ mt_destroy_monitor(void *monitor)
{
free(monitor);
}
+
+struct mt_doubles *
+mt_monitor_colorimetry_rgbwgamma(void * monitor)
+{
+ struct mt_monitor *mon = (struct mt_monitor *) monitor;
+
+ if (!mon || !mon->block || !mon->len)
+ return NULL;
+
+ return mon->backend->colorimetry( mon );
+}
+void
+
+mt_destroy_doubles(struct mt_doubles ** values)
+{
+ if(*values)
+ {
+ if((*values)->values)
+ free( (*values)->values );
+ free( *values );
+ *values = 0;
+ }
+}
/**
* Compile: gcc -Wall -g test.c -o test -L./ -lminitru -lc -lm
*
* Usage: oyranos-monitor -f edid -o edid.data
* LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./test edid.data
*/
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "minitru.h"
int main(int argc, char **argv)
{
const char * file_name = 0;
FILE * fp = 0;
uint8_t * mem = 0;
size_t size = 0, s;
void * mt_monitor = 0;
if(argc > 1)
file_name = argv[1];
else
{
fprintf(stderr, "Please specify EDID/CVT block as argument\nExiting\n");
exit(0);
}
fp = fopen( file_name, "rb" );
if(!fp)
{
fprintf(stderr, "Could not open file: %s\nExiting\n", file_name);
exit(1);
}
fseek( fp, 0L, SEEK_END );
size = ftell( fp );
rewind( fp );
if(!size)
{
fprintf(stderr, "File is empty: %s\nExiting\n", file_name);
exit(1);
}
mem = malloc(size+1);
memset( mem, 0, size );
s = fread( mem, sizeof(char), size, fp );
if(s != size)
{
fprintf(stderr, "Could not read file: %s\nExiting\n", file_name);
exit(1);
}
mt_monitor = mt_create_monitor( mem, size );
if(!mt_monitor)
{
fprintf(stderr, "Could not understand data block from: %s\nExiting\n", file_name);
exit(1);
}
struct mt_doubles * colorimetry = mt_monitor_colorimetry_rgbwgamma(
mt_monitor );
if(colorimetry)
{
fprintf(stdout, "red={%g,%g}\ngreen={%g,%g}\nblue={%g,%g}\n"
"white={%g,%g}\ngamma=%g\n",
colorimetry->values[0], colorimetry->values[1],
colorimetry->values[2], colorimetry->values[3],
colorimetry->values[4], colorimetry->values[5],
colorimetry->values[6], colorimetry->values[7],
colorimetry->values[8]
);
} else
fprintf(stderr, "Could not interprete colorimetry from: %s\n", file_name);
mt_destroy_doubles( &colorimetry );
mt_destroy_monitor( mt_monitor );
return 0;
}
_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel