| 5057 | } |
| 5058 | |
| 5059 | GMT_LOCAL int gmtapi_export_ppm (struct GMT_CTRL *GMT, char *fname, struct GMT_IMAGE *I) { |
| 5060 | /* Write a Portable Pixel Map (PPM) file if fname extension is .ppm, else returns 1. |
| 5061 | * We assume there is no pad, otherwise the pad will be part of the image on output. */ |
| 5062 | //uint32_t row, col, band; |
| 5063 | static char *comment = "# Produced by GMT\n"; |
| 5064 | char *ext = gmt_get_ext (fname), dim[GMT_LEN32] = {""}; |
| 5065 | size_t n; |
| 5066 | FILE *fp = NULL; |
| 5067 | if (ext == NULL || strcmp (ext, "ppm")) return GMT_NOT_A_VALID_FAMILY; /* Not requesting a PPM file - return GMT_NOT_A_VALID_FAMILY and let GDAL take over */ |
| 5068 | |
| 5069 | if ((fp = gmt_fopen (GMT, fname, GMT->current.io.w_mode)) == NULL) { /* Return GMT_ERROR_ON_FOPEN to signify failure */ |
| 5070 | GMT_Report (GMT->parent, GMT_MSG_ERROR, "Cannot create PPM file %s\n", fname); |
| 5071 | return GMT_ERROR_ON_FOPEN; |
| 5072 | } |
| 5073 | if (I->header->n_bands == 1) /* Use P5 for grayscale image */ |
| 5074 | n = fwrite ("P5\n", sizeof (char), 3U, fp); /* Write magic number, linefeed */ |
| 5075 | else /* Use P6 for rgb image */ |
| 5076 | n = fwrite ("P6\n", sizeof (char), 3U, fp); /* Write magic number, linefeed */ |
| 5077 | if (n != 3U) { |
| 5078 | gmt_fclose (GMT, fp); |
| 5079 | return GMT_IMAGE_WRITE_ERROR; |
| 5080 | } |
| 5081 | n = strlen (comment); |
| 5082 | if (fwrite (comment, sizeof (char), n, fp) != n) { |
| 5083 | gmt_fclose (GMT, fp); |
| 5084 | return GMT_IMAGE_WRITE_ERROR; /* Write comment and linefeed */ |
| 5085 | } |
| 5086 | snprintf (dim, GMT_LEN32, "%d %d\n255\n", I->header->mx, I->header->my); |
| 5087 | n = strlen (dim); |
| 5088 | if (fwrite (dim, sizeof (char), n, fp) != n) return GMT_IMAGE_WRITE_ERROR; /* Write dimensions and max color value + linefeeds */ |
| 5089 | /* Now dump the image in scanline order, with each pixel as (R, G, B) */ |
| 5090 | if (I->alpha) |
| 5091 | GMT_Report (GMT->parent, GMT_MSG_ERROR, "Alpha-channel not supported by PPM format - ignored\n"); |
| 5092 | n = I->header->size * I->header->n_bands; |
| 5093 | if (!strncmp (I->header->mem_layout, "TRP", 3U)) { /* Easy street! */ |
| 5094 | if (fwrite (I->data, sizeof(char), n, fp) != n) { |
| 5095 | gmt_fclose (GMT, fp); |
| 5096 | return GMT_IMAGE_WRITE_ERROR; |
| 5097 | } |
| 5098 | } |
| 5099 | else { /* Must change image layout first as PPM is strictly TRP */ |
| 5100 | char *data = NULL; |
| 5101 | GMT_Report (GMT->parent, GMT_MSG_VERBOSE, "Must convert image from %s to TRP in order to write PPM file\n", I->header->mem_layout); |
| 5102 | if ((data = gmt_M_memory_aligned (GMT, NULL, n, char)) == NULL) { |
| 5103 | GMT_Report (GMT->parent, GMT_MSG_ERROR, "Unable to allocate image memory in gmtapi_export_ppm to force TRP format - written as is\n"); |
| 5104 | if (fwrite (I->data, sizeof(char), n, fp) != n) { |
| 5105 | gmt_fclose (GMT, fp); |
| 5106 | return GMT_IMAGE_WRITE_ERROR; |
| 5107 | } |
| 5108 | } |
| 5109 | else { /* Convert from TRB to TRP */ |
| 5110 | GMT_Change_Layout (GMT->parent, GMT_IS_IMAGE, "TRP", 0, I, data, NULL); |
| 5111 | if (fwrite (data, sizeof(char), n, fp) != n) return GMT_IMAGE_WRITE_ERROR; |
| 5112 | gmt_M_free_aligned (GMT, data); |
| 5113 | } |
| 5114 | } |
| 5115 | gmt_fclose (GMT, fp); |
| 5116 |
no test coverage detected