/*! * Writes the header for unit [iunit] to file with the minimum, maximum and mean * density values in [dmin], [dmax], and [dmean]. A single title can be supplied in * an 80-byte array, [label], and will be treated according to the value of [labFlag]: ^ * 0: [label] becomes the only title ^ * 1: [label] is added at the end of existing titles, replacing the last one if there * are already 10 titles ^ * 2: [label] is added as the first title and others are shifted up ^ * -1 or anything else: do not add a title ^ * Returns -1 for various internal errors or 1 for an error writing the header. * Fortran wrappers iiuWriteHeader and iwrhdr (a void). */ int iiuWriteHeader(int iunit, int *label, int labFlag, float dmin, float dmax, float dmean) { int doExit = iiuGetExitOnError(); int i; MrcHeader *hdr = iiuMrcHeader(iunit, "iiuWriteHeader", doExit, 2); if (!hdr) return -1; if (labFlag == 0) { iiuAltLabels(iunit, label, 1); } else if (labFlag == 1) { hdr->nlabl = B3DMIN(hdr->nlabl + 1, MRC_NLABELS); memcpy(hdr->labels[hdr->nlabl - 1], label, MRC_LABEL_SIZE); fixTitlePadding(hdr->labels[hdr->nlabl - 1]); } else if (labFlag == 2) { hdr->nlabl = B3DMIN(hdr->nlabl + 1, MRC_NLABELS); for (i = hdr->nlabl - 1; i > 0; i--) memcpy(hdr->labels[i], hdr->labels[i - 1], MRC_LABEL_SIZE); memcpy(hdr->labels[0], label, MRC_LABEL_SIZE); fixTitlePadding(hdr->labels[0]); } hdr->amin = dmin; hdr->amax = dmax; hdr->amean = dmean; if (mrc_head_write(hdr->fp, hdr)) { if (doExit) exit(1); return 1; } return 0; }
// Set the drawing state and dialog to the start or end of the given movie segment void mvImageSetMovieEndState(int startEnd, MovieSegment &segment) { MovieTerminus *term = &segment.start; int maxSlices = B3DMIN(Imodv->vi->zsize, MAX_SLICES); if (startEnd == IMODV_MOVIE_END_STATE) term = &segment.end; if (mvImageSetMovieDrawState(segment)) return; // Otherwise set the image position and copy all the data over sImageTrans = term->imgTransparency; ivwSetLocation(Imodv->vi, term->imgXcenter - 1, term->imgYcenter - 1, term->imgZcenter - 1); sNumSlices = B3DMIN(term->imgSlices, maxSlices); // Update the dialog as needed if (sDia) { // Set this to prevent Y/Z swapping of sizes in the update sLastYsize = Imodv->vi->ysize; sDia->updateCoords(); sDia->mSliders->setValue(IIS_SLICES, sNumSlices); sDia->mSliders->setValue(IIS_TRANSPARENCY, sImageTrans); } }
/*! * Extracts a square matrix of size [dim] from the slice [sin], centered * around position [x], [y] and places the result into the array [mat]. */ void mrc_slice_mat_getimat(Islice *sin, int x, int y, int dim, float *mat) { int xs, ys, xe, ye; int i, j, ic, jc; xs = x - (dim / 2); xe = xs + dim; ys = y - (dim / 2); ye = ys + dim; if (xs >= 0 && xe < sin->xsize && ys >= 0 && ye < sin->ysize) { for(j = ys; j < ye; j++) for(i = xs; i < xe; i++) mat[(i-xs )+ dim * (j-ys)] = sliceGetPixelMagnitude(sin, i, j); } else { /* If any pixels are out of bounds, replicate from inside pixels */ for(j = ys; j < ye; j++) for(i = xs; i < xe; i++) { ic = B3DMAX(0, B3DMIN(sin->xsize - 1, i)); jc = B3DMAX(0, B3DMIN(sin->ysize - 1, j)); mat[(i-xs )+ dim * (j-ys)] = sliceGetPixelMagnitude(sin, ic, jc); } } }
void ContourCopy::update() { int minVal, maxVal, curVal; ImodView *vw = sData.vw; // For each operation that uses spin box, set up min and max value // and adjust the current value if necessary switch(sData.copyOperation){ case COPY_TO_OBJECT: minVal = 1; maxVal = vw->imod->objsize; sData.objectNumber = B3DMAX(1, B3DMIN(maxVal, sData.objectNumber)); curVal = sData.objectNumber; break; case COPY_TO_SECTION: minVal = 1; maxVal = vw->zsize; sData.sectionNumber = B3DMAX(1, B3DMIN(maxVal, sData.sectionNumber)); curVal = sData.sectionNumber; break; case COPY_TO_TIME: minVal = 1; maxVal = vw->numTimes; sData.timeIndex = B3DMAX(1, B3DMIN(maxVal, sData.timeIndex)); curVal = sData.timeIndex; break; case COPY_TO_NEXT_SECTION: case COPY_TO_PREV_SECTION: case COPY_TO_CURRENT: default: minVal = 0; maxVal = 0; curVal = 0; break; } // Set up spin box limits and value and enable it if meaningful diaSetSpinMMVal(mToSpinBox, minVal, maxVal, curVal); mToSpinBox->setSpecialValueText(minVal ? "" : " "); mToSpinBox->setEnabled(minVal > 0); mEllipseBox->setEnabled(sData.copyOperation == COPY_TO_OBJECT); // Enable the time radio button if appropriate if (vw->numTimes) mTimeRadio->setEnabled(sData.copyOperation == COPY_TO_TIME); }
/* * Ruueads a file of tilt angles whose name is in angleFile, and which must * have at least nzz lines. angleSign should be 1., or -1. to invert the * sign of the angles. Minimum and maximum angles are returned in minAngle * and maxAngle. The return value is the array of tilt angles. */ float *readTiltAngles(const char *angleFile, int nzz, float angleSign, float &minAngle, float &maxAngle) { char angleStr[MAX_LINE]; FILE *fpAngle; int k, err; float currAngle; float *tiltAngles = (float *)malloc(nzz * sizeof(float)); minAngle = 10000.; maxAngle = -10000.; if (!tiltAngles) exitError("Allocating array for tilt angles"); if ((fpAngle = fopen(angleFile, "r")) == 0) exitError("Opening tilt angle file %s", angleFile); for (k = 0; k < nzz; k++) { do { err = fgetline(fpAngle, angleStr, MAX_LINE); } while (err == 0); if (err == -1 || err == -2) exitError("%seading tilt angle file %s\n", err == -1 ? "R" : "End of file while r", angleFile); sscanf(angleStr, "%f", &currAngle); currAngle *= angleSign; minAngle = B3DMIN(minAngle, currAngle); maxAngle = B3DMAX(maxAngle, currAngle); tiltAngles[k] = currAngle; } fclose(fpAngle); return tiltAngles; }
/*! * Computes the minimum [DMIN], maximum [dmax], mean [avg], and standard deviation [SD] * from data in [array], dimensioned [nx] by [ny], for X indices from [ix0] to [ix1] and * Y indices from [iy0] to [iy1], inclusive (numbered from 0 when calling from C). It * also returns the sum in [sumDbl] and sum of squares in [sumSqDl]. */ void arrayMinMaxMeanSd(float *array, int nx, int ny, int ix0, int ix1, int iy0, int iy1, float *dmin, float *dmax, double *sumDbl, double *sumSqDbl, float *avg, float *SD) { float den; float *arrTmp; double sumTmp, sumTmpSq; int ix, iy; *sumDbl = 0.; *sumSqDbl = 0.; *dmin = 1.e37; *dmax = -1.e37; for (iy = iy0; iy <= iy1; iy++) { sumTmp = 0.;; sumTmpSq = 0.; arrTmp = array + (size_t)iy * nx + ix0; for (ix = ix0; ix <= ix1; ix++) { den = *arrTmp++; sumTmp = sumTmp + den; sumTmpSq = sumTmpSq + den * den; *dmin = B3DMIN(*dmin, den); *dmax = B3DMAX(*dmax, den); } *sumDbl += sumTmp; *sumSqDbl += sumTmpSq; } sumsToAvgSDdbl(*sumDbl, *sumSqDbl, ix1 + 1 - ix0, iy1 + 1 - iy0, avg, SD); }
/* * Compute the limits of usable data in one dimension for calling from the interp function */ static void interpLimits(int na, int nb, float cen, float trans, double scale, float *aOff, int *bSize, int *bOff) { float bcStart, bcEnd; int bdStart, bdEnd; /* Get starting and ending continuous coordinates in b from corners of a and limit them to edges of first and last pixel */ bcStart = -cen / scale + nb / 2. + trans; bcEnd = (na - cen) / scale + nb / 2. + trans; bcStart = B3DMAX(0., bcStart); bcEnd = B3DMIN(nb, bcEnd); /* Get discrete coordinates of the nearest whole pixel by rounding up on the start and down on the end, then get the offset and size from them */ bdStart = (int)ceil(bcStart - 0.001); bdEnd = (int)floor(bcEnd + 0.001) - 1; *bOff = bdStart; *aOff = scale * (bdStart - nb / 2. - trans) + cen; /* Make sure this is not negative; roundoff errors can give negative values */ *aOff = B3DMAX(0., *aOff); *bSize = bdEnd + 1 - bdStart; /* Make sure the output size will pass the test below too */ if (*bSize * scale + *aOff > na) (*bSize)--; }
// Compute starting and ending draw coordinates from center coordinate, desired // size and maximum size, shifting center if necessary static void setCoordLimits(int cur, int maxSize, int drawSize, int &str, int &end) { str = cur - drawSize / 2; str = B3DMAX(1, str); end = B3DMIN(str + drawSize, maxSize - 1); str = B3DMAX(1, end - drawSize); }
void SliceCache::clearAndSetSize(int dim, int hyper, int tSize) { int fftXdim, i, j, rIndex; double freqInc; numXtiles = mHeader.nx / (tSize / 2) - 1; mNumYtiles = mHeader.ny / (tSize / 2) - 1; mPsArraySize = numXtiles * mNumYtiles * mPsDim; mMaxSliceNum = mMaxCacheSize * 1024 * 1024 / (mPsArraySize * sizeof(float)); for (i = 0; i < (int)mCachedPS.size(); i++) { free(mCachedPS[i]); free(mCachedTileDone[i]); free(mCachedMeans[i]); } if (mTile) free(mTile); mTile = (float *)malloc(tSize * (tSize + 2) * sizeof(float)); if (mTileToPsInd) free(mTileToPsInd); mTileToPsInd = (int *)malloc(tSize * (tSize + 2) * sizeof(int)); if (!mTile || !mTileToPsInd) exitError("Allocating memory for mTile or PS index"); // Compute the index for each component of FFT and the counts in each bin mTileSize = tSize; mNDim = dim; mHyperRes = hyper; fftXdim = (mTileSize + 2) / 2; freqInc = 1. / ((mNDim - 1) * hyper); for (i = 0; i < mPsDim; i++) mFreqCount[i] = 0; for (i = 0; i < fftXdim - 1; i++) { for (j = 0; j < fftXdim; j++) { // Here make bins with integer truncation rIndex = (int)(sqrt((double)(i * i + j * j)) / (fftXdim - 1) / freqInc); rIndex = B3DMIN(rIndex, mPsDim - 1); mTileToPsInd[i * fftXdim + j] = rIndex; mFreqCount[rIndex] += 2; } } /*for (i = 0; i < mPsDim; i++) printf("%d\n", mFreqCount[i]); */ // Clear cache components mCachedPS.clear(); mCachedMeans.clear(); mCachedTileDone.clear(); mSliceAngles.clear(); mCachedSliceMap.clear(); mOldestIdx = -1; if (debugLevel >= 2) printf("cacheSize is set to %d \n", mMaxSliceNum); }
/*! * Sets the labels for unit [iunit] from the array in [labels], which should have the * 80 characters for [numLabels] labels packed contiguously. The labels may be * null-terminated; the null and following bytes will be filled with spaces. * Fortran wrappers iiuAltLabels and iallab. */ void iiuAltLabels(int iunit, int *labels, int numLabels) { MrcHeader *hdr = iiuMrcHeader(iunit, "iiuAltLabels", 1, 0); int i; hdr->nlabl = B3DMIN(MRC_NLABELS, numLabels); for (i = 0; i < hdr->nlabl; i++) { memcpy(hdr->labels[i], labels + 20 * i, MRC_LABEL_SIZE); fixTitlePadding(hdr->labels[i]); } for (i = hdr->nlabl; i < MRC_NLABELS; i++) memset(hdr->labels[i], 0, MRC_LABEL_SIZE + 1); }
// Set ancillary parameters to the state for a movie segment int mvImageSetMovieDrawState(MovieSegment &segment) { if (!segment.imgAxisFlags) { // If there is no image drawing, turn off Imodv flag and then, if there is currently, // take the update route to updating this module Imodv->texMap = 0; if (sFlags) mvImageUpdate(Imodv); return 1; } sFlags = segment.imgAxisFlags; Imodv->texMap = 1; sWhiteLevel = segment.imgWhiteLevel; sBlackLevel = segment.imgBlackLevel; sFalsecolor = segment.imgFalseColor; makeColorMap(); sXdrawSize = B3DMIN(segment.imgXsize, Imodv->vi->xsize); sYdrawSize = B3DMIN(segment.imgYsize, Imodv->vi->ysize); sZdrawSize = B3DMIN(segment.imgZsize, Imodv->vi->zsize); // Update the dialog as needed if (sDia) { sDia->mSliders->setValue(IIS_X_SIZE, sXdrawSize); sDia->mSliders->setValue(IIS_Y_SIZE, sYdrawSize); sDia->mSliders->setValue(IIS_Z_SIZE, sZdrawSize); diaSetChecked(sDia->mViewXBox, (sFlags & IMODV_DRAW_CX) != 0); diaSetChecked(sDia->mViewYBox, (sFlags & IMODV_DRAW_CY) != 0); diaSetChecked(sDia->mViewZBox, (sFlags & IMODV_DRAW_CZ) != 0); sDia->mSliders->setValue(IIS_BLACK, sBlackLevel); sDia->mSliders->setValue(IIS_WHITE, sWhiteLevel); diaSetChecked(sDia->mFalseBox, sFalsecolor != 0); } return 0; }
/* * Does common initial tasks for a montage snapshot: allocates the arrays, * (returns true for an error), and saves and adjusts the scale bar data */ bool utilStartMontSnap(int winx, int winy, int xFullSize, int yFullSize, float factor, ScaleBar &barSaved, int &numChunks, unsigned char **framePix, unsigned char ***fullPix, unsigned char ***linePtrs) { int iy, maxLines, line, ch, ndo; int chunkMax = 10000000; // This was needed to get to 2.9 GB on WinXP ScaleBar *barReal = scaleBarGetParams(); maxLines = B3DMAX(1, chunkMax / (4 * xFullSize)); numChunks = (yFullSize + maxLines - 1) / maxLines; *fullPix = (unsigned char **)malloc(numChunks * sizeof (unsigned char *)); if (!*fullPix) return true; for (ch = 0; ch < numChunks; ch++) (*fullPix)[ch] = NULL; *linePtrs = NULL; *framePix = NULL; *framePix = (unsigned char *)malloc(4 * winx * winy); *linePtrs = (unsigned char **)malloc(yFullSize * sizeof(unsigned char *)); if (!*framePix || !*linePtrs) { utilFreeMontSnapArrays(*fullPix, numChunks, *framePix, *linePtrs); return true; } line = 0; for (ch = 0; ch < numChunks; ch++) { ndo = B3DMIN(yFullSize - line, maxLines); (*fullPix)[ch] = (unsigned char *)malloc(ndo * 4 * xFullSize); if (!(*fullPix)[ch]) { imodPrintStderr("Failed on chunk %d, after %u\n", ch, (unsigned int)ch * ndo * 4 * xFullSize); utilFreeMontSnapArrays(*fullPix, numChunks, *framePix, *linePtrs); return true; } for (iy = 0; iy < ndo; iy++) (*linePtrs)[iy+line] = (*fullPix)[ch] + 4 * xFullSize * iy; line += ndo; } // Save and modify scale bar directives barSaved = *barReal; barReal->minLength = B3DNINT(factor * barReal->minLength); barReal->thickness = B3DNINT(factor * barReal->thickness); barReal->indentX = B3DNINT(factor * barReal->indentX); barReal->indentY = B3DNINT(factor * barReal->indentY); return false; }
// Return the limits of what is being drawn in X and Y bool mvImageSubsetLimits(double &zoom, float &zoomUpLimit, float &zoomDownLimit, int &ixStart, int &iyStart, int &nxUse, int &nyUse) { int ixCur, iyCur, izCur, xend, yend; ImodvApp *a = Imodv; if (ImodvClosed || !a->texMap || !sFlags || sXdrawSize <= 0) return false; zoomUpLimit = sPyrZoomUpLimit; zoomDownLimit = sPyrZoomDownLimit; zoom = 0.5 * B3DMIN(a->winx, a->winy) / a->imod->view->rad; ivwGetLocation(a->vi, &ixCur, &iyCur, &izCur); setCoordLimits(ixCur, a->vi->xsize, sXdrawSize, ixStart, xend); setCoordLimits(iyCur, a->vi->ysize, sYdrawSize, iyStart, yend); nxUse = xend + 1 - ixStart; nyUse = yend + 1 - iyStart; return true; }
/* * Finds the next section in the current object with a contour, given curz is * the current Z and dir is 1 to go forward or -1 to go back */ int utilNextSecWithCont(ImodView *vi, Iobj *obj, int curz, int dir) { int diff, co, contz; int newz = curz; Icont *cont; if (!obj) return newz; newz = -1; for (co = 0; co < obj->contsize; co++) { cont = &obj->cont[co]; if (!cont->psize) continue; contz = B3DNINT(cont->pts[0].z); contz = B3DMAX(0, B3DMIN(contz, vi->zsize - 1)); diff = dir * (contz - curz); if (diff > 0 && (newz < 0 || diff < dir * (newz - curz))) newz = contz; } return newz >= 0 ? newz : curz; }
/*! * Computes the minimum [DMIN], maximum [dmax], and mean [dmean] from data in [array], * dimensioned [nx] by [ny], for X indices from [ix0] to [ix1] and Y indices from [iy0] * to [iy1], inclusive (numbered from 0 when calling from C). */ void arrayMinMaxMean(float *array, int nx, int ny, int ix0, int ix1, int iy0, int iy1, float *dmin, float *dmax, float *dmean) { float den, sumTmp; float *arrTmp; double sumDbl; int ix, iy; sumDbl = 0.; *dmin = 1.e37; *dmax = -1.e37; for (iy = iy0; iy <= iy1; iy++) { sumTmp = 0.;; arrTmp = array + (size_t)iy * nx + ix0; for (ix = ix0; ix <= ix1; ix++) { den = *arrTmp++; sumTmp = sumTmp + den; *dmin = B3DMIN(*dmin, den); *dmax = B3DMAX(*dmax, den); } sumDbl += sumTmp; } *dmean = sumDbl / ((double)(ix1 + 1 - ix0) * (iy1 + 1 - iy0)); }
static void plax_draw_text(b3dInt32 thickness, b3dInt32 iysize, b3dInt32 cindex, b3dInt32 x, b3dInt32 y, b3dInt32 strsize, char *string) { static int lastbold; int width, height, align, maxWidth, maxHeight; int ysize = (int)(iysize * TEXT_SIZE_SCALE); int ifbold = 0; char *cstring = f2cString(string, strsize); if (!cstring) return; #ifdef PLAX_DEBUG printf("draw text %d %d %d %d %d %s\n", thickness, iysize, cindex, x, y, cstring); #endif if (thickness > 1) ifbold = 1; ysize = plax_scale(ysize); if (ysize <= 1) ysize = 1; if (sLastSize != ysize || lastbold != ifbold) { //QFont newFont("courier", ysize); QFont newFont; newFont.setPointSize(ysize); newFont.setStyleHint(QFont::TypeWriter); newFont.setItalic(false); newFont.setBold(ifbold != 0); sPainter->setFont(newFont); } lastbold = ifbold; sLastSize = ysize; plax_transform(&x, &y); plax_set_pen(cindex, 0); if (sNextTextAlign % 10) { maxWidth = 2 * B3DMIN(x, sPlaxWidth - x); maxHeight = 2 * B3DMIN(y - 1, sPlaxHeight - y - 1); switch (sNextTextAlign % 10) { case 1: // Top center align = Qt::AlignHCenter | Qt::AlignTop; width = B3DMIN(maxWidth, sPlaxWidth / 2); height = B3DMIN(sPlaxHeight - 1 - y, sPlaxHeight / 2); x -= width / 2; break; case 2: // right center align = Qt::AlignVCenter | Qt::AlignRight; width = B3DMIN(x - 1, sPlaxWidth / 2); height = B3DMIN(maxHeight, sPlaxHeight / 2); x -= width; y -= height / 2; break; case 3: // Bottom center align = Qt::AlignHCenter | Qt::AlignBottom; width = B3DMIN(maxWidth, sPlaxWidth / 2); height = B3DMIN(y - 1, sPlaxHeight / 2); x -= width / 2; y -= height; break; case 4: // left center align = Qt::AlignVCenter | Qt::AlignLeft; width = B3DMIN(sPlaxWidth - x - 1, sPlaxWidth / 2); height = B3DMIN(maxHeight, sPlaxHeight / 2); y -= height / 2; break; default: // all centered align = Qt::AlignVCenter | Qt::AlignHCenter; height = B3DMIN(maxHeight, sPlaxHeight / 2); width = B3DMIN(maxWidth, sPlaxWidth / 2); x -= width / 2; y -= height / 2; break; } if (sNextTextAlign >= 10) align |= Qt::TextWordWrap; sPainter->drawText(x, y, width, height, align, QString(cstring)); //printf("%d %d %d %d %d %s\n", x,y, width, height, align,cstring); sNextTextAlign = 0; } else { //printf("%d %d %s\n", x,y, cstring); sPainter->drawText(x, y, QString(cstring)); } fflush(stdout); free(cstring); }
static void fillPatchFromTiles(std::vector<FastSegment> &segments, std::vector<int> &startInds, int ushort, unsigned char *bmap, int fillXsize, int istart, int iend, int jstart, int jend) { int u, v, j, i, iseg, numSeg, segEnd, nextToFill, uvind, segStart; FastSegment *segp; unsigned char *imdata; unsigned short *usimdata; unsigned char pix; for (j = jstart; j < jend; j++) { v = j - jstart; numSeg = startInds[j + 1] - startInds[j]; nextToFill = istart; for (iseg = startInds[j]; iseg < startInds[j + 1]; iseg++) { segp = &(segments[iseg]); // If segment starts past the end, done with segments if (segp->XorY >= iend) break; // If segment ends before the start, skip it if (segp->XorY + segp->length <= istart) continue; // If segment starts past next place to fill, need to fill with 0's if (segp->XorY > nextToFill) { for (i = nextToFill; i < segp->XorY; i++) { u = i - istart; FILLDATA(0); } } // Fill with segment data segEnd = B3DMIN(segp->XorY + segp->length, iend); segStart = B3DMAX(segp->XorY, istart); imdata = segp->line + segp->stride * (segStart - segp->XorY); if (ushort) { usimdata = (unsigned short *)imdata; for (i = segStart; i < segEnd; i++) { u = i - istart; pix = bmap[*usimdata]; usimdata += segp->stride; FILLDATA(pix); } } else { for (i = segStart; i < segEnd; i++) { u = i - istart; pix = *imdata; imdata += segp->stride; FILLDATA(pix); } } nextToFill = segEnd; } // Fill past end for (i = nextToFill; i < iend; i++) { u = i - istart; FILLDATA(0); } } }
// The call from within the openGL calling routines to draw the image void imodvDrawImage(ImodvApp *a, int drawTrans) { Ipoint lowerLeft, lowerRight, upperRight, upperLeft, clamp; int tstep; int ixCur, iyCur, izCur; int xsize, ysize, zsize; int xstr, xend, ystr, yend, zstr, zend, fillXsize; unsigned char **idata; b3dUInt16 **usidata; unsigned char pix; int i, j, ypatch, jend, xpatch, zpatch, iend, xconst; int u, v, uvind; int iz, idir, numSave, baseXstr, baseXsize, baseYstr, baseYsize; int cacheSum, curtime, cacheInd = -1; float clampEnd; int pyrXYscale = 1, pyrZscale = 1; float pyrXoffset = 0., pyrYoffset = 0., pyrZoffset = 0.; double zoom; unsigned char **imdata; b3dUInt16 **usimdata; unsigned char *bmap = NULL; bool flipped, invertX, invertY, invertZ; Imat *mat; Ipoint inp, outp; std::vector<FastSegment> segments; std::vector<int> startInds; QTime drawTime; drawTime.start(); sWallLoad = sWallDraw = 0.; xsize = a->vi->xsize; ysize = a->vi->ysize; zsize = a->vi->zsize; if (sDia) sDia->updateCoords(); if (!sFlags) return; if (a->vi->pyrCache != NULL) { zoom = 0.5 * B3DMIN(a->winx, a->winy) / a->imod->view->rad; cacheInd = a->vi->pyrCache->pickBestCache(zoom, sPyrZoomUpLimit, sPyrZoomDownLimit, pyrXYscale); imodTrace('t', "zoom = %.3f, cache %d, scale %d", zoom, cacheInd, pyrXYscale); } ivwGetLocation(a->vi, &ixCur, &iyCur, &izCur); ivwGetTime(a->vi, &curtime); if (!sCmapInit || (a->vi->colormapImage && (izCur != cmapZ || curtime != cmapTime))) { makeColorMap(); cmapTime = curtime; cmapZ = izCur; } if (sXdrawSize < 0) { sXdrawSize = xsize; sYdrawSize = ysize; sZdrawSize = zsize; } // If doing stereo pairs, draw the pair as long as the step up stays in the // same set of images for an area if (a->imageStereo && a->stereo < 0) { iz = izCur + a->imageDeltaZ; if (izCur % a->imagesPerArea < iz % a->imagesPerArea) izCur = iz; } // Get data pointers if doing X or Y planes if ((sFlags & (IMODV_DRAW_CX | IMODV_DRAW_CY)) && cacheInd < 0 && !(a->imageStereo && a->stereo)) { if (ivwSetupFastAccess(a->vi, &imdata, 0, &cacheSum)) return; flipped = (!a->vi->vmSize || a->vi->fullCacheFlipped) && a->vi->li->axis == 2; usimdata = (b3dUInt16 **)imdata; } if (a->vi->ushortStore) { bmap = ivwUShortInRangeToByteMap(a->vi); if (!bmap) return; } // If doing multiple slices, need to find direction in which to do them invertX = invertY = invertZ = false; if (a->vi->colormapImage && sNumSlices > 1) { sNumSlices = 1; if (sDia) sDia->mSliders->setValue(IIS_SLICES, sNumSlices); } numSave = sNumSlices; if (a->imageStereo && a->stereo) sNumSlices = 1; if (sNumSlices > 1) { mat = imodMatNew(3); imodMatRot(mat, (double)a->imod->view->rot.z, b3dZ); imodMatRot(mat, (double)a->imod->view->rot.y, b3dY); imodMatRot(mat, (double)a->imod->view->rot.x, b3dX); inp.x = 1.; inp.y = inp.z = 0.0f; imodMatTransform(mat, &inp, &outp); invertX = outp.z < 0.; inp.x = 0.; inp.y = 1.; imodMatTransform(mat, &inp, &outp); invertY = outp.z < 0.; inp.y = 0.; inp.z = 1.; imodMatTransform(mat, &inp, &outp); invertZ = outp.z < 0.; imodMatDelete(mat); } if (!sTexImageSize && initTexMapping()) return; tstep = sTexImageSize - 2; clampEnd = (tstep + 1.) / (tstep + 2.); // This used to be 1 with RGB data being passed in glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glEnable(GL_TEXTURE_2D); /* Draw Current Z image. */ if (sFlags & IMODV_DRAW_CZ) { // Get the limits for the 3 axes. In every section, xstr, xend etc are the full image // starting and ending coordinates in actual X, Y, and Z diections. setSliceLimits(izCur, zsize, invertZ, drawTrans, zstr, zend, idir); setCoordLimits(ixCur, xsize, sXdrawSize, xstr, xend); setCoordLimits(iyCur, ysize, sYdrawSize, ystr, yend); baseXstr = xstr; baseXsize = xend + 1 - xstr; baseYstr = ystr; baseYsize = yend + 1 - ystr; // When displaying a lower resolution cache, this converts all of the limits to // loaded coordinates in that cache adjustLimitsForTiles(a, cacheInd, idir, xstr, xend, ystr, yend, zstr, zend, pyrXoffset, pyrYoffset, pyrZoffset, pyrZscale); // Outer loop is on the coordinate that varies through multiple slices if any for (iz = zstr; idir * (zend - iz) >= 0 ; iz += idir) { setAlpha(iz, zstr, zend, idir); lowerLeft.z = lowerRight.z = upperRight.z = upperLeft.z = iz * pyrZscale + pyrZoffset; // Load the area if this is the central Z value, and set up access to the tiles if (cacheInd >= 0) { if (iz == B3DNINT((izCur - pyrZoffset) / pyrZscale)) a->vi->pyrCache->loadTilesContainingArea(cacheInd, baseXstr, baseYstr, baseXsize, baseYsize, iz); if (a->vi->pyrCache->fastPlaneAccess(cacheInd, iz, b3dZ, segments, startInds)) continue; } else { // Or get the Z section idata = ivwGetZSection(a->vi, iz); if (!idata) continue; usidata = (b3dUInt16 **)idata; } // Loop on patches in Y, for each patch get limits to fill and set corners // ypatch is the starting coordinate and jend is the ending one for (ypatch = ystr; ypatch < yend; ypatch += tstep){ clamp.y = clampEnd; jend = ypatch + tstep; if (jend > yend) { jend = yend; clamp.y = (yend + 1. - ypatch) / (tstep + 2.); } lowerRight.y = lowerLeft.y = ypatch * pyrXYscale + pyrYoffset; upperLeft.y = upperRight.y = jend * pyrXYscale + pyrYoffset; // Loop on patches in X, for each patch get limits to fill and set corners // xpatch is the starting coordinate and iend is the ending one for (xpatch = xstr; xpatch < xend; xpatch += tstep){ clamp.x = clampEnd; iend = xpatch + tstep; if (iend > xend) { iend = xend; clamp.x = (xend + 1. - xpatch) / (tstep + 2.); } upperLeft.x = lowerLeft.x = xpatch * pyrXYscale + pyrXoffset; upperRight.x = lowerRight.x = iend * pyrXYscale + pyrXoffset; fillXsize = 2 + iend - xpatch; // Fill the data for one patch then draw the patch // each patch is filled to one more than its limits to allow interpolation // u and v are the coordinates in the plane being filled if (cacheInd >= 0) { fillPatchFromTiles(segments, startInds, a->vi->ushortStore, bmap, fillXsize, xpatch-1, iend+1, ypatch-1, jend+1); } else if (a->vi->ushortStore) { for (j = ypatch-1; j < jend+1; j++) { v = (j - (ypatch-1)); for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = bmap[usidata[j][i]]; FILLDATA(pix); } } } else { for (j = ypatch-1; j < jend+1; j++) { v = (j - (ypatch-1)); for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = idata[j][i]; FILLDATA(pix); } } } imodvDrawTImage(&lowerLeft, &lowerRight, &upperRight, &upperLeft, &clamp, (unsigned char *)sTdata, fillXsize, 2 + jend - ypatch); } } } } glDisable(GL_BLEND); /* Draw Current X image. */ if ((sFlags & IMODV_DRAW_CX) && !(a->stereo && a->imageStereo)) { setSliceLimits(ixCur, xsize, invertX, drawTrans, xstr, xend, idir); setCoordLimits(iyCur, ysize, sYdrawSize, ystr, yend); setCoordLimits(izCur, zsize, sZdrawSize, zstr, zend); adjustLimitsForTiles(a, cacheInd, idir, xstr, xend, ystr, yend, zstr, zend, pyrXoffset, pyrYoffset, pyrZoffset, pyrZscale); // Outer loop on X for (xpatch = xstr; idir * (xend - xpatch) >= 0 ; xpatch += idir) { setAlpha(xpatch, xstr, xend, idir); lowerLeft.x = lowerRight.x = upperRight.x = upperLeft.x = xpatch * pyrXYscale + pyrXoffset; if (cacheInd >= 0) { if (a->vi->pyrCache->fastPlaneAccess(cacheInd, xpatch, b3dX, segments, startInds)) continue; } // Next loop on Z patches for (zpatch = zstr; zpatch < zend; zpatch += tstep){ clamp.y = clampEnd; jend = zpatch + tstep; if (jend > zend) { jend = zend; clamp.y = (zend + 1. - zpatch) / (tstep + 2.); } lowerRight.z = lowerLeft.z = zpatch * pyrZscale + pyrZoffset; upperLeft.z = upperRight.z = jend * pyrZscale + pyrZoffset; // Loop on Y patches for (ypatch = ystr; ypatch < yend; ypatch += tstep){ clamp.x = clampEnd; iend = ypatch + tstep; if (iend > yend) { iend = yend; clamp.x = (yend + 1. - ypatch) / (tstep + 2.); } upperLeft.y = lowerLeft.y = ypatch * pyrXYscale + pyrYoffset; upperRight.y = lowerRight.y = iend * pyrXYscale + pyrYoffset; fillXsize = 2 + iend - ypatch; if (cacheInd >= 0) { fillPatchFromTiles(segments, startInds, a->vi->ushortStore, bmap, fillXsize, ypatch-1, iend+1, zpatch-1, jend+1); // Handle cases of flipped or not with different loops to put test // on presence of data in the outer loop } else if (flipped) { for (i = ypatch-1; i < iend+1; i++) { u = i - (ypatch-1); if (imdata[i]) { // Invert Z when accessing cache for flipped data xconst = xpatch + (zsize - 1) * xsize; if (a->vi->ushortStore) { for (j = zpatch-1; j < jend+1; j++) { v = j - (zpatch-1); pix = bmap[usimdata[i][xconst - j * xsize]]; FILLDATA(pix); } } else { for (j = zpatch-1; j < jend+1; j++) { v = j - (zpatch-1); pix = imdata[i][xconst - j * xsize]; FILLDATA(pix); } } } else { for (j = zpatch-1; j < jend+1; j++) { v = j - (zpatch-1); FILLDATA(0); } } } } else { for (j = zpatch-1; j < jend+1; j++) { v = j - (zpatch-1); if (imdata[j]) { if (a->vi->ushortStore) { for (i = ypatch-1; i < iend+1; i++) { u = i - (ypatch-1); pix = bmap[usimdata[j][xpatch + (i * xsize)]]; FILLDATA(pix); } } else { for (i = ypatch-1; i < iend+1; i++) { u = i - (ypatch-1); pix = imdata[j][xpatch + (i * xsize)]; FILLDATA(pix); } } } else { for (i = ypatch-1; i < iend+1; i++) { u = i - (ypatch-1); FILLDATA(0); } } } } imodvDrawTImage(&lowerLeft, &lowerRight, &upperRight, &upperLeft, &clamp, (unsigned char *)sTdata, fillXsize, 2 + jend - zpatch); } } } } glDisable(GL_BLEND); /* Draw Current Y image. */ if ((sFlags & IMODV_DRAW_CY) && !(a->stereo && a->imageStereo)) { setSliceLimits(iyCur, ysize, invertY, drawTrans, ystr, yend, idir); setCoordLimits(ixCur, xsize, sXdrawSize, xstr, xend); setCoordLimits(izCur, zsize, sZdrawSize, zstr, zend); adjustLimitsForTiles(a, cacheInd, idir, xstr, xend, ystr, yend, zstr, zend, pyrXoffset, pyrYoffset, pyrZoffset, pyrZscale); // Outer loop on Y for (ypatch = ystr; idir * (yend - ypatch) >= 0 ; ypatch += idir) { setAlpha(ypatch, ystr, yend, idir); lowerLeft.y = lowerRight.y = upperRight.y = upperLeft.y = ypatch * pyrXYscale + pyrYoffset; if (cacheInd >= 0) { if (a->vi->pyrCache->fastPlaneAccess(cacheInd, ypatch, b3dY, segments, startInds)) continue; } // Loop on patches in Z for (zpatch = zstr; zpatch < zend; zpatch += tstep) { clamp.y = clampEnd; jend = zpatch + tstep; if (jend > zend) { jend = zend; clamp.y = (zend + 1. - zpatch) / (tstep + 2.); } lowerRight.z = lowerLeft.z = zpatch * pyrZscale + pyrZoffset; upperLeft.z = upperRight.z = jend * pyrZscale + pyrZoffset; // Loop on patches in X for (xpatch = xstr; xpatch < xend; xpatch += tstep) { clamp.x = clampEnd; iend = xpatch + tstep; if (iend > xend) { iend = xend; clamp.x = (xend + 1. - xpatch) / (tstep + 2.); } upperLeft.x = lowerLeft.x = xpatch * pyrXYscale + pyrXoffset; upperRight.x = lowerRight.x = iend * pyrXYscale + pyrXoffset; fillXsize = 2 + iend - xpatch; if (cacheInd >= 0) { fillPatchFromTiles(segments, startInds, a->vi->ushortStore, bmap, fillXsize, xpatch-1, iend+1, zpatch-1, jend+1); } else { // This one is easier, one outer loop and flipped, non-flipped, or // no data cases for inner loop for (j = zpatch-1; j < jend+1; j++) { v = j - (zpatch-1); if (flipped && imdata[ypatch]) { xconst = (zsize - 1 - j) * xsize; if (a->vi->ushortStore) { for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = bmap[usimdata[ypatch][i + xconst]]; FILLDATA(pix); } } else { for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = imdata[ypatch][i + xconst]; FILLDATA(pix); } } } else if (!flipped && imdata[j]) { if (a->vi->ushortStore) { for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = bmap[usimdata[j][i + (ypatch * xsize)]]; FILLDATA(pix); } } else { for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); pix = imdata[j][i + (ypatch * xsize)]; FILLDATA(pix); } } } else { for (i = xpatch-1; i < iend+1; i++) { u = i - (xpatch-1); FILLDATA(0); } } } } imodvDrawTImage(&lowerLeft, &lowerRight, &upperRight, &upperLeft, &clamp, (unsigned char *)sTdata, fillXsize, 2 + jend - zpatch); } } } } B3DFREE(bmap); glDisable(GL_BLEND); //glFlush(); glDisable(GL_TEXTURE_2D); sNumSlices = numSave; if (imodDebug('v')) imodPrintStderr("Draw time %d load %.2f draw %.2f\n", drawTime.elapsed(), sWallLoad * 1000., sWallDraw * 1000.); }
// Read an image as raw or byte data static int ReadSection(ImodImageFile *inFile, char *buf, int byte) { int ysize = inFile->ny; int i, pixel, y, maxind; float slope = inFile->slope; float offset = inFile->offset; int outmin = 0; int outmax = 255; int xmin, xmax, ymin, ymax; unsigned char *obuf; float *fbuf; unsigned char *bdata; unsigned char map[256]; QRgb *rgbdata; QRgb rgbval; QImage *image; QImage image2; unsigned char *map2 = NULL; QVector<QRgb> colorTable; if (inFile->axis == 2) return -1; if (byte && (inFile->format != IIFORMAT_LUMINANCE)) return -1; if (!inFile->header && iiReopen(inFile)) return -1; image = (QImage *)inFile->header; // Convert a 16-bpp image to 32 if (image->depth() == 16) { image2 = image->convertToFormat(QImage::Format_RGB32); if (image2.isNull()) return -1; image = &image2; } colorTable = image->colorTable(); /* set the dimensions to read in */ xmin = inFile->llx; ymin = inFile->lly; if (inFile->urx < 0) xmax = inFile->nx-1; else xmax = inFile->urx; if (inFile->ury < 0) ymax = inFile->ny-1; else ymax = inFile->ury; if (byte) { // Get a map for scaling the bytes, then get composite map to go from // pixel indexes to scaled value; map2 = get_byte_map(slope, offset, outmin, outmax, 0); maxind = B3DMAX(0, colorTable.size() - 1); for (i = 0; i < 256; i++) { pixel = qRed(colorTable[B3DMIN(i, maxind)]); map[i] = map2[pixel]; } } // Loop on the lines to get data obuf = (unsigned char *)buf; fbuf = (float *)buf; for (y = ymin; y <= ymax; y++) { bdata = image->scanLine(ysize - 1 - y); // Bytes: just map the index values if (byte == 1) { for (i = xmin; i <= xmax; i++) *obuf++ = map[bdata[i]]; } else if (byte == 2) { for (i = xmin; i <= xmax; i++) *fbuf++ = bdata[i]; // 8 bit RGB: look up in color table } else if (image->depth() == 8) { for (i = xmin; i <= xmax; i++) { rgbval = colorTable[bdata[i]]; *obuf++ = qRed(rgbval); *obuf++ = qGreen(rgbval); *obuf++ = qBlue(rgbval); } // 32-bit: convert scan line pointer to rgb, get components } else { rgbdata = (QRgb *)bdata; for (i = xmin; i <= xmax; i++) { rgbval = rgbdata[i]; *obuf++ = qRed(rgbval); *obuf++ = qGreen(rgbval); *obuf++ = qBlue(rgbval); } } } return 0; }
// A new size comes in. Compute a new rad value to keep scale constant, set window size // accounting for the menu bar void ImodvWindow::newResizerSize(int sizeX, int sizeY) { ImodvApp *a = Imodv; a->imod->view->rad *= ((float)B3DMIN(sizeX, sizeY)) / B3DMIN(a->winx, a->winy); a->mainWin->resize(sizeX, sizeY + a->mainWin->height() - a->winy); }
int main( int argc, char *argv[]) { int i, ind, col, maxValType; FILE *fout; Imod *mod; int npatch = 0; int numValues[MAX_VALUE_COLS], valueIDs[MAX_VALUE_COLS]; int ix, iy, iz; int colForVal1 = 1; float dx, dy, dz; float value, maxVal[MAX_VALUE_COLS]; int ob, co, listInd, listStart, numCols; Ipoint *pts; char format[MAX_VALUE_COLS][10]; int colToTypeMap[MAX_VALUE_COLS]; setExitPrefix("ERROR: imod2patch - "); if (argc < 3){ if (argc != 1) printf("ERROR: imod2patch - wrong # of arguments\n"); printf("imod2patch usage:\n"); printf("imod2patch [-v col] imod_model patch_file\n"); exit(1); } for (ind = 0; ind < MAX_VALUE_COLS; ind++) { numValues[ind] = 0; valueIDs[ind] = 0; colToTypeMap[ind] = -1; maxVal[ind] = -1.e37; } i = 1; if (!strcmp(argv[i], "-v")) { i++; colForVal1 = atoi(argv[i++]); } mod = imodRead(argv[i]); if (!mod) exitError("Reading model %s\n", argv[i]); if (imodBackupFile(argv[++i])) exitError("Renaming existing output file to %s\n", argv[i]); fout = fopen(argv[i], "w"); if (!fout) exitError("Could not open %s\n", argv[i]); /* Count up patches and values and find max of values */ for (ob = 0; ob < mod->objsize; ob++) { listInd = 0; for (co = 0; co < mod->obj[ob].contsize; co++) { listStart = listInd; if (mod->obj[ob].cont[co].psize >= 2) { npatch++; for (ind = 0; ind < MAX_VALUE_COLS; ind++) { listInd = listStart; if (istoreFindValue(mod->obj[ob].store, co, GEN_STORE_VALUE1 + 2 * ind, &value, &listInd)) { maxVal[ind] = B3DMAX(maxVal[ind], value); numValues[ind]++; } } } } } /* printf("numval %d %d %d %f %f %f\n", numValues[0], numValues[1], numValues[2], maxVal[0], maxVal[1], maxVal[2]); */ /* Get the value ID's if any and convert an entered ID to a type #. Also set format for output based on maximum value */ maxValType = -1; numCols = 0; for (ind = 0; ind < MAX_VALUE_COLS; ind++) { strcpy(format[ind], "%10.4f"); if (numValues[ind]) { numCols++; maxValType = ind; if (maxVal[ind] > 10.1) strcpy(format[ind], "%10.2f"); else if (maxVal[ind] > 1.01) strcpy(format[ind], "%10.3f"); } } for (ind = 0; ind < B3DMIN(maxValType + 1, mod->obj[0].extra[IOBJ_EXSIZE - 1]); ind++) valueIDs[ind] = mod->obj[0].extra[IOBJ_EXSIZE - 2 - ind]; /*printf("# vla ID %d %d %d %d\n", maxValType, valueIDs[0],valueIDs[1],valueIDs[2]);*/ /* Error checks on the column for value 1 */ if (colForVal1 < 1 || colForVal1 > numCols) { if (numCols) exitError("The column for general value type must be between 1 and %d", numCols); exitError("There are no general values stored in the model"); } colForVal1--; /* Set up map from column to value type index */ if (numValues[0]) colToTypeMap[colForVal1] = 0; col = 0; for (ind = 1; ind <= maxValType; ind++) { if (numValues[ind]) { if (!colToTypeMap[col]) col++; colToTypeMap[col++] = ind; } } /*printf("%d %d %d %d\n", numCols, colToTypeMap[0], colToTypeMap[1], colToTypeMap[2]);*/ /* Output the header line */ fprintf(fout, "%d edited positions", npatch); if (mod->obj[0].extra[IOBJ_EXSIZE - 1] > 0) for (col = 0; col < numCols; col++) fprintf(fout, " %d", valueIDs[colToTypeMap[col]]); fprintf(fout, "\n"); for (ob = 0; ob < mod->objsize; ob++) { listInd = 0; for (co = 0; co < mod->obj[ob].contsize; co++) { listStart = listInd; if (mod->obj[ob].cont[co].psize >= 2) { pts = mod->obj[ob].cont[co].pts; ix = pts[0].x + 0.5; iy = pts[0].y + 0.5; iz = pts[0].z + 0.5; dx = (pts[1].x - pts[0].x) / mod->pixsize; dy = (pts[1].y - pts[0].y) / mod->pixsize; dz = (pts[1].z - pts[0].z) / mod->pixsize; if (mod->flags & IMODF_FLIPYZ) fprintf(fout, "%6d %5d %5d %8.2f %8.2f %8.2f", ix, iz, iy, dx, dz, dy); else fprintf(fout, "%6d %5d %5d %8.2f %8.2f %8.2f", ix, iy, iz, dx, dy, dz); for (col = 0; col < numCols; col++) { ind = colToTypeMap[col]; if (numValues[ind]) { listInd = listStart; value = 0.; istoreFindValue(mod->obj[ob].store, co, GEN_STORE_VALUE1 + 2 * ind, &value, &listInd); fprintf(fout, format[ind], value); } } fprintf(fout, "\n"); } } } fclose(fout); exit(0); }
/* * Sets up variables for defining the input size and center, and section lists * for the 2D processing case, and also sets ox, oy,oz and output mode. */ void set_input_options(ClipOptions *opt, MrcHeader *hin) { int i, zst, znd, ozst; if (opt->nofsecs == IP_DEFAULT){ opt->nofsecs = hin->nz; opt->secs = (int *)malloc(sizeof(int) * hin->nz); for (i = 0; i < hin->nz; i++) opt->secs[i] = i; } if (opt->dim == 3){ if (opt->iz == IP_DEFAULT){ opt->iz = hin->nz; } if (opt->cz == IP_DEFAULT){ opt->cz = hin->nz * 0.5f; } /* If there is no output entry, make it be same as input; but if there is, and it is smaller output, trim input to that size */ if (opt->oz == IP_DEFAULT) opt->oz = opt->iz; else if (opt->iz > opt->oz) opt->iz = opt->oz; /* Set up a section list for the case where something is treated as 2d without -2d being given */ if (opt->nofsecs != IP_DEFAULT) free(opt->secs); zst = (int)floor(opt->cz - opt->iz / 2.); znd = B3DMAX(B3DMIN(zst + opt->iz - 1, hin->nz - 1), 0); zst = B3DMAX(B3DMIN(zst, hin->nz - 1), 0); opt->nofsecs = znd + 1 - zst; opt->secs = (int *)malloc(sizeof(int) * opt->nofsecs); for (i = zst; i <= znd; i++) opt->secs[i - zst] = i; /* If requested output is larger than this output set, keep track of blank slices to put out before and after */ if (opt->oz != IP_DEFAULT && opt->oz > opt->nofsecs) { ozst = (int)floor(opt->cz - opt->oz / 2.); opt->outBefore = B3DMAX(0, zst - ozst); opt->outAfter = opt->oz - opt->nofsecs - opt->outBefore; if (opt->outAfter < 0) { opt->outBefore += opt->outAfter; opt->outAfter = 0; } } } else { /* 2D case: use section list size for default output size */ if (opt->oz == IP_DEFAULT) opt->oz = opt->nofsecs; } /* Convert starting, ending X or Y to ix/cx entries - main routine already checked for conflict */ if (opt->x != IP_DEFAULT) { opt->x2 = B3DMAX(opt->x, opt->x2); opt->cx = (opt->x + opt->x2 + 1) / 2.; opt->ix = opt->x2 + 1 - opt->x; } if (opt->ix == IP_DEFAULT) opt->ix = hin->nx; if ((int)opt->cx == IP_DEFAULT) opt->cx = hin->nx * 0.5f; if (opt->ox == IP_DEFAULT) { opt->ox = opt->ix; if (opt->process == IP_UNPACK) opt->ox *= 2; } else { if (!opt->ocanresize){ show_warning("clip - Process can't change output size."); opt->ox = opt->ix; } } if (opt->y != IP_DEFAULT) { opt->y2 = B3DMAX(opt->y, opt->y2); opt->cy = (opt->y + opt->y2 + 1) / 2.; opt->iy = opt->y2 + 1 - opt->y; } if (opt->iy == IP_DEFAULT) opt->iy = hin->ny; if ((int)opt->cy == IP_DEFAULT) opt->cy = hin->ny * 0.5f; if (opt->oy == IP_DEFAULT) opt->oy = opt->iy; else{ if (!opt->ocanresize){ show_warning("clip - Process can't change output size."); opt->oy = opt->iy; } } if (opt->pad == IP_DEFAULT) opt->pad = hin->amean; if (opt->mode == IP_DEFAULT) opt->mode = hin->mode; }
/* * Write one slice to output file * kSec is the index of the sections being processed, * zWrite is address of z value at which to write, maintained here * freeSlice 1 indicates to free the slice when done */ int clipWriteSlice(Islice *slice, MrcHeader *hout, ClipOptions *opt, int kSec, int *zWrite, int freeSlice) { Islice *ps = NULL; Islice *s; int z; int blankBefore = 0; int blankAfter = 0; /* Ignore if output size is smaller than # being processed */ if (kSec < (opt->nofsecs - opt->oz) / 2 || kSec >= (opt->nofsecs - opt->oz) / 2 + opt->oz) { if (freeSlice) sliceFree(slice); return 0; } /* determine if blank slices need to be written before or after this slice */ if (opt->oz > opt->nofsecs) { if (!kSec) { if (opt->outBefore == IP_DEFAULT) blankBefore = (opt->oz - opt->nofsecs) / 2; else blankBefore = opt->outBefore; } if (kSec == opt->nofsecs - 1) { if (opt->outAfter == IP_DEFAULT) blankAfter = opt->oz - opt->nofsecs - (opt->oz - opt->nofsecs) / 2; else blankAfter = opt->outAfter; } if (blankBefore || blankAfter) { ps = clipBlankSlice(hout, opt); if (!ps) return -1; } } /* Write blank slices before */ for (z = 0; z < blankBefore; z++) if (mrc_write_slice((void *)ps->data.b, hout->fp, hout, (*zWrite)++, 'z')) return -1; /* convert slice to output mode if needed */ if (slice->mode != opt->mode && sliceNewMode(slice, opt->mode) < 0) return -1; /* Resize slice if necessary */ s = slice; if (opt->ox != slice->xsize || opt->oy != slice->ysize) { slice->mean = opt->pad; s = mrc_slice_resize(slice, opt->ox, opt->oy); if (!s) { fprintf(stderr, "clipWriteSlice: error resizing slice.\n"); return(-1); } } /* maintain min & max, add to mean unless overwriting */ sliceMMM(s); hout->amin = B3DMIN(hout->amin, s->min); hout->amax = B3DMAX(hout->amax, s->max); if (opt->add2file != IP_APPEND_OVERWRITE) hout->amean += (s->mean + (blankBefore + blankAfter) * opt->pad) / hout->nz; /* Write slice, free slices as needed */ if (mrc_write_slice((void *)s->data.b, hout->fp, hout, (*zWrite)++, 'z')) return -1; if (opt->ox != slice->xsize || opt->oy != slice->ysize) sliceFree(s); if (freeSlice) sliceFree(slice); /* Write blank slices after */ for (z = 0; z < blankAfter; z++) if (mrc_write_slice((void *)ps->data.b, hout->fp, hout, (*zWrite)++, 'z')) return -1; if (ps) sliceFree(ps); return 0; }
int main( int argc, char *argv[] ) { int i = 0; FILE *fin, *fout; struct MRCheader hdata, hout; struct MRCheader *hptr; unsigned char *buf; int bsize, csize, dsize; int inside = 0; int ntaper = DEFAULT_TAPER; int taperEntered = 0; Islice slice; int zmin = -1, zmax = -1; int secofs; char *progname = imodProgName(argv[0]); setStandardExitPrefix(progname); if (argc < 2){ fprintf(stderr, "%s version %s\n", progname, VERSION_NAME); imodCopyright(); mrctaper_help(progname); exit(3); } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'i': inside = 1; break; case 't': taperEntered = 1; if (argv[i][2] != 0x00) sscanf(argv[i], "-t%d", &ntaper); else sscanf(argv[++i], "%d", &ntaper); break; case 'z': if (argv[i][2] != 0x00) sscanf(argv[i], "-z%d%*c%d", &zmin, &zmax); else sscanf(argv[++i], "%d%*c%d", &zmin, &zmax); break; default: printf("ERROR: %s - illegal option\n", progname); mrctaper_help(progname); exit(1); break; } } else break; } if (i < (argc - 2) || i == argc){ mrctaper_help(progname); exit(3); } if (ntaper < 1 || ntaper > 127) exitError("Taper must be between 1 and 127."); if (i < argc - 1) fin = iiFOpen(argv[i++], "rb"); else fin = iiFOpen(argv[i++], "rb+"); if (fin == NULL) exitError("Opening %s.", argv[i - 1]); if (mrc_head_read(fin, &hdata)) exitError("Can't Read Input File Header."); if (sliceModeIfReal(hdata.mode) < 0) exitError("Can operate only on byte, integer and real data."); if (!taperEntered) { ntaper = (hdata.nx + hdata.ny) / 200; ntaper = B3DMIN(127, B3DMAX(DEFAULT_TAPER, ntaper)); printf("Tapering over %d pixels\n", ntaper); } if (zmin == -1 && zmax == -1) { zmin = 0; zmax = hdata.nz - 1; } else { if (zmin < 0) zmin = 0; if (zmax >= hdata.nz) zmax = hdata.nz - 1; } if (i < argc) { fout = iiFOpen(argv[i], "wb"); if (fout == NULL) exitError("Opening %s.", argv[i]); hout = hdata; hout.fp = fout; /* DNM: eliminate extra header info in the output, and mark it as not swapped */ mrcInitOutputHeader(&hout); hptr = &hout; hout.nz = zmax + 1 - zmin; hout.mz = hout.nz; hout.zlen = hout.nz; secofs = zmin; } else { if (b3dOutputFileType() == IIFILE_TIFF) exitError("Cannot write to an existing TIFF file."); hptr = &hdata; fout = fin; secofs = 0; } mrc_getdcsize(hdata.mode, &dsize, &csize); bsize = hdata.nx * hdata.ny; buf = (unsigned char *)malloc(dsize * csize * bsize); if (!buf) exitError("Couldn't get memory for slice."); sliceInit(&slice, hdata.nx, hdata.ny, hdata.mode, buf); for (i = zmin; i <= zmax; i++) { printf("\rDoing section #%4d", i); fflush(stdout); if (mrc_read_slice(buf, fin, &hdata, i, 'Z')) exitError("Reading section %d.", i); if (sliceTaperAtFill(&slice, ntaper, inside)) exitError("Can't get memory for taper operation."); if (mrc_write_slice(buf, fout, hptr, i - secofs, 'Z')) exitError("Writing section %d.", i); } puts("\nDone!"); mrc_head_label(hptr, "mrctaper: Image tapered down to fill value at edges"); mrc_head_write(fout, hptr); iiFClose(fout); return(0); }
/* Write the data volume with potential padding */ int grap_volume_write(Istack *v, MrcHeader *hout, ClipOptions *opt) { FILE *fp = hout->fp; int zs, ks, z; int k; float min, max, mean, zscale; Islice *s, *ps = NULL; int labels; if (opt->mode == IP_DEFAULT) opt->mode = v->vol[0]->mode; if (opt->ox == IP_DEFAULT) opt->ox = v->vol[0]->xsize; if (opt->oy == IP_DEFAULT) opt->oy = v->vol[0]->ysize; if (opt->oz == IP_DEFAULT) opt->oz = v->zsize; if (v->vol[0]->mode != opt->mode) for(k = 0; k < v->zsize; k++){ sliceNewMode(v->vol[k], opt->mode); } /* calculate min, max, mean of volume. */ sliceMMM(v->vol[0]); min = v->vol[0]->min; max = v->vol[0]->max; mean = v->vol[0]->mean; for(k = 1; k < v->zsize; k++){ sliceMMM(v->vol[k]); min = B3DMIN(min, v->vol[k]->min); max = B3DMAX(max, v->vol[k]->max); mean += v->vol[k]->mean; } mean /= (float)v->zsize; /* DNM 6/26/02: do not make a new header if appending or overwriting! */ switch(opt->add2file){ case IP_APPEND_OVERWRITE: ks = opt->isec; hout->nz = ks + opt->oz; opt->ox = hout->nx; opt->oy = hout->ny; if (hout->mode != v->vol[0]->mode){ fprintf(stderr, "overwriting requires data modes to be the same.\n"); return(-1); } /* DNM 6/26/02: fix min and max, also fix mz and zlen */ /* DNM 9/13/02: oops, had xlen instead of zlen */ /* todo: recalc mmm. This is a start but not much */ hout->amin = B3DMIN(min, hout->amin); hout->amax = B3DMAX(max, hout->amax); zscale = hout->zlen / hout->mz; hout->mz = hout->nz; hout->zlen = hout->mz * zscale; break; case IP_APPEND_ADD: ks = hout->nz; hout->nz = hout->nz + opt->oz; opt->ox = hout->nx; opt->oy = hout->ny; if (hout->mode != v->vol[0]->mode){ fprintf(stderr, "inserting requires data modes to be the same.\n"); return(-1); } hout->amin = B3DMIN(min, hout->amin); hout->amax = B3DMAX(max, hout->amax); hout->amean = ((hout->amean * ks) + (mean * opt->oz)) / hout->nz; zscale = hout->zlen / hout->mz; hout->mz = hout->nz; hout->zlen = hout->mz * zscale; break; case IP_APPEND_FALSE: /* New file: reinitialize header but preserve the labels, set min/max/mean */ labels = hout->nlabl; mrc_head_new(hout, opt->ox, opt->oy, opt->oz, v->vol[0]->mode); hout->nlabl = labels; hout->amin = min; hout->amax = max; hout->amean = mean; ks = 0; } if (opt->pad == IP_DEFAULT) opt->pad = hout->amean; if (mrc_head_write(fp, hout)) return -1; zs = (v->zsize - opt->oz) / 2; for (k = ks, z = zs; k < hout->nz; k++, z++) { /* printf("%d %d\n", k, z);*/ /* Write blank slice outside z range */ if ((z < 0) || (z >= v->zsize)) { if (!ps) { ps = clipBlankSlice(hout, opt); if (!ps) return -1; } if (mrc_write_slice((void *)ps->data.b, fp, hout, k, 'z')) return (-1); } else { /* Resize slice only if necessary */ s = v->vol[z]; if (opt->ox != v->vol[0]->xsize || opt->oy != v->vol[0]->ysize) { v->vol[z]->mean = opt->pad; s = mrc_slice_resize(v->vol[z], opt->ox, opt->oy); if (!s){ fprintf(stderr, "volume_write: error resizing slice.\n"); return(-1); } } if (mrc_write_slice((void *)s->data.b, fp, hout, k, 'z')) return (-1); if (opt->ox != v->vol[0]->xsize || opt->oy != v->vol[0]->ysize) sliceFree(s); } } if (ps) sliceFree(ps); return(0); }
/* Really fill the slice data for one slice */ void TumblerWindow::fillASlice(TumblerStruct *xtum) { unsigned short *sdata; short *ndata = xtum->count->data.s; int xysize = xtum->slice->xsize * xtum->slice->ysize; int n; float xs, ys, zs, xt, yt, zt; float x, y, z; float xsx, xsy, xsz; float ysx, ysy, ysz; float zsx, zsy, zsz; float xtz, ytz, ztz; int isize, jsize; int ksize, xsize, ysize, zsize; int xi, yi, zi; int i, j, k; float zoomfac; int xmin,ymin,zmin,xmax,ymax,zmax; int val; float dx, dy, dz; float x1, x2, y1, y2, z1, z2; float a, b, c, d, e, f; int pxi, nxi, pyi, nyi, pzi, nzi, cindex; int maxval = xtum->maxval; int minval = xtum->minval; float dsum; int nsum, shortcut, izoom, ilimshort, jlimshort, ishort, fillval, nmax; float zoom = xtum->zoom; unsigned char *bmap = NULL; sdata = (unsigned short *)xtum->slice->data.s; if (xtum->slice->xsize <= 0) return; if (xtum->slice->ysize <= 0) return; if (xtum->vi->ushortStore) { bmap = ivwUShortInRangeToByteMap(xtum->vi); if (!bmap) return; } zoomfac = xtum->highres ? zoom : 1.0; xmin = xtum->cx - xtum->nx/2; if (xmin < 0) xmin = 0; ymin = xtum->cy - xtum->ny/2; if (ymin < 0) ymin = 0; zmin = xtum->cz - xtum->nz/2; if (zmin < 0) zmin = 0; xmax = xtum->cx + xtum->nx/2; if (xmax >= xtum->vi->xsize) xmax = xtum->vi->xsize - 1; ymax = xtum->cy + xtum->ny/2; if (ymax >= xtum->vi->ysize) ymax = xtum->vi->ysize - 1; zmax = xtum->cz + xtum->nz/2; if (zmax >= xtum->vi->zsize) zmax = xtum->vi->zsize - 1; isize = xtum->slice->xsize; jsize = xtum->slice->ysize; ksize = xtum->ms; xsize = xtum->vi->xsize; ysize = xtum->vi->ysize; zsize = xtum->vi->zsize; xsx = xtum->xstep.x/zoomfac; xsy = xtum->xstep.y/zoomfac; xsz = xtum->xstep.z/zoomfac; ysx = xtum->ystep.x/zoomfac; ysy = xtum->ystep.y/zoomfac; ysz = xtum->ystep.z/zoomfac; /* Steps in Z are independent of highres */ zsx = xtum->zstep.x; zsy = xtum->zstep.y; zsz = xtum->zstep.z; /* DNM 4/29/04: rewrote for compactness and clarity */ xs = xtum->cx - 0.5f * (xsx * isize + ysx * jsize + zsx * xtum->ms); ys = xtum->cy - 0.5f * (xsy * isize + ysy * jsize + zsy * xtum->ms); zs = xtum->cz - 0.5f * (xsz * isize + ysz * jsize + zsz * xtum->ms); /* imodPrintStderr("xyzs %f %f %f\n", xs, ys, zs); */ x = xs; y = ys; z = zs; shortcut = 0; izoom = (int)zoom; if (xtum->highres && (zoom == izoom) && (zoom > 1.0)) { shortcut = 1; ilimshort = izoom * ((isize - 1) / izoom - 1); jlimshort = izoom * ((jsize - 1) / izoom - 1); } else izoom = 1; for(n = 0; n < xysize; n++) { sdata[n] = 0; ndata[n] = 0; } for(k = 0; k < ksize; k++){ xtz = x; ytz = y; ztz = z; for(j = 0, n = 0; j < jsize; j++){ xt = x; yt = y; zt = z; cindex = j * isize; for(i = 0; i < isize; i++){ /* DNM 2/25/03: eliminate floor as in slicer */ xi = (int)x; yi = (int)y; zi = (int)(z + 0.5); if ((xi >= xmin) && (xi <= xmax) && (yi >= ymin) && (yi <= ymax) && (zi >= zmin) && (zi <= zmax) ){ val = (*ivwFastGetValue)(xi, yi, zi); if (xtum->highres) { dx = x - xi - 0.5; dy = y - yi - 0.5; dz = z - zi; pxi = xi - 1; nxi = xi + 1; pyi = yi - 1; nyi = yi + 1; pzi = zi - 1; nzi = zi + 1; if (pxi < 0) pxi = 0; if (nxi >= xsize) nxi = xi; if (pyi < 0) pyi = 0; if (nyi >= ysize) nyi = yi; if (pzi < 0) pzi = 0; if (nzi >= zsize) nzi = zi; x1 = (*ivwFastGetValue)(pxi, yi, zi); x2 = (*ivwFastGetValue)(nxi, yi, zi); y1 = (*ivwFastGetValue)( xi, pyi, zi); y2 = (*ivwFastGetValue)( xi, nyi, zi); z1 = (*ivwFastGetValue)( xi, yi, pzi); z2 = (*ivwFastGetValue)( xi, yi, nzi); a = (x1 + x2) * 0.5f - (float)val; b = (y1 + y2) * 0.5f - (float)val; c = (z1 + z2) * 0.5f - (float)val; d = (x2 - x1) * 0.5f; e = (y2 - y1) * 0.5f; f = (z2 - z1) * 0.5f; val = (int) ((a * dx * dx) + (b * dy * dy) + (c * dz * dz) + (d * dx) + (e * dy) + (f * dz) + (float)val + 0.5); } if (bmap) val = bmap[B3DMAX(0, B3DMIN(65535, val))]; if (val > maxval) val = maxval; if (val < minval) val = minval; sdata[cindex + i] += (unsigned short)val; ndata[cindex + i]++; } x += xsx; y += xsy; z += xsz; /* If taking short cut, advance the source position to get to next unzoomed pixel position */ if (shortcut != 0 && ((i >= izoom && j % izoom == 0) || (i >= izoom - 1 && j % izoom != 0)) && i < ilimshort && j >= izoom && j < jlimshort) { ishort = izoom - 1; if (j % izoom) ishort = ilimshort - izoom; x += xsx * ishort; y += xsy * ishort; z += xsz * ishort; i += ishort; } } x = xt + ysx; y = yt + ysy; z = zt + ysz; } x = xtz + zsx; y = ytz + zsy; z = ztz + zsz; } nmax = 0; nsum = 0; dsum = 0.; for (n = 0; n < xysize; n++) { if (nmax < ndata[n]) nmax = ndata[n]; nsum += ndata[n]; dsum += sdata[n]; } fillval = (int)(dsum / nsum + 0.5); for(n = 0; n < xysize; n++) sdata[n] += (nmax - ndata[n]) * fillval; xtum->fillval = fillval * nmax; if (shortcut) slicerCubicFillin(sdata, isize, jsize, izoom, ilimshort, jlimshort, 0, 65535, 0); B3DFREE(bmap); }
/*! * Fills [mat] with the coefficients of a Gaussian kernel with standard deviation * [sigma]. The size of the kernel is set to 3 for [sigma] up to 1., 5 for [sigma] * up to 2., etc., up to the size given by [limit]. The size is returned in [dim]. * The coefficients are scaled to sum to 1. */ void scaledGaussianKernel(float *mat, int *dim, int limit, float sigma) { *dim = 2 * (int)ceil((double)sigma) + 1; *dim = B3DMIN(limit, *dim); sliceGaussianKernel(mat, *dim, sigma); }
/* Draw one of the image arrays in a subarea of the window */ void TumblerWindow::drawSubArea(TumblerStruct *xtum, unsigned short *sdata, int llx, int urx) { float scale, offset; unsigned int i, xysize; unsigned char *data; b3dUInt16 *usdata; float tf, tmax, tmin; int xo, yo; int zoom = xtum->zoom; xysize = xtum->slice->xsize * xtum->slice->ysize; data = xtum->bwslice->data.b; usdata = xtum->bwslice->data.us; scaleData(xtum, sdata); tmax = 255.0f; tmin = 0.0f; scale = xtum->scale; offset = xtum->offset; /* DNM: scale for depth 8 only if not rgba */ if (App->depth == 8 && !App->rgba){ scale *= xtum->vi->rampsize/256.0f; tmax = xtum->vi->rampbase + xtum->vi->rampsize; tmin = xtum->vi->rampbase; for(i = 0; i < xysize; i++){ tf = ((sdata[i] + offset) * scale) + xtum->vi->rampbase; if (tf < tmin) tf = tmin; if (tf > tmax) tf = tmax; data[i] = (unsigned char)tf; } } else if (xtum->vi->ushortStore) { tmax = 65535.; scale *= 256.; for (i = 0; i < xysize; i++) { tf = (sdata[i] + offset) * scale; usdata[i] = (b3dUInt16)B3DMAX(tmin, B3DMIN(tmax, tf)); } } else { for(i = 0; i < xysize; i++){ tf = (sdata[i] + offset) * scale; data[i] = (unsigned char)B3DMAX(tmin, B3DMIN(tmax, tf)); } } if (xtum->highres) zoom = 1; /* DNM 1/20/02: add slice argument to graphics calls; make it -1 to prevent image re-use */ b3dDrawGreyScalePixelsSubArea (xtum->image, ivwMakeLinePointers(xtum->vi, data, xtum->slice->xsize, xtum->slice->ysize, xtum->vi->rawImageStore), xtum->slice->xsize, xtum->slice->ysize, 0, 0, llx, 0, urx, xtum->height, xtum->vi->rampbase, zoom, &xo, &yo, -1); }
/*! * Converts the data in slice [s] from its current mode to [mode], allocating * a new data array as needed. Complex values are converted to others by * taking the magnitude. Values are converted to complex modes by setting the * real component to the value, and the imaginary component to 0. RGB values * are converted by taking a weighted sum of components. When converting to a * mode with integer or byte values, the data are truncated to fit within the * range of the new mode. Returns the new mode or -1 for error. */ int sliceNewMode(Islice *s, int mode) { Islice *ns; Ival val; int i, j; int default_copy = 0; int limit_val = 0; float minval, maxval; if (!s) return(-1); if (s->mode == mode) return(mode); ns = sliceCreate(s->xsize, s->ysize, mode); /* Set up limiting values */ if (mode == MRC_MODE_BYTE || mode == MRC_MODE_RGB) { limit_val = 1; minval = 0.; maxval = 255; } else if (mode == MRC_MODE_SHORT) { limit_val = 1; minval = -32768.; maxval = 32767.; } else if (mode == MRC_MODE_USHORT) { limit_val = 1; minval = 0.; maxval = 65535.; } if (!ns) return(-1); switch(s->mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: default_copy = 1; break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: val[1] = 0; default_copy = 1; break; case MRC_MODE_RGB: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); val[2] = val[1] = val[0]; slicePutVal(ns, i, j, val); } break; default: default_copy = 1; break; } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (float)sqrt(val[0] * val[0] + val[1] * val[1]); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: default_copy = 1; break; case MRC_MODE_RGB: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (float)sqrt(val[0] * val[0] + val[1] * val[1]); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); val[2] = val[1] = val[0]; slicePutVal(ns, i, j, val); } break; } break; case MRC_MODE_RGB: switch(mode){ case MRC_MODE_BYTE: case MRC_MODE_SHORT: case MRC_MODE_USHORT: case MRC_MODE_FLOAT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (val[0] * 0.3f) + (val[1] * 0.59f) + (val[2] * 0.11f); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } break; case MRC_MODE_COMPLEX_FLOAT: case MRC_MODE_COMPLEX_SHORT: for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); val[0] = (val[0] * 0.3f) + (val[1] * 0.59f) + (val[2] * 0.11f); val[1] = 0; slicePutVal(ns, i, j, val); } break; default: default_copy = 1; break; } break; default: default_copy = 1; break; } if (default_copy){ for(j = 0; j < s->ysize; j++) for(i = 0; i < s->xsize; i++){ sliceGetVal(s, i, j, val); if (limit_val) val[0] = B3DMIN(maxval, B3DMAX(minval, val[0])); slicePutVal(ns, i, j, val); } } free(s->data.b); /* 2/3/07: switch from copying ns to s to just setting data and mode */ s->data.b = ns->data.b; s->mode = mode; free(ns); return(mode); }
/* * Main entry */ int main( int argc, char *argv[]) { Imod *imod; Iobj *obj; Ipoint point; Istore store; FILE *infp; char line[1024]; int open = 0, zsort = 0, scat = 0, numPerCont = 0, fromZero = 0, zFromZero = 0; int err, nvals, nread, ob, co, lineNum, after, needcont, i, numOffset, linelen; int numPts = 0, numConts = 0, numObjs = 0; int sphere = 0, circle = 0; float tst1, tst2, xx, yy, zz, value; float zOffset = 0.; int numColors = 0; int numNames = 0; int hasValues = 0; int contValues = 0; int *red, *green, *blue; int directScale = 0; float xscale = 1., yscale = 1., zscale = 1., xtrans = 0., ytrans = 0., ztrans = 0.; char **names = NULL; char *progname = imodProgName(argv[0]); char *filename, *imagename; MrcHeader hdata; IrefImage *ref; FILE *fpimage = NULL; char *errString; int numOptArgs, numNonOptArgs; /* Fallbacks from ../manpages/autodoc2man 2 1 point2model */ int numOptions = 16; const char *options[] = { "input:InputFile:FN:", "output:OutputFile:FN:", "open:OpenContours:B:", "scat:ScatteredPoints:B:", "number:PointsPerContour:I:", "planar:PlanarContours:B:", "zero:NumberedFromZero:B:", "zcoord:ZCoordinatesFromZero:B:", "values:ValuesInLastColumn:I:", "circle:CircleSize:I:", "sphere:SphereRadius:I:", "color:ColorOfObject:ITM:", "name:NameOfObject:CHM:", "image:ImageForCoordinates:FN:", "pixel:PixelSpacingOfImage:FT:", "origin:OriginOfImage:FT:" }; /* Startup with fallback */ PipReadOrParseOptions(argc, argv, options, numOptions, progname, 2, 1, 1, &numOptArgs, &numNonOptArgs, imodUsageHeader); /* Get input and output files */ if (PipGetInOutFile("InputFile", 0, &filename)) exitError("No input file specified"); infp = fopen(filename, "r"); if (!infp) exitError("Error opening input file %s", filename); free(filename); if (PipGetInOutFile("OutputFile", 1, &filename)) exitError("No output file specified"); if (!PipGetString("ImageForCoordinates", &imagename)) { fpimage = fopen(imagename, "rb"); if (!fpimage) exitError("Could not open image file for coordinates: %s", imagename); if (mrc_head_read(fpimage, &hdata)) exitError("Reading header from %s", imagename); free(imagename); } directScale = 2 - PipGetThreeFloats("PixelSpacingOfImage", &xscale, &yscale, &zscale) - PipGetThreeFloats("OriginOfImage", &xtrans, &ytrans, &ztrans); if (directScale && fpimage) exitError("You cannot use -image together with -pixel or -origin"); err = PipGetInteger("PointsPerContour", &numPerCont); err = PipGetInteger("SphereRadius", &sphere); err = PipGetInteger("CircleSize", &circle); err = PipGetBoolean("OpenContours", &open); err = PipGetBoolean("ScatteredPoints", &scat); err = PipGetBoolean("PlanarContours", &zsort); err = PipGetInteger("ValuesInLastColumn", &hasValues); err = PipGetBoolean("ZCoordinatesFromZero", &zFromZero); if (zFromZero) zOffset = 0.5; B3DCLAMP(hasValues, -1, 1); if (hasValues < 0) { hasValues = 1; contValues = 1; } err = PipGetBoolean("NumberedFromZero", &fromZero); numOffset = 1 - fromZero; if (numPerCont < 0) exitError("Number of points per contour must be positive or zero"); if (open + scat > 1) exitError("Only one of -open or -scat may be entered"); // Get colors err = PipNumberOfEntries("ColorOfObject", &numColors); if (numColors) { red = (int *)malloc(numColors * sizeof(int)); green = (int *)malloc(numColors * sizeof(int)); blue = (int *)malloc(numColors * sizeof(int)); if (!red || !green || !blue) exitError("Allocating memory for colors"); for (co = 0; co < numColors; co++) err = PipGetThreeIntegers("ColorOfObject", &red[co], &green[co], &blue[co]); } // Get names err = PipNumberOfEntries("NameOfObject", &numNames); if (numNames) { names = (char **)malloc(numNames * sizeof(char *)); if (!names) exitError("Allocating memory for names"); for (co = 0; co < numNames; co++) err = PipGetString("NameOfObject", &names[co]); } PipDone(); // Read first line of file, figure out how many values if (fgetline(infp, line, 1024) <= 0) exitError("Reading beginning of file"); nvals = sscanf(line, "%f %f %f %f %f %f", &tst1, &tst2, &xx, &yy, &zz, &value); nvals -= hasValues; if (nvals < 3) exitError("There must be at least %d values per line", 3 + hasValues); nvals = B3DMIN(nvals, 5); if (numPerCont && nvals > 3) { exitError("The point file has contour numbers and the -number option " "cannot be used"); } if (zsort && nvals > 3) exitError("The point file has contour numbers and the -planar option " "cannot be used"); rewind(infp); imod = imodNew(); if (!imod) exitError("Failed to get model structure"); // Set the image reference scaling if (fpimage) { imodSetRefImage(imod, &hdata); fclose(fpimage); } else if (directScale) { imod->refImage = (IrefImage *)malloc(sizeof(IrefImage)); if (!imod->refImage) exitError("Allocating IrefImage structure"); ref = imod->refImage; ref->ctrans.x = xtrans; ref->ctrans.y = ytrans; ref->ctrans.z = ztrans; ref->cscale.x = xscale; ref->cscale.y = yscale; ref->cscale.z = zscale; ref->oscale.x = ref->oscale.y = ref->oscale.z = 1.; ref->orot.x = ref->orot.y = ref->orot.z = 0.; ref->crot.x = ref->crot.y = ref->crot.z = 0.; ref->otrans.x = ref->otrans.y = ref->otrans.z = 0.; } ob = 0; co = 0; lineNum = 0; imod->xmax = 0.; imod->ymax = 0.; imod->zmax = 0.; store.type = GEN_STORE_VALUE1; store.flags = GEN_STORE_FLOAT << 2; // To do: error check contour and object #'s, and they are numbered from 1. while (1) { // get line, done on EOF, skip blank line linelen = fgetline(infp, line, 1024); if (linelen < 0) break; if (linelen == 0) continue; if (nvals == 3) { nread = sscanf(line, "%f %f %f %f", &xx, &yy, &zz, &value); } else if (nvals == 4) { nread = sscanf(line, "%d %f %f %f %f", &co, &xx, &yy, &zz, &value); co -= numOffset; } else { nread = sscanf(line, "%d %d %f %f %f %f", &ob, &co, &xx, &yy, &zz, &value); co -= numOffset; ob -= numOffset; } zz -= zOffset; lineNum++; // Skip line with no values if (nread <= 0) continue; if (B3DMIN(5 + hasValues, nread) != nvals + hasValues && !(contValues && nread == nvals)) exitError("Every line should have %d entries; line %d has %d", nvals + hasValues, lineNum, nread); if (ob < 0 || co < 0) exitError("Illegal object or contour number (object %d, contour %d at line %d", ob + numOffset, co + numOffset, lineNum); // Add objects if needed to get to the current object if (ob >= imod->objsize) { for (i = imod->objsize; i <= ob; i++) { if (imodNewObject(imod)) exitError("Failed to add object to model"); if (open) imod->obj[i].flags |= IMOD_OBJFLAG_OPEN; if (scat) imod->obj[i].flags |= IMOD_OBJFLAG_SCAT | IMOD_OBJFLAG_OPEN; numObjs++; imod->obj[i].pdrawsize = B3DMAX(0, sphere); if (circle > 0) { imod->obj[i].symsize = circle; imod->obj[i].symbol = IOBJ_SYM_CIRCLE; } if (i < numColors) { imod->obj[i].red = red[i] / 255.; imod->obj[i].green = green[i] / 255.; imod->obj[i].blue = blue[i] / 255.; } if (i < numNames) { strncpy(imod->obj[i].name, names[i], IOBJ_STRSIZE - 1); imod->obj[i].name[IOBJ_STRSIZE - 1] = 0x00; } } } // Determine if a contour is needed: either the contour number is too high // or the number limit is reached or there is a change in Z needcont = 0; obj = &imod->obj[ob]; if (co >= obj->contsize) needcont = 1; else if ((numPerCont && obj->cont[co].psize >= numPerCont) || (zsort && B3DNINT(obj->cont[co].pts[0].z) != B3DNINT(zz))) { co++; needcont = 1; } if (needcont) { imodSetIndex(imod, ob, -1, -1); for (i = obj->contsize; i<= co; i++) { if (imodNewContour(imod)) exitError("Failed to add contour to model"); numConts++; } } point.x = xx; point.y = yy; point.z = zz; imod->xmax = B3DMAX(imod->xmax, B3DNINT(xx + 10.)); imod->ymax = B3DMAX(imod->ymax, B3DNINT(yy + 10.)); imod->zmax = B3DMAX(imod->zmax, B3DNINT(zz + 1.)); if (!imodPointAppend(&obj->cont[co], &point)) exitError("Failed to add point to contour"); numPts++; // take care of value for contour or point, only add one per contour if (hasValues) { store.value.f = value; err = 0; if (contValues && istoreLookup(obj->store, co, &after) < 0) { if (nread < nvals + 1) exitError("The first point for a contour must have a value entry; line %d " "has only %d entries", lineNum, nread); store.index.i = co; err = istoreInsert(&obj->store, &store); } else { store.index.i = obj->cont[co].psize - 1; err = istoreInsert(&obj->cont[co].store, &store); } if (err) exitError("Failed to add general value"); } } // Get the object min/max values set up if (hasValues) { for (ob = 0; ob < imod->objsize; ob++) { if (imod->obj[ob].contsize && istoreFindAddMinMax1(&imod->obj[ob])) exitError("Adding min/max values to object"); } } // Attach image file's size as the max values if (fpimage) { imod->xmax = hdata.nx; imod->ymax = hdata.ny; imod->zmax = hdata.nz; } fclose(infp); if (imodBackupFile(filename)) printf("Warning: %s - Failed to make old version of %s be a backup file\n", progname, filename); imod->file = fopen(filename, "wb"); if (!imod->file) exitError("Opening new model file %s", filename); if (imodWriteFile(imod)) exitError("Writing model file %s", filename); free(filename); printf("Model created with %d objects, %d contours, %d points\n", numObjs, numConts, numPts); exit(0); }