// Save a raw image instance into a file bool save_image(const std::string &dest_filename, LLPointer<LLImageRaw> raw_image, int blocks_size, int precincts_size, int levels, bool reversible, bool output_stats) { LLPointer<LLImageFormatted> image = create_image(dest_filename); // Set the image codestream parameters on output in the case of a j2c image if (image->getCodec() == IMG_CODEC_J2C) { // That method doesn't exist (and likely, doesn't make sense) for any other image file format // hence the required cryptic cast. if ((blocks_size != -1) || (precincts_size != -1) || (levels != 0)) { ((LLImageJ2C*)(image.get()))->initEncode(*raw_image, blocks_size, precincts_size, levels); } ((LLImageJ2C*)(image.get()))->setReversible(reversible); } if (!image->encode(raw_image, 0.0f)) { return false; } if (output_stats) { output_image_stats(image, dest_filename); } return image->save(dest_filename); }
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLPointer<LLImageRaw> raw = new LLImageRaw; S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); F32 ratio = (F32)width / height; F32 supersample = 1.f; if (gSavedSettings.getBOOL("HighResSnapshot")) { #if 1//SHY_MOD // screenshot improvement const F32 mult = gSavedSettings.getF32("SHHighResSnapshotScale"); width *= mult; height *= mult; static const LLCachedControl<F32> super_sample_scale("SHHighResSnapshotSuperSample",1.f); supersample = super_sample_scale; #else //shy_mod width *= 2; height *= 2; #endif //ignore } if (gViewerWindow->rawSnapshot(raw, width, height, ratio, gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE, LLViewerWindow::SNAPSHOT_TYPE_COLOR, 6144, supersample)) { LLPointer<LLImageFormatted> formatted; switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: formatted = new LLImagePNG; break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: formatted = new LLImageBMP; break; default: llwarns << "Unknown Local Snapshot format" << llendl; return true; } formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize(); gViewerWindow->saveImageNumbered(formatted, -1); } return true; }
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLPointer<LLImageRaw> raw = new LLImageRaw; S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); if (gSavedSettings.getBOOL("HighResSnapshot")) { #if SHY_MOD // screenshot improvement const F32 mult = gSavedSettings.getF32("SHHighResSnapshotScale"); width *= mult; height *= mult; #else //shy_mod width *= 2; height *= 2; #endif //ignore } if (gViewerWindow->rawSnapshot(raw, width, height, TRUE, FALSE, gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE)) { gViewerWindow->playSnapshotAnimAndSound(); LLPointer<LLImageFormatted> formatted; switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: formatted = new LLImagePNG; break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: formatted = new LLImageBMP; break; default: llwarns << "Unknown Local Snapshot format" << llendl; return true; } formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize(); gViewerWindow->saveImageNumbered(formatted); } return true; }
// note: modifies the argument raw_image!!!! LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image) { raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); compressedImage->setRate(0.f); if (gSavedSettings.getBOOL("LosslessJ2CUpload") && (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)) compressedImage->setReversible(TRUE); compressedImage->encode(raw_image, 0.0f); if (!compressedImage->encode(raw_image, 0.0f)) { llinfos << "convertToUploadFile : encode returns with error!!" << llendl; // Clear up the pointer so we don't leak that one compressedImage = NULL; } return compressedImage; }
// note: modifies the argument raw_image!!!! LLPointer<LLImageJ2C> LLViewerImageList::convertToUploadFile(LLPointer<LLImageRaw> raw_image) { raw_image->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT); LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C(); compressedImage->setRate(0.f); if (gSavedSettings.getBOOL("LosslessJ2CUpload") && (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)) compressedImage->setReversible(TRUE); compressedImage->encode(raw_image, 0.0f); return compressedImage; }
// static void LLFloaterAuction::onClickSnapshot(void* data) { LLFloaterAuction* self = (LLFloaterAuction*)(data); LLPointer<LLImageRaw> raw = new LLImageRaw; gForceRenderLandFence = self->getChild<LLUICtrl>("fence_check")->getValue().asBoolean(); BOOL success = gViewerWindow->rawSnapshot(raw, gViewerWindow->getWindowWidthScaled(), gViewerWindow->getWindowHeightScaled(), TRUE, FALSE, FALSE, FALSE); gForceRenderLandFence = FALSE; if (success) { self->mTransactionID.generate(); self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID()); // <FS:PP> FIRE-8190: Preview function for "UI Sounds" Panel // if(!gSavedSettings.getBOOL("QuietSnapshotsToDisk")) if(!gSavedSettings.getBOOL("PlayModeUISndSnapshot")) // </FS:PP> FIRE-8190: Preview function for "UI Sounds" Panel { gViewerWindow->playSnapshotAnimAndSound(); } llinfos << "Writing TGA..." << llendl; LLPointer<LLImageTGA> tga = new LLImageTGA; tga->encode(raw); LLVFile::writeFile(tga->getData(), tga->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_IMAGE_TGA); raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); llinfos << "Writing J2C..." << llendl; LLPointer<LLImageJ2C> j2c = new LLImageJ2C; j2c->encode(raw, 0.0f); LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_TEXTURE); self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE); gGL.getTexUnit(0)->bind(self->mImage); self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP); } else { llwarns << "Unable to take snapshot" << llendl; } }
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLPointer<LLImageRaw> raw = new LLImageRaw; S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); if (gSavedSettings.getBOOL("HighResSnapshot")) { width *= 2; height *= 2; } if (gViewerWindow->rawSnapshot(raw, width, height, TRUE, FALSE, gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE)) { gViewerWindow->playSnapshotAnimAndSound(); LLImageBase::setSizeOverride(TRUE); LLPointer<LLImageFormatted> formatted; switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: formatted = new LLImagePNG; break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: formatted = new LLImageBMP; break; default: llwarns << "Unknown Local Snapshot format" << llendl; LLImageBase::setSizeOverride(FALSE); return true; } formatted->encode(raw, 0); LLImageBase::setSizeOverride(FALSE); gViewerWindow->saveImageNumbered(formatted); } return true; }
// static void LLFloaterAuction::onClickSnapshot(void* data) { LLFloaterAuction* self = (LLFloaterAuction*)(data); LLPointer<LLImageRaw> raw = new LLImageRaw; gForceRenderLandFence = self->childGetValue("fence_check").asBoolean(); BOOL success = gViewerWindow->rawSnapshot(raw, gViewerWindow->getWindowWidth(), gViewerWindow->getWindowHeight(), TRUE, FALSE, FALSE, FALSE); gForceRenderLandFence = FALSE; if (success) { self->mTransactionID.generate(); self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID()); if(!gSavedSettings.getBOOL("QuietSnapshotsToDisk")) { gViewerWindow->playSnapshotAnimAndSound(); } llinfos << "Writing TGA..." << llendl; LLPointer<LLImageTGA> tga = new LLImageTGA; tga->encode(raw); LLVFile::writeFile(tga->getData(), tga->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_IMAGE_TGA); raw->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT); llinfos << "Writing J2C..." << llendl; LLPointer<LLImageJ2C> j2c = new LLImageJ2C; j2c->encode(raw, 0.0f); LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_TEXTURE); self->mImage = new LLImageGL((LLImageRaw*)raw, FALSE); self->mImage->bind(); self->mImage->setClamp(TRUE, TRUE); } else { llwarns << "Unable to take snapshot" << llendl; } }
bool handleEvent(const LLSD& userdata) { LLPointer<LLImageRaw> raw = new LLImageRaw; S32 width = gViewerWindow->getWindowWidthRaw(); S32 height = gViewerWindow->getWindowHeightRaw(); if (gSavedSettings.getBOOL("HighResSnapshot")) { width *= 2; height *= 2; } if (gViewerWindow->rawSnapshot(raw, width, height, TRUE, FALSE, gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE)) { gViewerWindow->playSnapshotAnimAndSound(); LLPointer<LLImageFormatted> formatted; LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); switch (fmt) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; default: LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: formatted = new LLImagePNG; break; case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: formatted = new LLImageBMP; break; } formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize() ; gViewerWindow->saveImageNumbered(formatted); } return true; }
// Create the baked texture, send it out to the server, then wait for it to come // back so we can switch to using it. void LLViewerTexLayerSetBuffer::doUpload() { LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); LL_INFOS() << "Uploading baked " << layer_set->getBodyRegionName() << LL_ENDL; LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); // Don't need caches since we're baked now. (note: we won't *really* be baked // until this image is sent to the server and the Avatar Appearance message is received.) layer_set->deleteCaches(); // Get the COLOR information from our texture U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ]; glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); stop_glerror(); // Get the MASK information from our texture LLGLSUIDefault gls_ui; LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 ); U8* baked_mask_data = baked_mask_image->getData(); layer_set->gatherMorphMaskAlpha(baked_mask_data, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); // Create the baked image from our color and mask information const S32 baked_image_components = 5; // red green blue [bump] clothing LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components ); U8* baked_image_data = baked_image->getData(); S32 i = 0; for (S32 u=0; u < mFullWidth; u++) { for (S32 v=0; v < mFullHeight; v++) { baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. baked_image_data[5*i + 4] = baked_mask_data[i]; i++; } } LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; const char* comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // writes into baked_color_data. 5 channels (rgb, heightfield/alpha, mask) if (compressedImage->encode(baked_image, comment_text)) { LLTransactionID tid; tid.generate(); const LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); if (LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), gVFS, asset_id, LLAssetType::AT_TEXTURE)) { // Read back the file and validate. BOOL valid = FALSE; LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; S32 file_size = 0; U8* data = LLVFile::readFile(gVFS, LLImageBase::getPrivatePool(), asset_id, LLAssetType::AT_TEXTURE, &file_size); if (data) { valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' } else { integrity_test->setLastError("Unable to read entire file"); } if (valid) { const bool highest_lod = layer_set->isLocalTextureDataFinal(); // Baked_upload_data is owned by the responder and deleted after the request completes. LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp, layer_set, asset_id, highest_lod); // upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit. mUploadID = asset_id; // Upload the image const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); if(!url.empty() && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing. { LLSD body = LLSD::emptyMap(); // The responder will call LLViewerTexLayerSetBuffer::onTextureUploadComplete() LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); LL_INFOS() << "Baked texture upload via capability of " << mUploadID << " to " << url << LL_ENDL; } else { gAssetStorage->storeAssetData(tid, LLAssetType::AT_TEXTURE, LLViewerTexLayerSetBuffer::onTextureUploadComplete, baked_upload_data, TRUE, // temp_file TRUE, // is_priority TRUE); // store_local LL_INFOS() << "Baked texture upload via Asset Store." << LL_ENDL; } if (highest_lod) { // Sending the final LOD for the baked texture. All done, pause // the upload timer so we know how long it took. mNeedsUpload = FALSE; mNeedsUploadTimer.pause(); } else { // Sending a lower level LOD for the baked texture. Restart the upload timer. mNumLowresUploads++; mNeedsUploadTimer.unpause(); mNeedsUploadTimer.reset(); } // Print out notification that we uploaded this texture. if (gSavedSettings.getBOOL("DebugAvatarRezTime")) { const std::string lod_str = highest_lod ? "HighRes" : "LowRes"; LLSD args; args["EXISTENCE"] = llformat("%d",(U32)layer_set->getAvatar()->debugGetExistenceTimeElapsedF32()); args["TIME"] = llformat("%d",(U32)mNeedsUploadTimer.getElapsedTimeF32()); args["BODYREGION"] = layer_set->getBodyRegionName(); args["RESOLUTION"] = lod_str; LLNotificationsUtil::add("AvatarRezSelfBakedTextureUploadNotification",args); LL_DEBUGS("Avatar") << self_av_string() << "Uploading [ name: " << layer_set->getBodyRegionName() << " res:" << lod_str << " time:" << (U32)mNeedsUploadTimer.getElapsedTimeF32() << " ]" << LL_ENDL; } } else { // The read back and validate operation failed. Remove the uploaded file. mUploadPending = FALSE; LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); file.remove(); LL_INFOS() << "Unable to create baked upload file (reason: corrupted)." << LL_ENDL; } } } else { // The VFS write file operation failed. mUploadPending = FALSE; LL_INFOS() << "Unable to create baked upload file (reason: failed to write file)" << LL_ENDL; } delete [] baked_color_data; }