Revision: 75437
http://sourceforge.net/p/brlcad/code/75437
Author: starseeker
Date: 2020-04-17 16:14:01 +0000 (Fri, 17 Apr 2020)
Log Message:
-----------
Take a stab at pushing the image writing into the backend. For the Dm object
that looks like it leaves flushing and syncing operations as still using
exposing xvars.
Modified Paths:
--------------
brlcad/branches/dm-fb-merge/include/dm.h
brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c
brlcad/branches/dm-fb-merge/src/libdm/dm-generic.c
brlcad/branches/dm-fb-merge/src/libdm/dm_obj.c
brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.c
brlcad/branches/dm-fb-merge/src/libdm/include/calltable.h
Modified: brlcad/branches/dm-fb-merge/include/dm.h
===================================================================
--- brlcad/branches/dm-fb-merge/include/dm.h 2020-04-17 15:21:55 UTC (rev
75436)
+++ brlcad/branches/dm-fb-merge/include/dm.h 2020-04-17 16:14:01 UTC (rev
75437)
@@ -28,9 +28,8 @@
#include "common.h"
-#include "png.h"
-
#include "vmath.h"
+#include "bu/vls.h"
#include "bn.h"
#include "raytrace.h"
@@ -291,9 +290,9 @@
DM_EXPORT extern int dm_get_fb_visible(struct dm *dmp);
DM_EXPORT extern int dm_set_fb_visible(struct dm *dmp, int is_fb_visible);
-// TODO - this should be using libicv rather than returning a PNG struct -
right
-// now this just moving the guts of dmo_png_cmd behind the call table...
-DM_EXPORT extern png_structp dm_get_image(struct dm *dmp);
+// TODO - this should be using libicv - right now this just moving the guts of
+// dmo_png_cmd behind the call table, so only provides PNG...
+DM_EXPORT extern int dm_write_image(struct bu_vls *msgs, FILE *fp, struct dm
*dmp);
/* TODO - dm_vp is supposed to go away, but until we figure it out
* expose it here to allow dm hiding */
Modified: brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c 2020-04-17 15:21:55 UTC
(rev 75436)
+++ brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c 2020-04-17 16:14:01 UTC
(rev 75437)
@@ -55,6 +55,8 @@
# include "tk.h"
#endif
+#include "png.h"
+
#include "vmath.h"
#include "bu/endian.h"
#include "bn.h"
@@ -1752,6 +1754,264 @@
return 0;
}
+
+// TODO - this and getDisplayImage need to be consolidated...
+int
+X_write_image(struct bu_vls *msgs, FILE *fp, struct dm *dmp)
+{
+ png_structp png_p;
+ png_infop info_p;
+ XImage *ximage_p;
+ unsigned char **rows;
+ unsigned char *idata;
+ unsigned char *irow;
+ int bytes_per_pixel;
+ int bits_per_channel = 8; /* bits per color channel */
+ int i, j, k;
+ unsigned char *dbyte0, *dbyte1, *dbyte2, *dbyte3;
+ int red_shift;
+ int green_shift;
+ int blue_shift;
+ int red_bits;
+ int green_bits;
+ int blue_bits;
+
+ png_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "X_write_image: could not create PNG write
structure\n");
+ }
+ return -1;
+ }
+
+ info_p = png_create_info_struct(png_p);
+ if (!info_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "X_write_image: could not create PNG info
structure\n");
+ }
+ png_destroy_write_struct(&png_p, NULL);
+ return -1;
+ }
+
+ ximage_p = XGetImage(((struct dm_Xvars *)dmp->i->dm_vars.pub_vars)->dpy,
+ ((struct dm_Xvars *)dmp->i->dm_vars.pub_vars)->win,
+ 0, 0,
+ dmp->i->dm_width,
+ dmp->i->dm_height,
+ ~0, ZPixmap);
+ if (!ximage_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "png: could not get XImage\n");
+ }
+ png_destroy_write_struct(&png_p, &info_p);
+ return -1;
+ }
+
+ bytes_per_pixel = ximage_p->bytes_per_line / ximage_p->width;
+
+ if (bytes_per_pixel == 4) {
+ unsigned long mask;
+ unsigned long tmask;
+
+ /* This section assumes 8 bits per channel */
+
+ mask = ximage_p->red_mask;
+ tmask = 1;
+ for (red_shift = 0; red_shift < 32; red_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ mask = ximage_p->green_mask;
+ tmask = 1;
+ for (green_shift = 0; green_shift < 32; green_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ mask = ximage_p->blue_mask;
+ tmask = 1;
+ for (blue_shift = 0; blue_shift < 32; blue_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ /*
+ * We need to reverse things if the image byte order
+ * is different from the system's byte order.
+ */
+ if (((bu_byteorder() == BU_BIG_ENDIAN) && (ximage_p->byte_order ==
LSBFirst)) ||
+ ((bu_byteorder() == BU_LITTLE_ENDIAN) && (ximage_p->byte_order ==
MSBFirst))) {
+ DM_REVERSE_COLOR_BYTE_ORDER(red_shift, ximage_p->red_mask);
+ DM_REVERSE_COLOR_BYTE_ORDER(green_shift, ximage_p->green_mask);
+ DM_REVERSE_COLOR_BYTE_ORDER(blue_shift, ximage_p->blue_mask);
+ }
+
+ } else if (bytes_per_pixel == 2) {
+ unsigned long mask;
+ unsigned long tmask;
+ int bpb = 8; /* bits per byte */
+
+ /*XXX
+ * This section probably needs logic similar
+ * to the previous section (i.e. bytes_per_pixel == 4).
+ * That is we may need to reverse things depending on
+ * the image byte order and the system's byte order.
+ */
+
+ mask = ximage_p->red_mask;
+ tmask = 1;
+ for (red_shift = 0; red_shift < 16; red_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (red_bits = red_shift; red_bits < 16; red_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+
+ red_bits = red_bits - red_shift;
+ if (red_shift == 0)
+ red_shift = red_bits - bpb;
+ else
+ red_shift = red_shift - (bpb - red_bits);
+
+ mask = ximage_p->green_mask;
+ tmask = 1;
+ for (green_shift = 0; green_shift < 16; green_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (green_bits = green_shift; green_bits < 16; green_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+
+ green_bits = green_bits - green_shift;
+ green_shift = green_shift - (bpb - green_bits);
+
+ mask = ximage_p->blue_mask;
+ tmask = 1;
+ for (blue_shift = 0; blue_shift < 16; blue_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (blue_bits = blue_shift; blue_bits < 16; blue_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+ blue_bits = blue_bits - blue_shift;
+
+ if (blue_shift == 0)
+ blue_shift = blue_bits - bpb;
+ else
+ blue_shift = blue_shift - (bpb - blue_bits);
+ } else {
+ if (msgs) {
+ bu_vls_printf(msgs, "png: %d bytes per pixel is not yet
supported\n", bytes_per_pixel);
+ }
+ png_destroy_write_struct(&png_p, &info_p);
+ return -1;
+ }
+
+ rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char
*), "rows");
+ idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, 4,
"png data");
+
+ /* for each scanline */
+ for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {
+ /* irow points to the current scanline in ximage_p */
+ irow = (unsigned char *)(ximage_p->data +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
+
+ if (bytes_per_pixel == 4) {
+ unsigned int pixel;
+
+ /* rows[j] points to the current scanline in idata */
+ rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
+
+ /* for each pixel in current scanline of ximage_p */
+ for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
+ pixel = *((unsigned int *)(irow + k));
+
+ dbyte0 = rows[j] + k;
+ dbyte1 = dbyte0 + 1;
+ dbyte2 = dbyte0 + 2;
+ dbyte3 = dbyte0 + 3;
+
+ *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+ *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+ *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+ *dbyte3 = 255;
+ }
+ } else if (bytes_per_pixel == 2) {
+ unsigned short spixel;
+ unsigned long pixel;
+
+ /* rows[j] points to the current scanline in idata */
+ rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line*2));
+
+ /* for each pixel in current scanline of ximage_p */
+ for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
+ spixel = *((unsigned short *)(irow + k));
+ pixel = spixel;
+
+ dbyte0 = rows[j] + k*2;
+ dbyte1 = dbyte0 + 1;
+ dbyte2 = dbyte0 + 2;
+ dbyte3 = dbyte0 + 3;
+
+ if (0 <= red_shift)
+ *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+ else
+ *dbyte0 = (pixel & ximage_p->red_mask) << -red_shift;
+
+ *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+
+ if (0 <= blue_shift)
+ *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+ else
+ *dbyte2 = (pixel & ximage_p->blue_mask) << -blue_shift;
+
+ *dbyte3 = 255;
+ }
+ } else {
+ bu_free(rows, "rows");
+ bu_free(idata, "image data");
+ png_destroy_write_struct(&png_p, &info_p);
+ if (msgs) {
+ bu_vls_printf(msgs, "png: not supported for this platform\n");
+ }
+ return -1;
+ }
+ }
+
+ png_init_io(png_p, fp);
+ png_set_filter(png_p, 0, PNG_FILTER_NONE);
+ png_set_compression_level(png_p, 9);
+ png_set_IHDR(png_p, info_p, ximage_p->width, ximage_p->height,
bits_per_channel,
+ PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_set_gAMA(png_p, info_p, 0.77);
+ png_write_info(png_p, info_p);
+ png_write_image(png_p, rows);
+ png_write_end(png_p, NULL);
+
+ png_destroy_write_struct(&png_p, &info_p);
+
+ bu_free(rows, "rows");
+ bu_free(idata, "image data");
+
+ return 0;
+}
+
/* Display Manager package interface */
struct dm_impl dm_X_impl = {
X_close,
@@ -1795,7 +2055,7 @@
NULL,
X_geometry_request,
X_internal_var,
- NULL,
+ X_write_image,
0,
0, /* no displaylist */
0, /* no stereo */
Modified: brlcad/branches/dm-fb-merge/src/libdm/dm-generic.c
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/dm-generic.c 2020-04-17 15:21:55 UTC
(rev 75436)
+++ brlcad/branches/dm-fb-merge/src/libdm/dm-generic.c 2020-04-17 16:14:01 UTC
(rev 75437)
@@ -187,11 +187,11 @@
}
}
-png_structp
-dm_get_image(struct dm *dmp)
+int
+dm_write_image(struct bu_vls *msgs, FILE *fp, struct dm *dmp)
{
- if (!dmp || !dmp->i->dm_get_image) return NULL;
- return dmp->i->dm_get_image(dmp);
+ if (!dmp || !dmp->i->dm_write_image) return -1;
+ return dmp->i->dm_write_image(msgs, fp, dmp);
}
/* Properly generic functions */
Modified: brlcad/branches/dm-fb-merge/src/libdm/dm_obj.c
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/dm_obj.c 2020-04-17 15:21:55 UTC
(rev 75436)
+++ brlcad/branches/dm-fb-merge/src/libdm/dm_obj.c 2020-04-17 16:14:01 UTC
(rev 75437)
@@ -2040,23 +2040,8 @@
int argc,
const char **argv)
{
+ struct bu_vls msgs = BU_VLS_INIT_ZERO;
FILE *fp;
- png_structp png_p;
- png_infop info_p;
- XImage *ximage_p;
- unsigned char **rows;
- unsigned char *idata;
- unsigned char *irow;
- int bytes_per_pixel;
- int bits_per_channel = 8; /* bits per color channel */
- int i, j, k;
- unsigned char *dbyte0, *dbyte1, *dbyte2, *dbyte3;
- int red_shift;
- int green_shift;
- int blue_shift;
- int red_bits;
- int green_bits;
- int blue_bits;
if (argc != 2) {
struct bu_vls vls = BU_VLS_INIT_ZERO;
@@ -2067,241 +2052,26 @@
return BRLCAD_ERROR;
}
- if ((fp = fopen(argv[1], "wb")) == NULL) {
- Tcl_AppendResult(dmop->interp, "png: cannot open \"", argv[1], " for
writing\n", (char *)NULL);
+ if (!dmop->dmo_dmp->i->dm_write_image) {
+ Tcl_AppendResult(dmop->interp, "png: writing unsupported with this
display manager type.\n", (char *)NULL);
return BRLCAD_ERROR;
}
- png_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_p) {
- Tcl_AppendResult(dmop->interp, "png: could not create PNG write
structure\n", (char *)NULL);
- fclose(fp);
+ if ((fp = fopen(argv[1], "wb")) == NULL) {
+ Tcl_AppendResult(dmop->interp, "png: cannot open \"", argv[1], " for
writing\n", (char *)NULL);
return BRLCAD_ERROR;
}
- info_p = png_create_info_struct(png_p);
- if (!info_p) {
- Tcl_AppendResult(dmop->interp, "png: could not create PNG info
structure\n", (char *)NULL);
- fclose(fp);
- return BRLCAD_ERROR;
- }
+ int ret = dmop->dmo_dmp->i->dm_write_image(&msgs, fp, dmop->dmo_dmp);
- ximage_p = XGetImage(((struct dm_xvars
*)dmop->dmo_dmp->i->dm_vars.pub_vars)->dpy,
- ((struct dm_xvars
*)dmop->dmo_dmp->i->dm_vars.pub_vars)->win,
- 0, 0,
- dmop->dmo_dmp->i->dm_width,
- dmop->dmo_dmp->i->dm_height,
- ~0, ZPixmap);
- if (!ximage_p) {
- Tcl_AppendResult(dmop->interp, "png: could not get XImage\n", (char
*)NULL);
- fclose(fp);
- return BRLCAD_ERROR;
+ if (ret) {
+ Tcl_AppendResult(dmop->interp, bu_vls_cstr(&msgs), (char *)NULL);
}
- bytes_per_pixel = ximage_p->bytes_per_line / ximage_p->width;
-
- if (bytes_per_pixel == 4) {
- unsigned long mask;
- unsigned long tmask;
-
- /* This section assumes 8 bits per channel */
-
- mask = ximage_p->red_mask;
- tmask = 1;
- for (red_shift = 0; red_shift < 32; red_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
-
- mask = ximage_p->green_mask;
- tmask = 1;
- for (green_shift = 0; green_shift < 32; green_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
-
- mask = ximage_p->blue_mask;
- tmask = 1;
- for (blue_shift = 0; blue_shift < 32; blue_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
-
- /*
- * We need to reverse things if the image byte order
- * is different from the system's byte order.
- */
- if (((bu_byteorder() == BU_BIG_ENDIAN) && (ximage_p->byte_order ==
LSBFirst)) ||
- ((bu_byteorder() == BU_LITTLE_ENDIAN) && (ximage_p->byte_order ==
MSBFirst))) {
- DM_REVERSE_COLOR_BYTE_ORDER(red_shift, ximage_p->red_mask);
- DM_REVERSE_COLOR_BYTE_ORDER(green_shift, ximage_p->green_mask);
- DM_REVERSE_COLOR_BYTE_ORDER(blue_shift, ximage_p->blue_mask);
- }
-
- } else if (bytes_per_pixel == 2) {
- unsigned long mask;
- unsigned long tmask;
- int bpb = 8; /* bits per byte */
-
- /*XXX
- * This section probably needs logic similar
- * to the previous section (i.e. bytes_per_pixel == 4).
- * That is we may need to reverse things depending on
- * the image byte order and the system's byte order.
- */
-
- mask = ximage_p->red_mask;
- tmask = 1;
- for (red_shift = 0; red_shift < 16; red_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
- for (red_bits = red_shift; red_bits < 16; red_bits++) {
- if (!(tmask & mask))
- break;
- tmask = tmask << 1;
- }
-
- red_bits = red_bits - red_shift;
- if (red_shift == 0)
- red_shift = red_bits - bpb;
- else
- red_shift = red_shift - (bpb - red_bits);
-
- mask = ximage_p->green_mask;
- tmask = 1;
- for (green_shift = 0; green_shift < 16; green_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
- for (green_bits = green_shift; green_bits < 16; green_bits++) {
- if (!(tmask & mask))
- break;
- tmask = tmask << 1;
- }
-
- green_bits = green_bits - green_shift;
- green_shift = green_shift - (bpb - green_bits);
-
- mask = ximage_p->blue_mask;
- tmask = 1;
- for (blue_shift = 0; blue_shift < 16; blue_shift++) {
- if (tmask & mask)
- break;
- tmask = tmask << 1;
- }
- for (blue_bits = blue_shift; blue_bits < 16; blue_bits++) {
- if (!(tmask & mask))
- break;
- tmask = tmask << 1;
- }
- blue_bits = blue_bits - blue_shift;
-
- if (blue_shift == 0)
- blue_shift = blue_bits - bpb;
- else
- blue_shift = blue_shift - (bpb - blue_bits);
- } else {
- struct bu_vls vls = BU_VLS_INIT_ZERO;
-
- bu_vls_printf(&vls, "png: %d bytes per pixel is not yet supported\n",
bytes_per_pixel);
- Tcl_AppendResult(dmop->interp, bu_vls_addr(&vls), (char *)NULL);
- fclose(fp);
- bu_vls_free(&vls);
-
- return BRLCAD_ERROR;
- }
-
- rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char
*), "rows");
- idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, 4,
"png data");
-
- /* for each scanline */
- for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {
- /* irow points to the current scanline in ximage_p */
- irow = (unsigned char *)(ximage_p->data +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
-
- if (bytes_per_pixel == 4) {
- unsigned int pixel;
-
- /* rows[j] points to the current scanline in idata */
- rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
-
- /* for each pixel in current scanline of ximage_p */
- for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
- pixel = *((unsigned int *)(irow + k));
-
- dbyte0 = rows[j] + k;
- dbyte1 = dbyte0 + 1;
- dbyte2 = dbyte0 + 2;
- dbyte3 = dbyte0 + 3;
-
- *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
- *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
- *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
- *dbyte3 = 255;
- }
- } else if (bytes_per_pixel == 2) {
- unsigned short spixel;
- unsigned long pixel;
-
- /* rows[j] points to the current scanline in idata */
- rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line*2));
-
- /* for each pixel in current scanline of ximage_p */
- for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
- spixel = *((unsigned short *)(irow + k));
- pixel = spixel;
-
- dbyte0 = rows[j] + k*2;
- dbyte1 = dbyte0 + 1;
- dbyte2 = dbyte0 + 2;
- dbyte3 = dbyte0 + 3;
-
- if (0 <= red_shift)
- *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
- else
- *dbyte0 = (pixel & ximage_p->red_mask) << -red_shift;
-
- *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
-
- if (0 <= blue_shift)
- *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
- else
- *dbyte2 = (pixel & ximage_p->blue_mask) << -blue_shift;
-
- *dbyte3 = 255;
- }
- } else {
- bu_free(rows, "rows");
- bu_free(idata, "image data");
- fclose(fp);
-
- Tcl_AppendResult(dmop->interp, "png: not supported for this
platform\n", (char *)NULL);
- return BRLCAD_ERROR;
- }
- }
-
- png_init_io(png_p, fp);
- png_set_filter(png_p, 0, PNG_FILTER_NONE);
- png_set_compression_level(png_p, 9);
- png_set_IHDR(png_p, info_p, ximage_p->width, ximage_p->height,
bits_per_channel,
- PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
- png_set_gAMA(png_p, info_p, 0.77);
- png_write_info(png_p, info_p);
- png_write_image(png_p, rows);
- png_write_end(png_p, NULL);
-
- bu_free(rows, "rows");
- bu_free(idata, "image data");
+ bu_vls_free(&msgs);
fclose(fp);
- return BRLCAD_OK;
+ return (ret) ? BRLCAD_ERROR : BRLCAD_OK;
}
Modified: brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.c
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.c 2020-04-17 15:21:55 UTC
(rev 75436)
+++ brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.c 2020-04-17 16:14:01 UTC
(rev 75437)
@@ -32,6 +32,7 @@
#include <math.h>
#include <string.h>
+
#ifdef HAVE_X11_XOSDEFS_H
# include <X11/Xfuncproto.h>
# include <X11/Xosdefs.h>
@@ -69,6 +70,8 @@
#undef y1
#undef j1
+#include "png.h"
+
#include "tk.h"
#undef VMIN /* is used in vmath.h, too */
@@ -2623,6 +2626,264 @@
return 0;
}
+
+// TODO - this and getDisplayImage need to be consolidated...
+int
+ogl_write_image(struct bu_vls *msgs, FILE *fp, struct dm *dmp)
+{
+ png_structp png_p;
+ png_infop info_p;
+ XImage *ximage_p;
+ unsigned char **rows;
+ unsigned char *idata;
+ unsigned char *irow;
+ int bytes_per_pixel;
+ int bits_per_channel = 8; /* bits per color channel */
+ int i, j, k;
+ unsigned char *dbyte0, *dbyte1, *dbyte2, *dbyte3;
+ int red_shift;
+ int green_shift;
+ int blue_shift;
+ int red_bits;
+ int green_bits;
+ int blue_bits;
+
+ png_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "ogl_write_image: could not create PNG write
structure\n");
+ }
+ return -1;
+ }
+
+ info_p = png_create_info_struct(png_p);
+ if (!info_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "ogl_write_image: could not create PNG info
structure\n");
+ }
+ png_destroy_write_struct(&png_p, NULL);
+ return -1;
+ }
+
+ ximage_p = XGetImage(((struct dm_glxvars *)dmp->i->dm_vars.pub_vars)->dpy,
+ ((struct dm_glxvars *)dmp->i->dm_vars.pub_vars)->win,
+ 0, 0,
+ dmp->i->dm_width,
+ dmp->i->dm_height,
+ ~0, ZPixmap);
+ if (!ximage_p) {
+ if (msgs) {
+ bu_vls_printf(msgs, "png: could not get XImage\n");
+ }
+ png_destroy_write_struct(&png_p, &info_p);
+ return -1;
+ }
+
+ bytes_per_pixel = ximage_p->bytes_per_line / ximage_p->width;
+
+ if (bytes_per_pixel == 4) {
+ unsigned long mask;
+ unsigned long tmask;
+
+ /* This section assumes 8 bits per channel */
+
+ mask = ximage_p->red_mask;
+ tmask = 1;
+ for (red_shift = 0; red_shift < 32; red_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ mask = ximage_p->green_mask;
+ tmask = 1;
+ for (green_shift = 0; green_shift < 32; green_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ mask = ximage_p->blue_mask;
+ tmask = 1;
+ for (blue_shift = 0; blue_shift < 32; blue_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+
+ /*
+ * We need to reverse things if the image byte order
+ * is different from the system's byte order.
+ */
+ if (((bu_byteorder() == BU_BIG_ENDIAN) && (ximage_p->byte_order ==
LSBFirst)) ||
+ ((bu_byteorder() == BU_LITTLE_ENDIAN) && (ximage_p->byte_order ==
MSBFirst))) {
+ DM_REVERSE_COLOR_BYTE_ORDER(red_shift, ximage_p->red_mask);
+ DM_REVERSE_COLOR_BYTE_ORDER(green_shift, ximage_p->green_mask);
+ DM_REVERSE_COLOR_BYTE_ORDER(blue_shift, ximage_p->blue_mask);
+ }
+
+ } else if (bytes_per_pixel == 2) {
+ unsigned long mask;
+ unsigned long tmask;
+ int bpb = 8; /* bits per byte */
+
+ /*XXX
+ * This section probably needs logic similar
+ * to the previous section (i.e. bytes_per_pixel == 4).
+ * That is we may need to reverse things depending on
+ * the image byte order and the system's byte order.
+ */
+
+ mask = ximage_p->red_mask;
+ tmask = 1;
+ for (red_shift = 0; red_shift < 16; red_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (red_bits = red_shift; red_bits < 16; red_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+
+ red_bits = red_bits - red_shift;
+ if (red_shift == 0)
+ red_shift = red_bits - bpb;
+ else
+ red_shift = red_shift - (bpb - red_bits);
+
+ mask = ximage_p->green_mask;
+ tmask = 1;
+ for (green_shift = 0; green_shift < 16; green_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (green_bits = green_shift; green_bits < 16; green_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+
+ green_bits = green_bits - green_shift;
+ green_shift = green_shift - (bpb - green_bits);
+
+ mask = ximage_p->blue_mask;
+ tmask = 1;
+ for (blue_shift = 0; blue_shift < 16; blue_shift++) {
+ if (tmask & mask)
+ break;
+ tmask = tmask << 1;
+ }
+ for (blue_bits = blue_shift; blue_bits < 16; blue_bits++) {
+ if (!(tmask & mask))
+ break;
+ tmask = tmask << 1;
+ }
+ blue_bits = blue_bits - blue_shift;
+
+ if (blue_shift == 0)
+ blue_shift = blue_bits - bpb;
+ else
+ blue_shift = blue_shift - (bpb - blue_bits);
+ } else {
+ if (msgs) {
+ bu_vls_printf(msgs, "png: %d bytes per pixel is not yet
supported\n", bytes_per_pixel);
+ }
+ png_destroy_write_struct(&png_p, &info_p);
+ return -1;
+ }
+
+ rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char
*), "rows");
+ idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, 4,
"png data");
+
+ /* for each scanline */
+ for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {
+ /* irow points to the current scanline in ximage_p */
+ irow = (unsigned char *)(ximage_p->data +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
+
+ if (bytes_per_pixel == 4) {
+ unsigned int pixel;
+
+ /* rows[j] points to the current scanline in idata */
+ rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
+
+ /* for each pixel in current scanline of ximage_p */
+ for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
+ pixel = *((unsigned int *)(irow + k));
+
+ dbyte0 = rows[j] + k;
+ dbyte1 = dbyte0 + 1;
+ dbyte2 = dbyte0 + 2;
+ dbyte3 = dbyte0 + 3;
+
+ *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+ *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+ *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+ *dbyte3 = 255;
+ }
+ } else if (bytes_per_pixel == 2) {
+ unsigned short spixel;
+ unsigned long pixel;
+
+ /* rows[j] points to the current scanline in idata */
+ rows[j] = (unsigned char *)(idata +
((ximage_p->height-i-1)*ximage_p->bytes_per_line*2));
+
+ /* for each pixel in current scanline of ximage_p */
+ for (k = 0; k < ximage_p->bytes_per_line; k += bytes_per_pixel) {
+ spixel = *((unsigned short *)(irow + k));
+ pixel = spixel;
+
+ dbyte0 = rows[j] + k*2;
+ dbyte1 = dbyte0 + 1;
+ dbyte2 = dbyte0 + 2;
+ dbyte3 = dbyte0 + 3;
+
+ if (0 <= red_shift)
+ *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+ else
+ *dbyte0 = (pixel & ximage_p->red_mask) << -red_shift;
+
+ *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+
+ if (0 <= blue_shift)
+ *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+ else
+ *dbyte2 = (pixel & ximage_p->blue_mask) << -blue_shift;
+
+ *dbyte3 = 255;
+ }
+ } else {
+ bu_free(rows, "rows");
+ bu_free(idata, "image data");
+ png_destroy_write_struct(&png_p, &info_p);
+ if (msgs) {
+ bu_vls_printf(msgs, "png: not supported for this platform\n");
+ }
+ return -1;
+ }
+ }
+
+ png_init_io(png_p, fp);
+ png_set_filter(png_p, 0, PNG_FILTER_NONE);
+ png_set_compression_level(png_p, 9);
+ png_set_IHDR(png_p, info_p, ximage_p->width, ximage_p->height,
bits_per_channel,
+ PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_set_gAMA(png_p, info_p, 0.77);
+ png_write_info(png_p, info_p);
+ png_write_image(png_p, rows);
+ png_write_end(png_p, NULL);
+
+ png_destroy_write_struct(&png_p, &info_p);
+
+ bu_free(rows, "rows");
+ bu_free(idata, "image data");
+
+ return 0;
+}
+
struct dm_impl dm_ogl_impl = {
ogl_close,
ogl_drawBegin,
@@ -2665,7 +2926,7 @@
ogl_put_internal,
ogl_geometry_request,
ogl_internal_var,
- NULL,
+ ogl_write_image,
0,
1, /* has displaylist */
0, /* no stereo by default */
Modified: brlcad/branches/dm-fb-merge/src/libdm/include/calltable.h
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/include/calltable.h 2020-04-17
15:21:55 UTC (rev 75436)
+++ brlcad/branches/dm-fb-merge/src/libdm/include/calltable.h 2020-04-17
16:14:01 UTC (rev 75437)
@@ -96,7 +96,7 @@
int (*dm_put_internal)(struct dm *dmp);
int (*dm_geometry_request)(struct dm *dmp, int width, int height);
int (*dm_internal_var)(struct bu_vls *result, struct dm *dmp, const char
*key);
- png_structp (*dm_get_image)(struct dm *dmp);
+ int (*dm_write_image)(struct bu_vls *msgs, FILE *fp, struct dm *dmp);
unsigned long dm_id; /**< @brief window id */
int dm_displaylist; /**< @brief !0 means device has
displaylist */
int dm_stereo; /**< @brief stereo flag */
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits