00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032 #include <string.h>
00033
00034 #include <cxmemory.h>
00035 #include <cxmessages.h>
00036
00037 #include <cpl_error.h>
00038 #include <cpl_image.h>
00039 #include <cpl_imagelist.h>
00040
00041 #include "gialias.h"
00042 #include "gierror.h"
00043 #include "gicube.h"
00044 #include "giutils.h"
00045
00046
00055 enum GiCubeAxes {
00056 GICUBE_X = 0,
00057 GICUBE_Y = 1,
00058 GICUBE_Z = 2,
00059 GICUBE_AXES
00060 };
00061
00062 typedef enum GiCubeAxes GiCubeAxes;
00063
00064
00065 struct GiCubeAxis {
00066 cxdouble start;
00067 cxdouble step;
00068 };
00069
00070 typedef struct GiCubeAxis GiCubeAxis;
00071
00072
00073 struct GiCube {
00074 cxsize width;
00075 cxsize height;
00076 cxsize depth;
00077 cxsize size;
00078
00079 GiCubeAxis* axes[GICUBE_AXES];
00080
00081 cxdouble* pixels;
00082
00083 cpl_imagelist* planes;
00084 };
00085
00086
00087 inline static void
00088 _giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height,
00089 cxsize depth)
00090 {
00091
00092 self->width = width;
00093 self->height = height;
00094 self->depth = depth;
00095
00096 self->size = self->width * self->height * self->depth;
00097
00098 return;
00099
00100 }
00101
00102
00103 inline static GiCube*
00104 _giraffe_cube_new(void)
00105 {
00106
00107 GiCube* self = cx_malloc(sizeof *self);
00108
00109
00110 if (self != NULL) {
00111 _giraffe_cube_set_size(self, 0, 0, 0);
00112
00113 self->axes[GICUBE_X] = NULL;
00114 self->axes[GICUBE_Y] = NULL;
00115 self->axes[GICUBE_Z] = NULL;
00116
00117 self->pixels = NULL;
00118 self->planes = NULL;
00119 }
00120
00121 return self;
00122
00123 }
00124
00125
00126 inline static cxint
00127 _giraffe_cube_init_planes(GiCube* self)
00128 {
00129
00130 register cxsize i = 0;
00131
00132 register cxdouble* base = NULL;
00133
00134
00135 self->planes = cpl_imagelist_new();
00136 cx_assert(self->planes != NULL);
00137
00138
00139 base = self->pixels;
00140
00141 for (i = 0; i < self->depth; i++) {
00142
00143 cpl_image* plane = cpl_image_wrap_double(self->width, self->height,
00144 base);
00145
00146 cx_assert(plane != NULL);
00147 cpl_imagelist_set(self->planes, plane, i);
00148
00149 base += self->width * self->height;
00150
00151 }
00152
00153 return 0;
00154
00155 }
00156
00157
00158 inline static void
00159 _giraffe_cube_clear_planes(GiCube* self)
00160 {
00161
00162 register cxsize i = 0;
00163
00164
00165 for (i = 0; i < self->depth; i++) {
00166
00167 cpl_image* plane = cpl_imagelist_unset(self->planes, 0);
00168
00169 cpl_image_unwrap(plane);
00170
00171 }
00172
00173 cx_assert(cpl_imagelist_get_size(self->planes) == 0);
00174
00175 cpl_imagelist_delete(self->planes);
00176 self->planes =NULL;
00177
00178 return;
00179
00180 }
00181
00182
00183 inline static void
00184 _giraffe_cube_delete(GiCube* self)
00185 {
00186
00187 register cxint i = 0;
00188
00189 for (i = 0; i < GICUBE_AXES; i++) {
00190 if (self->axes[i] != NULL) {
00191 cx_free(self->axes[i]);
00192 self->axes[i] = NULL;
00193 }
00194 }
00195
00196 if (self->planes != NULL) {
00197 _giraffe_cube_clear_planes(self);
00198 self->planes = NULL;
00199 }
00200
00201 if (self->pixels != NULL) {
00202 cx_free(self->pixels);
00203 self->pixels = NULL;
00204 }
00205
00206 cx_free(self);
00207
00208 return;
00209
00210 }
00211
00212
00213 inline static cxint
00214 _giraffe_cube_get_axis(const GiCube* self, GiCubeAxes axis, cxdouble* start,
00215 cxdouble* step)
00216 {
00217
00218 if (self->axes[axis] == NULL) {
00219 return 1;
00220 }
00221 else {
00222
00223 if (start != NULL) {
00224 *start = self->axes[axis]->start;
00225 }
00226
00227 if (step != NULL) {
00228 *step = self->axes[axis]->step;
00229 }
00230
00231 }
00232
00233 return 0;
00234
00235 }
00236
00237
00238 inline static cxint
00239 _giraffe_cube_set_axis(GiCube* self, GiCubeAxes axis, cxdouble start,
00240 cxdouble step)
00241 {
00242
00243 if (self->axes[axis] == NULL) {
00244 self->axes[axis] = cx_calloc(1, sizeof(GiCubeAxis));
00245 }
00246
00247 cx_assert(self->axes[axis] != NULL);
00248
00249 self->axes[axis]->start = start;
00250 self->axes[axis]->step = step;
00251
00252 return 0;
00253
00254 }
00255
00256
00269 GiCube*
00270 giraffe_cube_new(void)
00271 {
00272
00273 return _giraffe_cube_new();
00274
00275 }
00276
00277
00304 GiCube*
00305 giraffe_cube_create(cxsize width, cxsize height, cxsize depth, cxdouble* data)
00306 {
00307
00308 GiCube* self = _giraffe_cube_new();
00309
00310
00311 _giraffe_cube_set_size(self, width, height, depth);
00312
00313 if (self->size == 0) {
00314 _giraffe_cube_delete(self);
00315 return NULL;
00316 }
00317
00318 if (data != NULL) {
00319 self->pixels = data;
00320 }
00321 else {
00322 self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00323 }
00324
00325 cx_assert(self->pixels != NULL);
00326
00327
00328
00329
00330
00331
00332
00333 giraffe_error_push();
00334
00335 _giraffe_cube_init_planes(self);
00336
00337 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00338 _giraffe_cube_delete(self);
00339 return NULL;
00340 }
00341
00342 giraffe_error_pop();
00343
00344 return self;
00345
00346 }
00347
00348
00361 void
00362 giraffe_cube_delete(GiCube* self)
00363 {
00364
00365 if (self != NULL) {
00366 _giraffe_cube_delete(self);
00367 }
00368
00369 return;
00370
00371 }
00372
00373
00387 cxsize
00388 giraffe_cube_get_width(const GiCube* self)
00389 {
00390
00391 cx_assert(self != NULL);
00392 return self->width;
00393
00394 }
00395
00396
00410 cxsize
00411 giraffe_cube_get_height(const GiCube* self)
00412 {
00413
00414 cx_assert(self != NULL);
00415 return self->height;
00416
00417 }
00418
00419
00433 cxsize
00434 giraffe_cube_get_depth(const GiCube* self)
00435 {
00436
00437 cx_assert(self != NULL);
00438 return self->depth;
00439
00440 }
00441
00442
00456 cxsize
00457 giraffe_cube_get_size(const GiCube* self)
00458 {
00459
00460 cx_assert(self != NULL);
00461 return self->size;
00462
00463 }
00464
00465
00484 cxint
00485 giraffe_cube_set_size(GiCube* self, cxsize width, cxsize height, cxsize depth)
00486 {
00487
00488 const cxchar* const _id = "giraffe_cube_set_size";
00489
00490
00491 cx_assert(self != NULL);
00492
00493 if ((width == 0) || (height == 0) || (depth == 0)) {
00494 cpl_error_set(_id, CPL_ERROR_ILLEGAL_INPUT);
00495 return 1;
00496 }
00497
00498 if ((self->width == width) && (self->height == height) &&
00499 (self->depth == depth)) {
00500 memset(self->pixels, 0, self->size * sizeof(cxdouble));
00501 }
00502 else {
00503
00504
00505
00506
00507
00508 if (self->planes != NULL) {
00509 _giraffe_cube_clear_planes(self);
00510 }
00511
00512 if (self->pixels != NULL) {
00513 cx_free(self->pixels);
00514 }
00515
00516
00517
00518
00519
00520
00521 _giraffe_cube_set_size(self, width, height, depth);
00522
00523
00524
00525
00526
00527
00528
00529 self->pixels = cx_calloc(self->size, sizeof(cxdouble));
00530 cx_assert(self->pixels);
00531
00532
00533 giraffe_error_push();
00534
00535 _giraffe_cube_init_planes(self);
00536
00537 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00538 return 1;
00539 }
00540
00541 giraffe_error_pop();
00542
00543 }
00544
00545 return 0;
00546
00547 }
00548
00549
00564 cxdouble*
00565 giraffe_cube_get_data(const GiCube* self)
00566 {
00567
00568 const cxchar* const _id = "giraffe_cube_get_data";
00569
00570
00571 if (self == NULL) {
00572 cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
00573 return 0;
00574 }
00575
00576 return self->pixels;
00577
00578 }
00579
00580
00601 cxint
00602 giraffe_cube_get_xaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00603 {
00604
00605 cx_assert(self != NULL);
00606
00607 return _giraffe_cube_get_axis(self, GICUBE_X, start, step);
00608
00609 }
00610
00611
00632 cxint
00633 giraffe_cube_get_yaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00634 {
00635
00636 cx_assert(self != NULL);
00637
00638 return _giraffe_cube_get_axis(self, GICUBE_Y, start, step);
00639
00640 }
00641
00642
00663 cxint
00664 giraffe_cube_get_zaxis(const GiCube* self, cxdouble* start, cxdouble* step)
00665 {
00666
00667 cx_assert(self != NULL);
00668
00669 return _giraffe_cube_get_axis(self, GICUBE_Z, start, step);
00670
00671 }
00672
00673
00689 cxint
00690 giraffe_cube_set_xaxis(GiCube* self, cxdouble start, cxdouble step)
00691 {
00692
00693 cx_assert(self != NULL);
00694
00695 return _giraffe_cube_set_axis(self, GICUBE_X, start, step);
00696
00697 }
00698
00699
00715 cxint
00716 giraffe_cube_set_yaxis(GiCube* self, cxdouble start, cxdouble step)
00717 {
00718
00719 cx_assert(self != NULL);
00720
00721 return _giraffe_cube_set_axis(self, GICUBE_Y, start, step);
00722
00723 }
00724
00725
00741 cxint
00742 giraffe_cube_set_zaxis(GiCube* self, cxdouble start, cxdouble step)
00743 {
00744
00745 cx_assert(self != NULL);
00746
00747 return _giraffe_cube_set_axis(self, GICUBE_Z, start, step);
00748
00749 }
00750
00751
00769 cxint
00770 giraffe_cube_save(const GiCube* self, cpl_propertylist* properties,
00771 const cxchar* filename, cxcptr data)
00772 {
00773
00774 cxbool xaxis = FALSE;
00775 cxbool yaxis = FALSE;
00776 cxbool zaxis = FALSE;
00777
00778 cxdouble xstart = 0.;
00779 cxdouble xstep = 0.;
00780 cxdouble ystart = 0.;
00781 cxdouble ystep = 0.;
00782 cxdouble zstart = 0.;
00783 cxdouble zstep = 0.;
00784
00785
00786
00787 data = NULL;
00788
00789 if (self == NULL || properties == NULL || filename == NULL) {
00790 return -1;
00791 }
00792
00793
00794
00795
00796
00797
00798
00799 if (giraffe_cube_get_xaxis(self, &xstart, &xstep) == 0) {
00800 xaxis = TRUE;
00801 }
00802
00803 if (giraffe_cube_get_yaxis(self, &ystart, &ystep) == 0) {
00804 yaxis = TRUE;
00805 }
00806
00807 if (giraffe_cube_get_zaxis(self, &zstart, &zstep) == 0) {
00808 zaxis = TRUE;
00809 }
00810
00811
00812 if ((xaxis == TRUE) && (yaxis == TRUE) && (zaxis == TRUE)) {
00813
00814 const cxchar* ctype[] = {"PIXEL", "PIXEL", "WAVE"};
00815 const cxchar* cunit[] = {"pixel", "pixel", "nm"};
00816
00817 cxint status = 0;
00818
00819 cxdouble crpix[] = {1., 1., 1.};
00820 cxdouble crval[] = {xstart, ystart, zstart};
00821
00822 cpl_matrix* cd = cpl_matrix_new(3, 3);
00823
00824 cpl_matrix_set(cd, 0, 0, xstep);
00825 cpl_matrix_set(cd, 1, 1, ystep);
00826 cpl_matrix_set(cd, 2, 2, zstep);
00827
00828 status = giraffe_propertylist_update_wcs(properties, 3, crpix, crval,
00829 ctype, cunit, cd);
00830
00831 if (status != 0) {
00832 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
00833 NULL, NULL);
00834 }
00835
00836 cpl_matrix_delete(cd);
00837 cd = NULL;
00838
00839 }
00840 else {
00841
00842 giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
00843 NULL, NULL);
00844
00845 }
00846
00847 giraffe_error_push();
00848
00849 cpl_imagelist_save(self->planes, filename, CPL_BPP_IEEE_FLOAT,
00850 properties, CPL_IO_DEFAULT);
00851
00852 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00853 return 1;
00854 }
00855
00856 giraffe_error_pop();
00857
00858 return 0;
00859
00860 }