void pnm_ppm_free(ppm_t *ppm) { if (!ppm) return; if (ppm->pixels) ppm_freearray(ppm->pixels, ppm->rows); pnm_ppm_init(ppm); }
char* get_arr(int *rows, int *cols, char shapefile[]) { char *arr; int k, i, j; pixval maxval; pixel **pixels; FILE* ppmshape = fopen(shapefile, "r"); pixels = ppm_readppm(ppmshape, cols, rows, &maxval); arr = (char*)malloc((*cols)*(*rows)); for(i = 0, k = 0; i < *rows; i++) for(j = 0; j < *cols; j++, k++) { char r, g, b; r = (0xff * PPM_GETR(pixels[i][j])) / maxval; g = (0xff * PPM_GETR(pixels[i][j])) / maxval; b = (0xff * PPM_GETR(pixels[i][j])) / maxval; if(r==0 && b==0 && g==0) arr[k] = 0; else arr[k] = 0xff; } ppm_freearray(pixels, *rows); return arr; }
static void destroyCanvas(canvas * const canvasP) { ppm_freearray(canvasP->pixels, canvasP->height); free(canvasP); }
unsigned char* CircularBuffer::bufferFromImage(char *photoLocation) { pixel** pixarray; FILE *fp; int cols, rows; pixval maxval; register int x, y; unsigned char *buf=NULL; if ((fp = fopen (photoLocation,"r")) == NULL) { fprintf (stderr, "%s: Can't open input file:\n %s.\n", photoLocation); exit (1); } pixarray = ppm_readppm (fp, &cols, &rows, &maxval); fclose (fp); if (buf == NULL) buf = (unsigned char *)malloc(IMG_SIZE); /* Use this double 'for loop' in the consumer/client threads. * You'll need to modify this code to read from a socket into * a data structure called "pixarray" first. */ for (y = 0; y < rows; y++) { for (x = 0; x < cols; x++) { buf[(y*cols+x)*3+0] = PPM_GETR(pixarray[rows-y-1][x]); buf[(y*cols+x)*3+1] = PPM_GETG(pixarray[rows-y-1][x]); buf[(y*cols+x)*3+2] = PPM_GETB(pixarray[rows-y-1][x]); } } ppm_freearray (pixarray, rows); return buf; }
/** frees the data */ void GeoImage::freeData() { if (data_) { switch (type_) { case PBM: pbm_freearray(data_, rows_); break; case PGM: pgm_freearray(data_, rows_); break; case PPM: ppm_freearray(data_, rows_); break; case PFM_3BYTE:{ PFM3Byte *ppmbuf = (PFM3Byte *) data_; free(ppmbuf->r); free(ppmbuf->g); free(ppmbuf->b); free(data_); } break; default: free(data_); break; } data_ = 0; dataSize_=0; } }
static void readPpmPalette(const char * const paletteFileName, pixel (* const ppmPaletteP)[], unsigned int * const paletteSizeP) { FILE * pfP; pixel ** pixels; int cols, rows; pixval maxval; pfP = pm_openr(paletteFileName); pixels = ppm_readppm(pfP, &cols, &rows, &maxval); pm_close(pfP); *paletteSizeP = rows * cols; if (*paletteSizeP > MAXCOLORS) pm_error("ordered palette image contains %d pixels. Maximum is %d", *paletteSizeP, MAXCOLORS); { int j; int row; j = 0; /* initial value */ for (row = 0; row < rows; ++row) { int col; for (col = 0; col < cols; ++col) (*ppmPaletteP)[j++] = pixels[row][col]; } } ppm_freearray(pixels, rows); }
bool saveAsPPM(const std::unique_ptr<Image>& img_ptr, const char* filepath) { FILE* fp = fopen(filepath, "wb"); if (!fp) { printf("error loading file %s at saveAsPPM()\n", filepath); return false; } const size_t w = img_ptr->getWidth(); const size_t h = img_ptr->getHeight(); const pixval maxVal = 255; pixel** pxls = ppm_allocarray(w, h); if (!pxls) { printf("error allocating memory space at saveAsPPM()"); fclose(fp); return false; } for (size_t y = 0; y < h; y++) { for (size_t x = 0; x < w; x++) { if (img_ptr->getChannelNum() >= 3) { float vclip[3]; for (size_t c = 0; c < 3; c++) { vclip[c] = (img_ptr->getValues(c))[y*w + x]; if (vclip[c] < 0) vclip[c] = 0; if (vclip[c] > 1) vclip[c] = 1; } pxls[y][x].r = static_cast<pixval>(vclip[0] * maxVal); pxls[y][x].g = static_cast<pixval>(vclip[1] * maxVal); pxls[y][x].b = static_cast<pixval>(vclip[2] * maxVal); } else { float vclip = (img_ptr->getValues(0))[y*w + x]; if (vclip < 0) vclip = 0; if (vclip > 1) vclip = 1; pxls[y][x].r = static_cast<pixval>(vclip * maxVal); pxls[y][x].g = static_cast<pixval>(vclip * maxVal); pxls[y][x].b = static_cast<pixval>(vclip * maxVal); } } } ppm_writeppm(fp, pxls, w, h, maxVal, 0); ppm_freearray(pxls, h); fclose(fp); return true; }
int main(int argc, char **argv) { FILE *ifp; pixel **pixels; int rows, row, cols, col, pal_len, i; pixval maxval; struct cmdlineInfo cmdline; unsigned char rgb[NUM_COLORS][3]; char ansi_code[NUM_COLORS][MAX_ANSI_STR_LEN]; ppm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); ifp = pm_openr(cmdline.inputFilespec); pixels = ppm_readppm(ifp, &cols, &rows, &maxval); pm_close(ifp); pal_len=generate_palette(rgb, ansi_code); for (row = 0; row < rows; ++row) { for (col = 0; col < cols; col++) { pixval const r=(int)PPM_GETR(pixels[row][col])*255/maxval; pixval const g=(int)PPM_GETG(pixels[row][col])*255/maxval; pixval const b=(int)PPM_GETB(pixels[row][col])*255/maxval; int val, dist; /* The following loop calculates the index that corresponds to the minimum color distance between the given RGB values and the values available in the palette. */ for(i=0, dist=sqr(255)*3, val=0; i<pal_len; i++) { pixval const pr=rgb[i][0]; pixval const pg=rgb[i][1]; pixval const pb=rgb[i][2]; unsigned int j; if( (j=sqr(r-pr)+sqr(b-pb)+sqr(g-pg))<dist ) { dist=j; val=i; } } printf("%s%c", ansi_code[val],0xB1); } printf(ESC"\x30m\n"); } printf(ESC"\x30m"); ppm_freearray(pixels, rows); exit(0); }
static void doOneImage(FILE * const ifP, struct script * const scriptP) { pixel ** pixels; pixval maxval; int rows, cols; pixels = ppm_readppm(ifP, &cols, &rows, &maxval); executeScript(scriptP, pixels, cols, rows, maxval); ppm_writeppm(stdout, pixels, cols, rows, maxval, 0); ppm_freearray(pixels, rows); }
void process_file(const char *fname) { FILE *in; int codec, num_images, format; int i; int width, height, size, maxval; unsigned char *data; pixel **img; in = fopen(fname, "rb"); if (in == NULL) { perror(fname); exit(1); } read_header(in, &codec, &num_images, &format); for (i = 0; i < num_images; i++) { width = read_LEint32(in); height = read_LEint32(in); data = malloc(width * height * 2); if (codec == 0) read_data_codec0(in, width, height, data); else if (codec == 3) { size = read_LEint32(in); read_data_codec3(in, size, data); } else { fprintf(stderr, "%s: unsupported codec %d\n", fname, codec); exit(1); } if (format == 1) { img = toimg_fmt1(data, width, height); maxval = 255; } else if (format == 5) { img = toimg_fmt5(data, width, height); maxval = 255; } else { fprintf(stderr, "%s: unsupported format %d\n", fname, format); exit(1); } write_img(img, fname, i, width, height, maxval); free(data); ppm_freearray(img, height); } fclose(in); }
void savebmp(const char *filename, float wf, float hf, int dpi, std::vector< std::vector <Pixel> >* data) { /* Example program fragment to read a PAM or PNM image from stdin, add up the values of every sample in it (I don't know why), and write the image unchanged to stdout. */ FILE* f = fopen(filename,"wb"); pm_init(filename, 0); pixel** truePix = ppm_allocarray(wf,hf); for (int i = 0; i < wf; i++) { for (int j = 0; j < hf; j++) { PPM_ASSIGN(truePix[i][j],data->at(i).at(j).getColor()->getRed(), data->at(i).at(j).getColor()->getGreen(), data->at(i).at(j).getColor()->getBlue()); } } ppm_writeppm(f, truePix, (int)wf, (int)hf, 256, 0); ppm_freearray(truePix, (int)hf); }
static void convertWithMap(FILE * const ifP, unsigned int const cols, unsigned int const rows, gray const maxval, int const format, const char * const mapFileName, FILE * const ofP, gray * const grayrow, pixel * const pixelrow) { unsigned int row; FILE * mapFileP; int mapcols, maprows; pixval mapmaxval; pixel ** mappixels; unsigned int mapmaxcolor; mapFileP = pm_openr(mapFileName); mappixels = ppm_readppm(mapFileP, &mapcols, &maprows, &mapmaxval); pm_close(mapFileP); mapmaxcolor = maprows * mapcols - 1; ppm_writeppminit(ofP, cols, rows, mapmaxval, 0); for (row = 0; row < rows; ++row) { unsigned int col; pgm_readpgmrow(ifP, grayrow, cols, maxval, format); for (col = 0; col < cols; ++col) { unsigned int c; if (maxval == mapmaxcolor) c = grayrow[col]; else c = grayrow[col] * mapmaxcolor / maxval; pixelrow[col] = mappixels[c / mapcols][c % mapcols]; } ppm_writeppmrow(ofP, pixelrow, cols, mapmaxval, 0); } ppm_freearray(mappixels, maprows); }
void write_img(FILE *f, const char *fname, int n, int num_img) { FILE *out; int32_t width, height; int x, y; unsigned char p; pixel **img; char newname[1024]; const char *basename; fseek(f, 116 + 40 * (num_img - 1), SEEK_SET); width = read_LEint32(f); height = read_LEint32(f); img = ppm_allocarray(width, height); fseek(f, 100 + 40 * num_img + (width * height + 24) * n, SEEK_SET); for (y = 0; y < height; y++) for (x = 0; x < width; x++) { p = getc(f); img[y][x] = cmap[p]; } basename = strrchr(fname, '/'); if (basename != NULL) basename++; else basename = fname; strcpy(newname, basename); if (strlen(newname) > 4 && strcasecmp(newname + strlen(newname) - 4, ".mat") == 0) newname[strlen(newname) - 4] = '\0'; sprintf(newname + strlen(newname), "_%d.ppm", n); out = fopen(newname, "wb"); if (out == NULL) { perror(newname); exit(1); } ppm_writeppm(out, img, width, height, 255, 0); ppm_freearray(img, height); fclose(out); }
std::unique_ptr<Image> loadPGMImage(const char* filepath) { FILE* fp = fopen(filepath, "rb"); if (!fp) { printf("error loading file %s at loadPGMImage()\n", filepath); return std::unique_ptr<Image>(); } int img_w, img_h; gray max_pval; gray** pixels = pgm_readpgm(fp, &img_w, &img_h, &max_pval); if (!pixels) { printf("error reading image from file %s at loadPGMImage()\n", filepath); fclose(fp); return std::unique_ptr<Image>(); } auto img_ptr = std::make_unique<Image>(img_w, img_h, 3); for (int y = 0; y < img_h; y++) { for (int x = 0; x < img_w; x++) { (img_ptr->getValues(0))[y * img_w + x] = static_cast<float>(pixels[y][x]) / max_pval; (img_ptr->getValues(1))[y * img_w + x] = static_cast<float>(pixels[y][x]) / max_pval; (img_ptr->getValues(2))[y * img_w + x] = static_cast<float>(pixels[y][x]) / max_pval; } } ppm_freearray(pixels, img_h); fclose(fp); return img_ptr; }
/** write a scrap of the data, * return the filename, * if the file exist do nothing * argument fname is optional * the coordinates of the image part are geodata e.g. Gauss Krueger **/ QString GeoImage::part(float west, float north, float east, float south, QString fname) { if (fname.isEmpty()) { //create output filname Q_ASSERT(contains("key")); QString dir = CleanUp::getTmpDir(); fname.sprintf("%s/%s_%f_%f_%f_%f", dir.toLatin1().constData(), value("key").toLatin1().constData(), west, north, east, south); } qDebug("# GeoImage::part %s (%f, %f, %f, %f)", fname.toLatin1().constData(), west, north, east, south); QFile f(fname); if (f.exists()) return fname; const void *data_p = data(); //get pointer to data Q_ASSERT(data_p); if (type_ == UNKNOWN) return 0; int dx, dy, i, j, rx1, ry1, rx2, ry2; picBBox(west, north, east, south, rx1, ry2, rx2, ry1); dx = rx2 - rx1 + 1; dy = ry2 - ry1 + 1; if (dx <= 0 || dy <= 0) { qDebug("# (ERROR) GeoImage::part: (dx=%d=%d-%d || dy=%d=%d-%d)", dx, rx2, rx1, dy, ry2, ry1); throw ImageException(rx1,rx2,dx,ry1,ry2,dy); } FILE *of = fopen(fname.toLatin1().constData(), "w"); if (!of) { throw FileIOException(FileIOException::OPEN_FAILED,fname); } switch (type_) { case PBM:{ bit *bpi, *bpo, **dat_b_out = pbm_allocarray(dx, dy); bit **dat_b = (bit **) data_p; for (i = 0; i < dy; i++) { bpi = dat_b[i + ry1] + rx1; bpo = dat_b_out[i]; for (j = 0; j < dx; j++) { *bpo = *bpi; bpo++; bpi++; } } pbm_writepbm(of, (bit **) dat_b_out, dx, dy, 0); pbm_freearray(dat_b_out, dy); } break; case PGM:{ gray *gpi, *gpo, **dat_g_out = pgm_allocarray(dx, dy); gray **dat_g = (gray **) data_p; gray maxval = 0; for (i = 0; i < dy; i++) { gpi = dat_g[i + ry1] + rx1; gpo = dat_g_out[i]; for (j = 0; j < dx; j++) { *gpo = *gpi; if (*gpi > maxval) maxval = *gpi; gpo++; gpi++; } } pgm_writepgm(of, (gray **) dat_g_out, dx, dy, maxval, 0); pgm_freearray(dat_g_out, dy); } break; case PPM:{ pixel *ppi, *ppo, **dat_p_out = ppm_allocarray(dx, dy); pixel **dat_p = (pixel **) data_p; pixval maxval = 255; //! should be calculated for (i = 0; i < dy; i++) { ppi = dat_p[i + ry1] + rx1; ppo = dat_p_out[i]; for (j = 0; j < dx; j++) { *ppo = *ppi; ppo++; ppi++; } } ppm_writeppm(of, (pixel **) dat_p_out, dx, dy, maxval, 0); ppm_freearray(dat_p_out, dy); } break; default: pfm_geo_set(geoWest(),geoNorth(),geoEast(),geoSouth()); pfm_writepfm_region_type(of, data_, cols_, rows_, minval_, maxval_, rx1, ry1, rx2, ry2, type_); break; } fclose(of); return fname; }
// Generates the messages based on the function requested by the client // Function name is either: start_movie, stop_movie, seek_movie void generateMessages(int workerThreadID, request* req) { int frame, messageID, endFrame, startFrame; int repeat; char* clientID = req->clientID; // Handle a stop_movie request // Add the clientID into the stopList if(strcmp(req->funcRequest, "stop_movie") == 0) {\ insertStopID(clientID); #ifdef DEBUG printStopList(); #endif return; } // Handle a start_movie request if (strcmp(req->funcRequest, "start_movie") == 0) { startFrame = 1; repeat = req->argument; } // Handle a seek_movie request else if(strcmp(req->funcRequest, "seek_movie") == 0) { // Start frame is the seek frame startFrame = req->argument; repeat = 0; // Do some minor error checking if (startFrame <= 0) { startFrame = 1; } } messageID = 1; endFrame = 100; //magic cookie bad // Create a message for each frame from the startframe to the endframe // For start_movie, it is the entire movie // For seek_movie, it is seekFrame-->endFrame for (frame = startFrame; frame <= endFrame; frame++) { pixel** pixArray; FILE *fp; int cols, rows; pixval maxval; char s[80]; // Attempt to open the frame for processing sprintf (s, "./images/%s%d.ppm", req->filePrefix, frame); if ((fp = fopen (s,"r")) == NULL) { fprintf (stderr, "%s: Can't open input file:\n %s.\n", s); exit (1); } // Read the ppm image into a multidimensional array pixArray = ppm_readppm (fp, &cols, &rows, &maxval); fclose (fp); // Since all slots have a copy of the original client request // create a pointer to the request object so we don't waste memory request* copyReq = req; // IMPORTANT regarding stopping playback // We check every 20 frames to reduce redundancy // We don't want to generate messages for a movie that the client // has already requested be stopped, so check every 20 messages to make sure if (frame != 100 && ((frame % 20) == 0)) { // If the message is part of a movie which the client has already // requested be stopped, then stop sending them frames and // jump to the last frame if (searchStopList(clientID) == TRUE) { frame = 99; ppm_freearray (pixArray, rows); } // Otherwise this is still part of a valid movie request else { // Insert this message into the buffer and increment the message id insertToBuffer(workerThreadID, copyReq, messageID, pixArray, rows, cols, frame, repeat); messageID++; } } else { // Insert this message into the buffer and increment the message id insertToBuffer(workerThreadID, copyReq, messageID, pixArray, rows, cols, frame, repeat); messageID++; } } }
// Sends the pixarray for a given slot in the circular buffer // The size of the frame we send is (rows * cols * 3) + 1. // The *3 is for the three channels per pixel (RGB) and the +1 // is an extra byte which lets the client know whether or not // more data is coming (we denote this byte as the TERM flag). // If the term flag == 1, then there is more data coming, so the // client should keep the connection open. // If the term flag == 0, then there is no more data coming, and // the client should close the connection. void sendFrame(int bufferIndex) { int i = bufferIndex; int sizeToSend = buffer[i].rows * buffer[i].cols * 3 + 1; int x, y; int rows = buffer[i].rows; int cols = buffer[i].cols; unsigned char *buf = NULL; // +1 slot used to determine if there is more data coming: 0 or 1 buf = (unsigned char *)malloc ((cols*rows*3) + 1); if (!buf) { perror("Could not malloc memory for buf\n"); exit(1); } // Place the frame data into a char array for (y = 0; y < rows; y++) { for (x = 0; x < cols; x++) { buf[(y*cols+x)*3+0] = PPM_GETR(buffer[i].pixArray[rows-y-1][x]); buf[(y*cols+x)*3+1] = PPM_GETG(buffer[i].pixArray[rows-y-1][x]); buf[(y*cols+x)*3+2] = PPM_GETB(buffer[i].pixArray[rows-y-1][x]); } } char* clientID = buffer[i].clientRequest->clientID; // Determine if this is part of a movie which was already stopped by client int inStopList = searchStopList(clientID); // clientRequest objects are shared for all frames belonging to a single // client request. Therefore, no need to make redundant copies, just pointers. // Only free this client request obj when the last frame is serviced! int deleteFlag = FALSE; // Check to see if the movie has repeat = 1, if so, there is more data to send even // though the movie is done playing. if (buffer[i].frame == 100) { // If its a repeat, and the client hasnt requested a stop movie, then copy this request again if (buffer[i].repeat == TRUE && inStopList == FALSE) { // Add a start_movie request to the request list, with repeat flag = 1 // Set the 100th frame with more data flag = 1 deleteFlag = FALSE; insertRequest(buffer[i].clientRequest); buf[cols*rows*3] = NOTCLOSE; } else { // Call deleteStopID(clientID) // Set the 100th frame with more data flag = 0 deleteStopID(clientID); buf[cols*rows*3] = CLOSE; deleteFlag = TRUE; } } // If its not the last frame else { // If it is part of a movie which was stopped, then this is the last frame // and the client should just close the connection if (inStopList == TRUE) { buf[cols*rows*3] = CLOSE; } // Otherwise this is a frame for a movie which has regular playback // so don't close the connection, just receive the movie frames else { buf[cols*rows*3] = NOTCLOSE; } } // The movie hasn't been stopped, so send the frame data if (inStopList == FALSE) { // Send the entire frame (reduces write syscalls) #ifdef DEBUG printf("Send frame: %d request string: %s\n", buffer[i].frame, buffer[i].clientRequest->requestString); #endif write(buffer[i].clientRequest->clientSD, buf, sizeToSend); if (errno == EPIPE) { #ifdef DEBUG printf("Got EPIPE error errno: %d\n", errno); #endif insertStopID(buffer[i].clientRequest->clientID); close(buffer[i].clientRequest->clientSD); errno = 0; } } // Release the memory ppm_freearray (buffer[i].pixArray, buffer[i].rows); free(buf); // If this clientRequest obj is not going to be used anymore, free if (deleteFlag == TRUE) { free(buffer[i].clientRequest); } }
static void convert_image(const char *filename, const char *name) { FILE *fp; xel **pnm; xelval maxval; int cols, rows, fmt, clut_len = 0, size; const char *type; // Load the image if (!strcmp(filename, "-")) fp = stdin; else { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno)); exit(1); } } pnm = pnm_readpnm(fp, &cols, &rows, &maxval, &fmt); if (!pnm) { fprintf(stderr, "Error reading PNM file: %s\n", strerror(errno)); exit(1); } switch (PNM_FORMAT_TYPE(fmt)) { case PPM_TYPE: normalize_ppm(pnm, cols, rows, maxval); clut_len = fill_clut(pnm, cols, rows); if (clut_len > 0 && clut_len <= 256) { type = "CLUT256"; size = cols*rows; } else { type = "RGB888"; size = cols*rows*3; } break; case PGM_TYPE: type = "GREY256"; size = cols*rows; break; case PBM_TYPE: type = "BW"; size = (cols+7)/8*rows; break; default: fprintf(stderr, "Unknown PNM format %d\n", PNM_FORMAT_TYPE(fmt)); exit(1); } // Print header printf(" /*\n"); printf(" * Image %s\n", name); printf(" */\n\n"); printf("#include \"image.h\"\n\n"); // Print forward declarations printf("static const unsigned char %s_data[];\n", name); if (clut_len > 0 && clut_len <= 256) printf("static const unsigned char %s_clut[];\n", name); printf("\n"); // Print image structure printf("const struct image %s = {\n", name); printf(" width:\t%d,\n", cols); printf(" height:\t%d,\n", rows); printf(" type:\tIMAGE_%s,\n", type); printf(" data:\t%s_data,\n", name); if (clut_len > 0 && clut_len <= 256) { printf(" clut_len:\t%d,\n", clut_len); printf(" clut:\t%s_clut\n", name); } printf("};\n\n"); // Print image data printf("static const unsigned char %s_data[%d] = {\n", name, size); switch (PNM_FORMAT_TYPE(fmt)) { case PPM_TYPE: if (clut_len > 0 && clut_len <= 256) print_clut256_data(pnm, cols, rows, clut_len); else print_rgb888_data(pnm, cols, rows); break; case PGM_TYPE: print_grey256_data(pnm, cols, rows, maxval); break; case PBM_TYPE: print_bw_data(pnm, cols, rows); break; } printf("};\n\n"); // Print image clut if (clut_len > 0 && clut_len <= 256) { printf("static const unsigned char %s_clut[%d] = {\n", name, clut_len*3); print_image_clut(clut_len); printf("};\n\n"); } // Free temporary data ppm_freearray(pnm, rows); }
int main(int argc, char *argv[]) { FILE *ifp; int rows, cols; unsigned int ncolors; bool transparentSomewhere; pixval maxval, alphaMaxval; colorhash_table cht; colorhist_vector chv; colorhash_table colornameHash; /* Hash table to map colors to their names */ const char ** colornames; /* Table of color names; 'colornameHash' yields an index into this array. */ pixel **pixels; gray **alpha; /* Used for rgb value -> character-pixel string mapping */ cixel_map *cmap; /* malloc'ed */ /* The XPM colormap */ unsigned int cmapSize; /* Number of entries in 'cmap' */ unsigned int transIndex; /* Index into 'cmap' of the transparent color, if there is one */ unsigned int charsPerPixel; struct cmdlineInfo cmdline; ppm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); ifp = pm_openr(cmdline.inputFilename); pixels = ppm_readppm(ifp, &cols, &rows, &maxval); pm_close(ifp); if (cmdline.alpha_filename) readAlpha(cmdline.alpha_filename, &alpha, cols, rows, &alphaMaxval); else alpha = NULL; computeColormap(pixels, alpha, cols, rows, alphaMaxval, &chv, &cht, &ncolors, &transparentSomewhere); if (cmdline.hexonly) colornameHash = NULL; else if (cmdline.rgb) ppm_readcolornamefile(cmdline.rgb, TRUE, &colornameHash, &colornames); else ppm_readcolornamefile(NULL, FALSE, &colornameHash, &colornames); /* Now generate the character-pixel colormap table. */ genCmap(chv, ncolors, maxval, colornameHash, colornames, transparentSomewhere, &cmap, &transIndex, &cmapSize, &charsPerPixel); writeXpmFile(stdout, pixels, alpha, alphaMaxval, cmdline.name, cols, rows, cmapSize, charsPerPixel, cmap, cht, transIndex); if (colornameHash) { ppm_freecolorhash(colornameHash); ppm_freecolornames(colornames); } destroyCmap(cmap, cmapSize); ppm_freearray(pixels, rows); if (alpha) pgm_freearray(alpha, rows); return 0; }