bool ImageBuf::copy_pixels (int xbegin, int xend, int ybegin, int yend, TypeDesc format, void *result) const { #if 1 // Fancy method -- for each possible base type that the user // wants for a destination type, call a template specialization. switch (format.basetype) { case TypeDesc::UINT8 : copy_pixels<unsigned char> (xbegin, xend, ybegin, yend, (unsigned char *)result); break; case TypeDesc::INT8: copy_pixels<char> (xbegin, xend, ybegin, yend, (char *)result); break; case TypeDesc::UINT16 : copy_pixels<unsigned short> (xbegin, xend, ybegin, yend, (unsigned short *)result); break; case TypeDesc::INT16 : copy_pixels<short> (xbegin, xend, ybegin, yend, (short *)result); break; case TypeDesc::UINT : copy_pixels<unsigned int> (xbegin, xend, ybegin, yend, (unsigned int *)result); break; case TypeDesc::INT : copy_pixels<int> (xbegin, xend, ybegin, yend, (int *)result); break; case TypeDesc::HALF : copy_pixels<half> (xbegin, xend, ybegin, yend, (half *)result); break; case TypeDesc::FLOAT : copy_pixels<float> (xbegin, xend, ybegin, yend, (float *)result); break; case TypeDesc::DOUBLE : copy_pixels<double> (xbegin, xend, ybegin, yend, (double *)result); break; case TypeDesc::UINT64 : copy_pixels<unsigned long long> (xbegin, xend, ybegin, yend, (unsigned long long *)result); break; case TypeDesc::INT64 : copy_pixels<long long> (xbegin, xend, ybegin, yend, (long long *)result); break; default: return false; } #else // Naive method -- loop over pixels, calling getpixel() size_t usersize = format.size() * nchannels(); float *pel = (float *) alloca (nchannels() * sizeof(float)); for (int y = ybegin; y < yend; ++y) for (int x = xbegin; x < xend; ++x) { getpixel (x, y, pel); convert_types (TypeDesc::TypeFloat, pel, format, result, nchannels()); result = (void *) ((char *)result + usersize); } #endif return true; }
bool ImageBuf::get_pixels (int xbegin, int xend, int ybegin, int yend, int zbegin, int zend, TypeDesc format, void *result, stride_t xstride, stride_t ystride, stride_t zstride) const { return get_pixel_channels (xbegin, xend, ybegin, yend, zbegin, zend, 0, nchannels(), format, result, xstride, ystride, zstride); }
void PtexReader::blendFaces(FaceData*& face, int faceid, Res res, bool blendu) { Res pres; // parent res, 1 higher in blend direction int length; // length of blend edge (1xN or Nx1) int e1, e2; // neighboring edge ids if (blendu) { assert(res.ulog2 < 0); // res >= 0 requires reduction, not blending length = (res.vlog2 <= 0 ? 1 : res.v()); e1 = e_bottom; e2 = e_top; pres = Res(res.ulog2+1, res.vlog2); } else { assert(res.vlog2 < 0); length = (res.ulog2 <= 0 ? 1 : res.u()); e1 = e_right; e2 = e_left; pres = Res(res.ulog2, res.vlog2+1); } // get neighbor face ids FaceInfo& f = _faceinfo[faceid]; int nf1 = f.adjfaces[e1], nf2 = f.adjfaces[e2]; // compute rotation of faces relative to current int r1 = (f.adjedge(e1)-e1+2)&3; int r2 = (f.adjedge(e2)-e2+2)&3; // swap u and v res for faces rotated +/- 90 degrees Res pres1 = pres, pres2 = pres; if (r1 & 1) pres1.swapuv(); if (r2 & 1) pres2.swapuv(); // ignore faces that have insufficient res (unlikely, but possible) if (nf1 >= 0 && !(_faceinfo[nf1].res >= pres)) nf1 = -1; if (nf2 >= 0 && !(_faceinfo[nf2].res >= pres)) nf2 = -1; // get parent face data int nf = 1; // number of faces to blend (1 to 3) bool flip[3]; // true if long dimension needs to be flipped PtexFaceData* psrc[3]; // the face data psrc[0] = getData(faceid, pres); flip[0] = 0; // don't flip main face if (nf1 >= 0) { // face must be flipped if rot is 1 or 2 for blendu, or 2 or 3 for blendv // thus, just add the blendu bool val to align the ranges and check bit 1 // also, no need to flip if length is zero flip[nf] = length ? (r1 + blendu) & 1 : 0; psrc[nf++] = getData(nf1, pres1); } if (nf2 >= 0) { flip[nf] = length ? (r2 + blendu) & 1 : 0; psrc[nf++] = getData(nf2, pres2); } // get reduce lock and make sure we still need to reduce AutoMutex rlocker(reducelock); if (face) { // another thread must have generated it while we were waiting AutoLockCache locker(_cache->cachelock); // make sure it's still there now that we have the lock if (face) { face->ref(); // release parent data for (int i = 0; i < nf; i++) psrc[i]->release(); return; } } // allocate a new face data (1 x N or N x 1) DataType dt = datatype(); int nchan = nchannels(); int size = _pixelsize * length; PackedFace* pf = new PackedFace((void**)&face, _cache, res, _pixelsize, size); void* data = pf->getData(); if (nf == 1) { // no neighbors - just copy face memcpy(data, psrc[0]->getData(), size); } else { float weight = 1.0f / nf; memset(data, 0, size); for (int i = 0; i < nf; i++) PtexUtils::blend(psrc[i]->getData(), weight, data, flip[i], length, dt, nchan); } { AutoLockCache clocker(_cache->cachelock); face = pf; // clean up unused data _cache->purgeData(); } // release parent data for (int i = 0; i < nf; i++) psrc[i]->release(); }