bool TIFFOutput::write_tile (int x, int y, int z, TypeDesc format, const void *data, stride_t xstride, stride_t ystride, stride_t zstride) { if (! m_spec.valid_tile_range (x, x, y, y, z, z)) return false; m_spec.auto_stride (xstride, ystride, zstride, format, spec().nchannels, spec().tile_width, spec().tile_height); x -= m_spec.x; // Account for offset, so x,y are file relative, not y -= m_spec.y; // image relative const void *origdata = data; // Stash original pointer data = to_native_tile (format, data, xstride, ystride, zstride, m_scratch); if (m_planarconfig == PLANARCONFIG_SEPARATE && m_spec.nchannels > 1) { // Convert from contiguous (RGBRGBRGB) to separate (RRRGGGBBB) imagesize_t tile_pixels = m_spec.tile_pixels(); imagesize_t plane_bytes = tile_pixels * m_spec.format.size(); DASSERT (plane_bytes*m_spec.nchannels == m_spec.tile_bytes()); m_scratch.resize (m_spec.tile_bytes()); contig_to_separate (tile_pixels, (const unsigned char *)data, &m_scratch[0]); for (int c = 0; c < m_spec.nchannels; ++c) { if (TIFFWriteTile (m_tif, (tdata_t)&m_scratch[plane_bytes*c], x, y, z, c) < 0) { error ("TIFFWriteTile failed"); return false; } } } else { // No contig->separate is necessary. But we still use scratch // space since TIFFWriteTile is destructive when // TIFFTAG_PREDICTOR is used. if (data == origdata) { m_scratch.assign ((unsigned char *)data, (unsigned char *)data + m_spec.tile_bytes()); data = &m_scratch[0]; } if (TIFFWriteTile (m_tif, (tdata_t)data, x, y, z, 0) < 0) { error ("TIFFWriteTile failed"); return false; } } // Should we checkpoint? Only if we have enough tiles and enough time has passed if (m_checkpointTimer() > DEFAULT_CHECKPOINT_INTERVAL_SECONDS && m_checkpointItems >= MIN_SCANLINES_OR_TILES_PER_CHECKPOINT) { TIFFCheckpointDirectory (m_tif); m_checkpointTimer.lap(); m_checkpointItems = 0; } else { ++m_checkpointItems; } return true; }
// overwrite a tile on an existing tiled TIFF image static void put_tile_into_file(char *filename, struct tiff_tile *t, int tidx) { if (t->broken) fail("can not save broken tiles yet"); // Note, the mode "r+" is officially undocumented, but its behaviour is // described on file tif_open.c from libtiff. TIFF *tif = tiffopen_fancy(filename, "r+"); if (!tif) fail("could not open TIFF file \"%s\" for writing", filename); int tw = tiff_tilewidth(tif); int th = tiff_tilewidth(tif); int spp = tiff_samplesperpixel(tif); int bps = tiff_bitspersample(tif); //int fmt = tiff_sampleformat(tif); if (tw != t->w) fail("tw=%d different to t->w=%d", tw, t->w); if (th != t->h) fail("th=%d different to t->h=%d", th, t->h); if (spp != t->spp) fail("spp=%d different to t->spp=%d", spp, t->spp); if (bps != t->bps) fail("bps=%d different to t->bps=%d", bps, t->bps); if (spp != t->spp) fail("spp=%d different to t->spp=%d", spp, t->spp); int ii[2]; int r = tiff_tile_corner(ii, tif, tidx); if (!r) fail("bad tile %d", tidx); r = TIFFWriteTile(tif, t->data, ii[0], ii[1], 0, 0); TIFFClose(tif); }
static void create_zero_tiff_file(char *filename, int w, int h, int tw, int th, int spp, int bps, int fmt, bool incomplete, bool compressed) { //if (bps != 8 && bps != 16 && bps == 32 && bps != 64 // && bps != 128 && bps != 92) // fail("bad bps=%d", bps); //if (spp < 1) fail("bad spp=%d", spp); //int fmt_id = fmt_from_string(fmt); double gigabytes = (spp/8.0) * w * h * bps / 1024.0 / 1024.0 / 1024.0; //fprintf(stderr, "gigabytes = %g\n", gigabytes); TIFF *tif = TIFFOpen(filename, gigabytes > 1 ? "w8" : "w"); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_TILEWIDTH, tw); TIFFSetField(tif, TIFFTAG_TILELENGTH, th); if (compressed) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); int tilesize = tw * th * bps/8 * spp; uint8_t *buf = xmalloc(tilesize); for (int i = 0; i < tilesize; i++) { float x = ((i/((spp*bps)/8))%tw)/((double)tw)-0.5; float y = ((i/((spp*bps)/8))/th)/((double)th)-0.5; //buf[i] = 0; buf[i] = 127.5+128*cos(90*pow(hypot(x,y+0.3*x),1+(i%spp-1)/1.3)); } TIFFWriteTile(tif, buf, 0, 0, 0, 0); TIFFClose(tif); if (!incomplete) { for (int j = 0; j < h; j += th) for (int i = 0; i < w; i += tw) { tif = TIFFOpen(filename, "r+"); TIFFWriteTile(tif, buf, i, j, 0, 0); TIFFClose(tif); } } free(buf); }
/// Write tile data at position pos to the file. Threadsafe. virtual bool writeTile(const V2i& pos, void* data) { if(!m_tif) return false; if(m_tiled) { return TIFFWriteTile(m_tif, data, pos.x, pos.y, 0, 0) != -1; } else { // TODO: Do some buffering or something // TIFFWriteScanline(tif, buf, lineNum); return false; } }
void CqTiffOutputFile::writeTiledPixels(const CqMixedImageBuffer& buffer) { SqTileInfo tileInfo = m_header.find<Attr::TileInfo>(); // Check that the buffer has a height that is a multiple of the tile height. if( buffer.height() % tileInfo.height != 0 && m_currentLine + buffer.height() != m_header.height() ) { AQSIS_THROW_XQERROR(XqInternal, EqE_Bug, "pixel buffer with height = " << buffer.height() << " must be a multiple " "of requested tile height (= " << tileInfo.height << ") or run exactly to " "the full image height (= " << m_header.height() << ")."); } CqTiffDirHandle dirHandle(m_fileHandle); const TqUint8* rawBuf = buffer.rawData(); const TqInt bytesPerPixel = buffer.channelList().bytesPerPixel(); boost::scoped_array<TqUint8> tileBuf( new TqUint8[bytesPerPixel*tileInfo.width*tileInfo.height]); const TqInt rowStride = bytesPerPixel*buffer.width(); const TqInt tileRowStride = bytesPerPixel*tileInfo.width; const TqInt endLine = m_currentLine + buffer.height(); const TqInt numTileCols = (buffer.width()-1)/tileInfo.width + 1; for(TqInt line = m_currentLine; line < endLine; line += tileInfo.height) { // srcBuf will point to the beginning of the memory region which will // become the tile. const TqUint8* srcBuf = rawBuf; for(TqInt tileCol = 0; tileCol < numTileCols; ++tileCol) { const TqInt tileDataLen = min(tileRowStride, rowStride - tileCol*tileRowStride); const TqInt tileDataHeight = min(tileInfo.height, buffer.height() - line); // Copy parts of the scanlines into the tile buffer. stridedCopy(tileBuf.get(), tileRowStride, srcBuf, rowStride, tileDataHeight, tileDataLen); TIFFWriteTile(dirHandle.tiffPtr(), reinterpret_cast<tdata_t>(const_cast<TqUint8*>(tileBuf.get())), tileCol*tileInfo.width, line, 0, 0); srcBuf += tileRowStride; } rawBuf += rowStride*tileInfo.height; } m_currentLine = endLine; }
/* Write a set of tiles across the strip. */ static int layer_write_tile( Write *write, Layer *layer, VipsRegion *strip ) { VipsImage *im = layer->image; VipsRect *area = &strip->valid; VipsRect image; int x; image.left = 0; image.top = 0; image.width = im->Xsize; image.height = im->Ysize; for( x = 0; x < im->Xsize; x += write->tilew ) { VipsRect tile; tile.left = x; tile.top = area->top; tile.width = write->tilew; tile.height = write->tileh; vips_rect_intersectrect( &tile, &image, &tile ); /* Have to repack pixels. */ pack2tiff( write, layer, strip, &tile, write->tbuf ); #ifdef DEBUG_VERBOSE printf( "Writing %dx%d tile at position %dx%d to image %s\n", tile.width, tile.height, tile.left, tile.top, TIFFFileName( layer->tif ) ); #endif /*DEBUG_VERBOSE*/ if( TIFFWriteTile( layer->tif, write->tbuf, tile.left, tile.top, 0, 0 ) < 0 ) { vips_error( "vips2tiff", "%s", _( "TIFF write tile failed" ) ); return( -1 ); } } return( 0 ); }
void master(const struct fracInfo info) { int ntasks, dest, msgsize; struct fracData *work = malloc(sizeof(*work)); MPI_Status status; int rowsTaken = 0; MPI_Comm_size(MPI_COMM_WORLD, &ntasks); size_t size = sizeof(unsigned char) * (unsigned long)info.nCols * (unsigned long)info.nRows; unsigned char *fractal = (unsigned char*)malloc(size); if(!fractal) { printf("fractal allocation failed, %lu bytes\n", size); exit(1); } // Allocate buffer int membersize, emptysize, fullsize; int position; char *buffer; MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD, &membersize); emptysize = membersize; MPI_Pack_size(1, MPI_INT, MPI_COMM_WORLD, &membersize); emptysize += membersize; MPI_Pack_size(get_max_work_size(&info), MPI_UNSIGNED_CHAR, MPI_COMM_WORLD, &membersize); fullsize = emptysize + membersize; buffer = malloc(fullsize); if(!buffer) { printf("buffer allocation failed, %d bytes\n",fullsize); exit(1); } // Send initial data for (dest = 1; dest < ntasks; dest++) { //Get next work item get_work(&info,&rowsTaken,work); //pack and send work position = 0; MPI_Pack(&work->startRow,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD); MPI_Pack(&work->nRows,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD); MPI_Send(buffer, position, MPI_PACKED, dest, WORKTAG, MPI_COMM_WORLD); } printf("sent initial work\n"); //Get next work item get_work(&info,&rowsTaken,work); int startRow, nRows; while(work->nRows) { // Recieve and unpack work MPI_Recv(buffer, fullsize, MPI_PACKED, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); position = 0; MPI_Get_count(&status, MPI_PACKED, &msgsize); MPI_Unpack(buffer, msgsize, &position, &startRow,1,MPI_INT,MPI_COMM_WORLD); MPI_Unpack(buffer, msgsize, &position, &nRows,1,MPI_INT,MPI_COMM_WORLD); MPI_Unpack(buffer, msgsize, &position, fractal+((unsigned long)startRow*info.nCols), nRows*info.nCols, MPI_UNSIGNED_CHAR, MPI_COMM_WORLD); //pack and send work position = 0; MPI_Pack(&work->startRow,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD); MPI_Pack(&work->nRows,1,MPI_INT,buffer,emptysize,&position,MPI_COMM_WORLD); MPI_Send(buffer, position, MPI_PACKED, status.MPI_SOURCE, WORKTAG, MPI_COMM_WORLD); //Get next work item get_work(&info,&rowsTaken,work); if(status.MPI_SOURCE==1) printf("%d\n",work->startRow); } // Recieve all remaining work for (dest = 1; dest < ntasks; dest++) { // Recieve and unpack work MPI_Recv(buffer, fullsize, MPI_PACKED, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); position = 0; MPI_Get_count(&status, MPI_PACKED, &msgsize); MPI_Unpack(buffer, msgsize, &position, &startRow,1,MPI_INT,MPI_COMM_WORLD); MPI_Unpack(buffer, msgsize, &position, &nRows,1,MPI_INT,MPI_COMM_WORLD); // unpack pixel data MPI_Unpack(buffer, msgsize, &position, fractal+((unsigned long)startRow*info.nCols), nRows*info.nCols, MPI_UNSIGNED_CHAR, MPI_COMM_WORLD); // Kill slaves MPI_Send(0,0,MPI_INT,dest,DIETAG,MPI_COMM_WORLD); } free(work); free(buffer); //Save image as TIFF unsigned int nx = info.nCols; unsigned int ny = info.nRows; char fileName[] = "/home/pi/Mandelbrot/Mandelbrot.tiff"; TIFF *out = TIFFOpen(fileName, "w"); uint32 tileDim = 256; tsize_t tileBytes = tileDim*tileDim*sizeof(char); unsigned char *buf = (unsigned char *)_TIFFmalloc(tileBytes); char description[1024]; snprintf(description, sizeof(description),"xStart:%f yStart:%f spacing:%f AAx:%d",info.xStart,info.yStart,info.spacing,info.AA); TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, description); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) nx); TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) ny); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_LZW); TIFFSetField(out, TIFFTAG_TILEWIDTH, tileDim); TIFFSetField(out, TIFFTAG_TILELENGTH, tileDim); // TIFFSetField(out, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); // TIFFSetField(out, TIFFTAG_XRESOLUTION, resolution); // TIFFSetField(out, TIFFTAG_YRESOLUTION, resolution); // TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); unsigned long x,y,i,j; unsigned long tileStart; // Iterate through and write tiles for(y=0; y<ny; y+=tileDim) { for(x=0; x<nx; x+=tileDim) { // Fill tile with fractal data tileStart = y*nx+x; for(i=0; i<tileDim; i++) { for(j=0; j<tileDim; j++) { if(x+j < nx && y+i < ny) buf[i*tileDim+j] = fractal[(y+i)*nx+(x+j)]; else buf[i*tileDim+j] = (unsigned char)0; } } TIFFWriteTile(out, buf, x, y, 0, 0); } } TIFFClose(out); _TIFFfree(buf); free(fractal); }
/////////////////////////////////////////////////////////////////////// // Function : appendLayer // Description : Append a layer of image into an image file // Return Value : - // Comments : static void appendLayer(TIFF *out,int dstart,int numSamples,int bitsperpixel,int tileSize,int width,int height,void *data) { int x,y; unsigned char *tileData; int pixelSize; TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (unsigned long) width); TIFFSetField(out, TIFFTAG_IMAGELENGTH, (unsigned long) height); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE); TIFFSetField(out, TIFFTAG_XRESOLUTION, 1.0f); TIFFSetField(out, TIFFTAG_YRESOLUTION, 1.0f); TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_LZW); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_THUNDERSCAN); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_PIXARFILM); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_PIXARLOG); //TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (unsigned long) numSamples); TIFFSetField(out, TIFFTAG_TILEWIDTH, (unsigned long) tileSize); TIFFSetField(out, TIFFTAG_TILELENGTH, (unsigned long) tileSize); if (bitsperpixel == 8) { TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (unsigned long) (sizeof(unsigned char)*8)); pixelSize = numSamples*sizeof(unsigned char); } else if (bitsperpixel == 16) { TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (unsigned long) (sizeof(unsigned short)*8)); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); pixelSize = numSamples*sizeof(unsigned short); } else { TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (unsigned long) (sizeof(float)*8)); pixelSize = numSamples*sizeof(float); } memBegin(CRenderer::globalMemory); tileData = (unsigned char *) ralloc(pixelSize*tileSize*tileSize,CRenderer::globalMemory); assert(TIFFTileSize(out) == (tileSize*tileSize*pixelSize)); for (y=0;y<height;y+=tileSize) { for (x=0;x<width;x+=tileSize) { int ty; for (ty=0;ty<tileSize;ty++) { memcpy(&tileData[ty*tileSize*pixelSize],&((unsigned char *) data)[((y+ty)*width+x)*pixelSize],tileSize*pixelSize); } TIFFWriteTile(out,tileData,x,y,0,0); } } TIFFWriteDirectory(out); memEnd(CRenderer::globalMemory); }