666{
671 int numbands = 0;
672
674 int width = 0;
675 int height = 0;
676
677 ArrayType *array;
678 Oid etype;
679 Datum *elements;
680 bool *nulls;
681 int16 typlen;
682 bool typbyval;
683 char typalign;
684 int ndims = 1;
685 int *dims;
686 int num = 0;
687
688 int ul[2] = {0};
689 struct pixelvalue {
692
693 bool noset;
694 bool nodata;
696 };
697 struct pixelvalue *
pixval = NULL;
698 int numpixval = 0;
699 int dimpixval[2] = {1, 1};
700 int dimnoset[2] = {1, 1};
701 int hasnodata =
FALSE;
702 double nodataval = 0;
703 bool keepnodata =
FALSE;
704 bool hasnosetval =
FALSE;
705 bool nosetvalisnull =
FALSE;
706 double nosetval = 0;
707
708 int rtn = 0;
709 double val = 0;
710 int isnodata = 0;
711
712 int i = 0;
713 int j = 0;
716
717
718 if (PG_ARGISNULL(0))
719 PG_RETURN_NULL();
720 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
721
722
724 if (!raster) {
725 PG_FREE_IF_COPY(pgraster, 0);
726 elog(ERROR, "RASTER_setPixelValuesArray: Could not deserialize raster");
727 PG_RETURN_NULL();
728 }
729
730
734
735
736 if (PG_ARGISNULL(1)) {
737 elog(NOTICE, "Band index cannot be NULL. Value must be 1-based. Returning original raster");
739 PG_RETURN_POINTER(pgraster);
740 }
741
742 nband = PG_GETARG_INT32(1);
743 if (nband < 1 || nband > numbands) {
744 elog(NOTICE, "Band index is invalid. Value must be 1-based. Returning original raster");
746 PG_RETURN_POINTER(pgraster);
747 }
748
749
750 for (i = 2, j = 0; i < 4; i++, j++) {
751 if (PG_ARGISNULL(i)) {
752 elog(NOTICE, "%s cannot be NULL. Value must be 1-based. Returning original raster", j < 1 ? "X" : "Y");
754 PG_RETURN_POINTER(pgraster);
755 }
756
757 ul[j] = PG_GETARG_INT32(i);
758 if (
759 (ul[j] < 1) || (
760 (j < 1 && ul[j] > width) ||
761 (j > 0 && ul[j] > height)
762 )
763 ) {
764 elog(NOTICE, "%s is invalid. Value must be 1-based. Returning original raster", j < 1 ? "X" : "Y");
766 PG_RETURN_POINTER(pgraster);
767 }
768
769
770 ul[j] -= 1;
771 }
772
773
774 if (PG_ARGISNULL(4)) {
775 elog(NOTICE, "No values to set. Returning original raster");
777 PG_RETURN_POINTER(pgraster);
778 }
779
780 array = PG_GETARG_ARRAYTYPE_P(4);
781 etype = ARR_ELEMTYPE(array);
782 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
783
784 switch (etype) {
785 case FLOAT4OID:
786 case FLOAT8OID:
787 break;
788 default:
790 PG_FREE_IF_COPY(pgraster, 0);
791 elog(ERROR, "RASTER_setPixelValuesArray: Invalid data type for new values");
792 PG_RETURN_NULL();
793 break;
794 }
795
796 ndims = ARR_NDIM(array);
797 dims = ARR_DIMS(array);
799
800 if (ndims < 1 || ndims > 2) {
801 elog(NOTICE, "New values array must be of 1 or 2 dimensions. Returning original raster");
803 PG_RETURN_POINTER(pgraster);
804 }
805
806
807
808 if (ndims != 2)
809 dimpixval[1] = dims[0];
810 else {
811 dimpixval[0] = dims[0];
812 dimpixval[1] = dims[1];
813 }
815
816 deconstruct_array(
817 array,
818 etype,
819 typlen, typbyval, typalign,
820 &elements, &nulls, &num
821 );
822
823
824 if (num < 1 || num != (dimpixval[0] * dimpixval[1])) {
825 if (num) {
826 pfree(elements);
827 pfree(nulls);
828 }
830 PG_FREE_IF_COPY(pgraster, 0);
831 elog(ERROR, "RASTER_setPixelValuesArray: Could not deconstruct new values array");
832 PG_RETURN_NULL();
833 }
834
835
836 numpixval = num;
837 pixval = palloc(
sizeof(
struct pixelvalue) * numpixval);
839 pfree(elements);
840 pfree(nulls);
842 PG_FREE_IF_COPY(pgraster, 0);
843 elog(ERROR, "RASTER_setPixelValuesArray: Could not allocate memory for new pixel values");
844 PG_RETURN_NULL();
845 }
846
847
848 i = 0;
849 for (y = 0;
y < dimpixval[0];
y++) {
850 for (x = 0;
x < dimpixval[1];
x++) {
851
854
858
859 if (nulls[i])
861 else {
862 switch (etype) {
863 case FLOAT4OID:
864 pixval[i].value = DatumGetFloat4(elements[i]);
865 break;
866 case FLOAT8OID:
867 pixval[i].value = DatumGetFloat8(elements[i]);
868 break;
869 }
870 }
871
872 i++;
873 }
874 }
875
876 pfree(elements);
877 pfree(nulls);
878
879
880 if (!PG_ARGISNULL(5)) {
881 array = PG_GETARG_ARRAYTYPE_P(5);
882 etype = ARR_ELEMTYPE(array);
883 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
884
885 switch (etype) {
886 case BOOLOID:
887 break;
888 default:
891 PG_FREE_IF_COPY(pgraster, 0);
892 elog(ERROR, "RASTER_setPixelValuesArray: Invalid data type for noset flags");
893 PG_RETURN_NULL();
894 break;
895 }
896
897 ndims = ARR_NDIM(array);
898 dims = ARR_DIMS(array);
900
901 if (ndims < 1 || ndims > 2) {
902 elog(NOTICE, "Noset flags array must be of 1 or 2 dimensions. Returning original raster");
905 PG_RETURN_POINTER(pgraster);
906 }
907
908
909
910 if (ndims != 2)
911 dimnoset[1] = dims[0];
912 else {
913 dimnoset[0] = dims[0];
914 dimnoset[1] = dims[1];
915 }
917
918 deconstruct_array(
919 array,
920 etype,
921 typlen, typbyval, typalign,
922 &elements, &nulls, &num
923 );
924
925
926 if (num < 1 || num != (dimnoset[0] * dimnoset[1])) {
928 if (num) {
929 pfree(elements);
930 pfree(nulls);
931 }
933 PG_FREE_IF_COPY(pgraster, 0);
934 elog(ERROR, "RASTER_setPixelValuesArray: Could not deconstruct noset flags array");
935 PG_RETURN_NULL();
936 }
937
938 i = 0;
939 j = 0;
940 for (y = 0;
y < dimnoset[0];
y++) {
941 if (y >= dimpixval[0]) break;
942
943 for (x = 0;
x < dimnoset[1];
x++) {
944
945 if (x >= dimpixval[1]) {
946 i += (dimnoset[1] - dimpixval[1]);
947 break;
948 }
949
950 if (!nulls[i] && DatumGetBool(elements[i]))
952
953 i++;
954 j++;
955 }
956
957
958 if (x < dimpixval[1])
959 j += (dimpixval[1] - dimnoset[1]);
960 }
961
962 pfree(elements);
963 pfree(nulls);
964 }
965
966 else if (!PG_ARGISNULL(6) && PG_GETARG_BOOL(6)) {
968 if (PG_ARGISNULL(7))
969 nosetvalisnull =
TRUE;
970 else
971 nosetval = PG_GETARG_FLOAT8(7);
972 }
973
974#if POSTGIS_DEBUG_LEVEL > 0
975 for (i = 0; i < numpixval; i++) {
976 POSTGIS_RT_DEBUGF(4,
"pixval[%d](x, y, noset, nodata, value) = (%d, %d, %d, %d, %f)",
977 i,
983 );
984 }
985#endif
986
987
988 if (!PG_ARGISNULL(8))
989 keepnodata = PG_GETARG_BOOL(8);
990
991
993 if (!band) {
994 elog(NOTICE, "Could not find band at index %d. Returning original raster", nband);
997 PG_RETURN_POINTER(pgraster);
998 }
999
1000
1001
1003 if (hasnodata)
1005
1006 else
1008
1009
1010 for (i = 0; i < numpixval; i++) {
1011
1013 continue;
1014
1015 else if (hasnosetval) {
1016
1017 if (
pixval[i].nodata && nosetvalisnull)
1018 continue;
1019
1021 continue;
1022 }
1023
1024
1025 if (
1028 ) {
1029 elog(NOTICE, "Cannot set value for pixel (%d, %d) outside raster bounds: %d x %d",
1031 width, height
1032 );
1033 continue;
1034 }
1035
1036
1037 if (hasnodata && keepnodata) {
1042 PG_FREE_IF_COPY(pgraster, 0);
1043 elog(ERROR, "Cannot get value of pixel");
1044 PG_RETURN_NULL();
1045 }
1046
1047
1048 if (isnodata) {
1049 continue;
1050 }
1051 }
1052
1055 else
1057 }
1058
1060
1061
1064 PG_FREE_IF_COPY(pgraster, 0);
1065 if (!pgrtn)
1066 PG_RETURN_NULL();
1067
1068 SET_VARSIZE(pgrtn, pgrtn->
size);
1069 PG_RETURN_POINTER(pgrtn);
1070}
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
uint16_t rt_raster_get_width(rt_raster raster)
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
#define POSTGIS_RT_DEBUGF(level, msg,...)