Add Raw Image Support to Stop Motion (#120)

* start of raw support

* Save RAW Image and add RAW images to export sequence
This commit is contained in:
Jeremy Bullock 2020-08-17 14:19:20 -06:00 committed by GitHub
parent dd1976c5d8
commit abdb0dabb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 169 additions and 50 deletions

View file

@ -183,8 +183,8 @@ EdsError Canon::openCameraSession() {
m_camera, kEdsStateEvent_All, Canon::handleStateEvent, (EdsVoid*)this); m_camera, kEdsStateEvent_All, Canon::handleStateEvent, (EdsVoid*)this);
// We can't handle raw images yet, so make sure we are getting jpgs // We can't handle raw images yet, so make sure we are getting jpgs
if (getCurrentImageQuality().contains("RAW")) //if (getCurrentImageQuality().contains("RAW"))
setImageQuality("Large Fine Jpeg"); // setImageQuality("Large Fine Jpeg");
EdsUInt32 saveto = kEdsSaveTo_Host; EdsUInt32 saveto = kEdsSaveTo_Host;
m_error = EdsSetPropertyData(m_camera, kEdsPropID_SaveTo, 0, m_error = EdsSetPropertyData(m_camera, kEdsPropID_SaveTo, 0,
@ -373,9 +373,7 @@ EdsError Canon::getAvailableImageQualities() {
while (i < count) { while (i < count) {
QString quality = QString::fromStdString( QString quality = QString::fromStdString(
m_imageQualityMap[imageQualityDesc->propDesc[i]]); m_imageQualityMap[imageQualityDesc->propDesc[i]]);
if (!quality.contains("RAW")) {
m_imageQualityOptions.push_back(quality); m_imageQualityOptions.push_back(quality);
}
i++; i++;
} }
} }
@ -512,7 +510,9 @@ QString Canon::getCurrentImageQuality() {
err = EdsGetPropertyData(m_camera, kEdsPropID_ImageQuality, 0, sizeof(size), err = EdsGetPropertyData(m_camera, kEdsPropID_ImageQuality, 0, sizeof(size),
&data); &data);
std::string wbString = m_imageQualityMap[data]; std::string wbString = m_imageQualityMap[data];
return QString::fromStdString(m_imageQualityMap[data]); QString iq = QString::fromStdString(m_imageQualityMap[data]);
m_imageQuality = iq;
return iq;
} }
//----------------------------------------------------------------- //-----------------------------------------------------------------
@ -795,43 +795,119 @@ bool Canon::downloadImage(EdsBaseRef object) {
EdsError err = EDS_ERR_OK; EdsError err = EDS_ERR_OK;
EdsStreamRef stream = NULL; EdsStreamRef stream = NULL;
EdsDirectoryItemInfo dirItemInfo; EdsDirectoryItemInfo dirItemInfo;
EdsImageRef imgRef;
EdsStreamRef jpgStream = NULL;
EdsSize jpgSize;
EdsImageInfo imgInfo;
bool isRaw = false;
unsigned char* imgBuf = NULL;
int width, height;
UINT bufferSize;
err = EdsGetDirectoryItemInfo(object, &dirItemInfo); err = EdsGetDirectoryItemInfo(object, &dirItemInfo);
std::string itemName = dirItemInfo.szFileName;
if (itemName.at(itemName.length() - 1) == '2') {
isRaw = true;
}
err = EdsCreateMemoryStream(0, &stream); err = EdsCreateMemoryStream(0, &stream);
err = EdsCreateMemoryStream(0, &jpgStream);
if (isRaw) {
err = EdsDownload(object, dirItemInfo.size, stream); err = EdsDownload(object, dirItemInfo.size, stream);
}
else {
err = EdsDownload(object, dirItemInfo.size, jpgStream);
}
EdsDownloadComplete(object); EdsDownloadComplete(object);
std::string iq = m_imageQuality.toStdString();
if (isRaw) {
// If the settings are set to jpg and raw, only get the raw and then return
if ((m_imageQuality.toLower().contains("jpeg") || m_imageQuality.toLower().contains("jpg")) && m_imageQuality.toLower().contains("raw")) {
#ifdef MACOSX
UInt64 rawStreamSize = 0;
#else
unsigned __int64 rawStreamSize = 0;
#endif
unsigned char* rawStreamData = NULL;
err = EdsGetPointer(stream, (EdsVoid**)&rawStreamData);
err = EdsGetLength(stream, &rawStreamSize);
QFile fullImage(StopMotion::instance()->m_tempRaw);
fullImage.open(QIODevice::WriteOnly);
QDataStream dataStream(&fullImage);
dataStream.writeRawData((const char*)rawStreamData, rawStreamSize);
fullImage.close();
EdsRelease(stream);
EdsRelease(jpgStream);
stream = NULL;
jpgStream = NULL;
if (object) EdsRelease(object);
return err;
StopMotion::instance()->m_tempRaw = TApp::instance()->getCurrentScene()->getScene()->decodeFilePath(TFilePath("+extras")).getQString();
}
err = EdsCreateImageRef(stream, &imgRef);
EdsGetImageInfo(imgRef, kEdsImageSrc_Preview, &imgInfo);
jpgSize.height = imgInfo.height;
jpgSize.width = imgInfo.width;
EdsGetImage(imgRef, kEdsImageSrc_Preview, kEdsTargetImageType_RGB, imgInfo.effectiveRect, jpgSize, jpgStream);
height = jpgSize.height;
width = jpgSize.width;
bufferSize = width * height * 4;
}
#ifdef MACOSX #ifdef MACOSX
UInt64 mySize = 0; UInt64 jpgStreamSize = 0;
UInt64 rawStreamSize = 0;
#else #else
unsigned __int64 mySize = 0; unsigned __int64 jpgStreamSize = 0;
unsigned __int64 rawStreamSize = 0;
#endif #endif
unsigned char* data = NULL; unsigned char* jpgStreamData = NULL;
err = EdsGetPointer(stream, (EdsVoid**)&data); unsigned char* rawStreamData = NULL;
err = EdsGetLength(stream, &mySize); err = EdsGetPointer(jpgStream, (EdsVoid**)&jpgStreamData);
err = EdsGetLength(jpgStream, &jpgStreamSize);
if (isRaw) {
err = EdsGetPointer(stream, (EdsVoid**)&rawStreamData);
err = EdsGetLength(stream, &rawStreamSize);
}
// we now have the image in a buffer and the size of the image. // we now have the image in a buffer and the size of the image.
// For now, we are only dealing with jpg files, so lets get some jpg info.
int width, height, pixelFormat; if (!isRaw) {
int pixelFormat, pixelSize;
int inSubsamp, inColorspace; int inSubsamp, inColorspace;
tjhandle tjInstance = NULL; tjhandle tjInstance = NULL;
unsigned char* imgBuf = NULL;
tjInstance = tjInitDecompress(); tjInstance = tjInitDecompress();
tjDecompressHeader3(tjInstance, data, mySize, &width, &height, &inSubsamp, tjDecompressHeader3(tjInstance, jpgStreamData, jpgStreamSize, &width, &height, &inSubsamp,
&inColorspace); &inColorspace);
pixelFormat = TJPF_BGRX; pixelFormat = TJPF_BGRX;
int pixelSize = tjPixelSize[pixelFormat]; pixelSize = tjPixelSize[pixelFormat];
UINT bufferSize = width * height * pixelSize; bufferSize = width * height * pixelSize;
imgBuf = (unsigned char*)tjAlloc(bufferSize); imgBuf = (unsigned char*)tjAlloc(bufferSize);
int flags = 0; int flags = 0;
flags |= TJFLAG_BOTTOMUP; flags |= TJFLAG_BOTTOMUP;
// don't scale using jpg turbo, you can't control the size exactly // don't scale using jpg turbo, you can't control the size exactly
// get all the image info uncompressed and put into imgBuf // get all the image info uncompressed and put into imgBuf
tjDecompress2(tjInstance, data, mySize, imgBuf, width, width * pixelSize, tjDecompress2(tjInstance, jpgStreamData, jpgStreamSize, imgBuf, width, width * pixelSize,
height, pixelFormat, flags); height, pixelFormat, flags);
tjDestroy(tjInstance);
tjInstance = NULL;
}
// Get camera size info // Get camera size info
TCamera* camera = TCamera* camera =
@ -844,16 +920,21 @@ bool Canon::downloadImage(EdsBaseRef object) {
// end tj code // end tj code
// OpenCV image material - note width and height are flipped // OpenCV image material - note width and height are flipped
cv::Mat imgOriginal(height, width, CV_8UC4); cv::Mat imgOriginal(height, width, CV_8UC4);
if (isRaw) {
cv::Mat rawOriginal(height, width, CV_8UC3);
uchar* rawBuf = rawOriginal.data;
memcpy(rawBuf, jpgStreamData, jpgStreamSize);
cv::cvtColor(rawOriginal, imgOriginal, cv::COLOR_RGB2BGRA);
cv::flip(imgOriginal, imgOriginal, 0);
}
else {
uchar* origBuf = imgOriginal.data; uchar* origBuf = imgOriginal.data;
memcpy(origBuf, imgBuf, bufferSize); memcpy(origBuf, imgBuf, bufferSize);
// got the image, free the jpeg turbo stuff
tjFree(imgBuf); tjFree(imgBuf);
imgBuf = NULL; imgBuf = NULL;
tjDestroy(tjInstance); }
tjInstance = NULL;
// calculate the size of the new image // calculate the size of the new image
// and resize it down // and resize it down
@ -877,15 +958,30 @@ bool Canon::downloadImage(EdsBaseRef object) {
// write out the full res file // write out the full res file
if (!isRaw) {
QFile fullImage(StopMotion::instance()->m_tempFile); QFile fullImage(StopMotion::instance()->m_tempFile);
fullImage.open(QIODevice::WriteOnly); fullImage.open(QIODevice::WriteOnly);
QDataStream dataStream(&fullImage); QDataStream dataStream(&fullImage);
dataStream.writeRawData((const char*)data, mySize); dataStream.writeRawData((const char*)jpgStreamData, jpgStreamSize);
fullImage.close(); fullImage.close();
}
else {
QFile fullImage(StopMotion::instance()->m_tempRaw);
fullImage.open(QIODevice::WriteOnly);
QDataStream dataStream(&fullImage);
dataStream.writeRawData((const char*)rawStreamData, rawStreamSize);
fullImage.close();
JpgConverter::saveJpg(StopMotion::instance()->m_newImage, TFilePath(StopMotion::instance()->m_tempFile));
}
// free the canon stuff // free the canon stuff
if (isRaw) {
EdsRelease(imgRef);
}
EdsRelease(stream); EdsRelease(stream);
EdsRelease(jpgStream);
stream = NULL; stream = NULL;
jpgStream = NULL;
if (object) EdsRelease(object); if (object) EdsRelease(object);
if (err == EDS_ERR_OK) { if (err == EDS_ERR_OK) {

View file

@ -102,6 +102,7 @@ public:
int m_liveViewExposureOffset = 0; int m_liveViewExposureOffset = 0;
QString m_realShutterSpeed; QString m_realShutterSpeed;
QString m_displayedShutterSpeed; QString m_displayedShutterSpeed;
QString m_imageQuality;
// Canon Commands // Canon Commands
#ifdef WITH_CANON #ifdef WITH_CANON

View file

@ -1433,11 +1433,15 @@ bool StopMotion::importImage() {
scene->decodeFilePath(fullResFolder + TFilePath(levelName + L"..jpg")); scene->decodeFilePath(fullResFolder + TFilePath(levelName + L"..jpg"));
TFilePath fullResFile(fullResFp.withFrame(frameNumber)); TFilePath fullResFile(fullResFp.withFrame(frameNumber));
TFilePath fullResRawFile(fullResFile.getQString().replace(fullResFile.getQString().lastIndexOf("jpg"), 3, "cr2"));
m_tempRaw = fullResRawFile.getQString();
TFilePath liveViewFp = TFilePath liveViewFp =
scene->decodeFilePath(liveViewFolder + TFilePath(levelName + L"..jpg")); scene->decodeFilePath(liveViewFolder + TFilePath(levelName + L"..jpg"));
TFilePath liveViewFile(liveViewFp.withFrame(frameNumber)); TFilePath liveViewFile(liveViewFp.withFrame(frameNumber));
TFilePath tempFile = parentDir + "temp.jpg"; TFilePath tempFile = parentDir + "temp.jpg";
TFilePath tempRaw = parentDir + "temp.cr2";
TXshSimpleLevel *sl = 0; TXshSimpleLevel *sl = 0;
TXshLevel *level = scene->getLevelSet()->getLevel(levelName); TXshLevel *level = scene->getLevelSet()->getLevel(levelName);
@ -1569,6 +1573,12 @@ bool StopMotion::importImage() {
TSystem::copyFile(fullResFile, tempFile); TSystem::copyFile(fullResFile, tempFile);
TSystem::deleteFile(tempFile); TSystem::deleteFile(tempFile);
if (TSystem::doesExistFileOrLevel(TFilePath(tempRaw))) {
TSystem::copyFile(fullResRawFile, tempRaw);
TSystem::deleteFile(tempRaw);
}
if (m_hasLineUpImage) { if (m_hasLineUpImage) {
JpgConverter::saveJpg(m_lineUpImage, liveViewFile); JpgConverter::saveJpg(m_lineUpImage, liveViewFile);
// check the live view image map to see if there is already // check the live view image map to see if there is already
@ -1806,11 +1816,13 @@ void StopMotion::captureDslrImage() {
TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath));
TFilePath tempFile = parentDir + "temp.jpg"; TFilePath tempFile = parentDir + "temp.jpg";
TFilePath tempRaw = parentDir + "temp.cr2";
if (!TFileStatus(parentDir).doesExist()) { if (!TFileStatus(parentDir).doesExist()) {
TSystem::mkDir(parentDir); TSystem::mkDir(parentDir);
} }
m_tempFile = tempFile.getQString(); m_tempFile = tempFile.getQString();
m_tempRaw = tempRaw.getQString();
#ifdef WITH_CANON #ifdef WITH_CANON
m_canon->takePicture(); m_canon->takePicture();
@ -1880,11 +1892,13 @@ void StopMotion::takeTestShot() {
ToonzScene *scene = app->getCurrentScene()->getScene(); ToonzScene *scene = app->getCurrentScene()->getScene();
TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath));
TFilePath tempFile = parentDir + "temp.jpg"; TFilePath tempFile = parentDir + "temp.jpg";
TFilePath tempRaw = parentDir + "temp.cr2";
if (!TFileStatus(parentDir).doesExist()) { if (!TFileStatus(parentDir).doesExist()) {
TSystem::mkDir(parentDir); TSystem::mkDir(parentDir);
} }
m_tempFile = tempFile.getQString(); m_tempFile = tempFile.getQString();
m_tempRaw = tempRaw.getQString();
m_light->showOverlays(); m_light->showOverlays();
m_canon->takePicture(); m_canon->takePicture();
} }
@ -1978,11 +1992,19 @@ void StopMotion::saveTestShot() {
TFilePath(levelName + L"+" + QString::number(fileNumber).toStdWString() + TFilePath(levelName + L"+" + QString::number(fileNumber).toStdWString() +
L".jpg")); L".jpg"));
TFilePath fullResRawFile(testsThumbsFile.getQString().replace(testsThumbsFile.getQString().lastIndexOf("jpg"), 3, "cr2"));
m_tempRaw = fullResRawFile.getQString();
TFilePath tempFile = parentDir + "temp.jpg"; TFilePath tempFile = parentDir + "temp.jpg";
TFilePath tempRaw = parentDir + "temp.cr2";
if (!m_usingWebcam) { if (!m_usingWebcam) {
TSystem::copyFile(testsFile, tempFile); TSystem::copyFile(testsFile, tempFile);
TSystem::deleteFile(tempFile); TSystem::deleteFile(tempFile);
if (TSystem::doesExistFileOrLevel(TFilePath(tempRaw))) {
TSystem::copyFile(fullResRawFile, tempRaw);
TSystem::deleteFile(tempRaw);
}
} else { } else {
JpgConverter::saveJpg(m_newImage, testsFile); JpgConverter::saveJpg(m_newImage, testsFile);
} }
@ -2387,12 +2409,6 @@ bool StopMotion::exportImageSequence() {
scene->decodeFilePath(fullResFolder + TFilePath(levelName + L"..jpg")); scene->decodeFilePath(fullResFolder + TFilePath(levelName + L"..jpg"));
TFilePath fullResFile(fullResFp.withFrame(frameNumber)); TFilePath fullResFile(fullResFp.withFrame(frameNumber));
TFilePath liveViewFp =
scene->decodeFilePath(liveViewFolder + TFilePath(levelName + L"..jpg"));
TFilePath liveViewFile(liveViewFp.withFrame(frameNumber));
TFilePath tempFile = parentDir + "temp.jpg";
TXshSimpleLevel *sl = 0; TXshSimpleLevel *sl = 0;
TXshLevel *level = scene->getLevelSet()->getLevel(levelName); TXshLevel *level = scene->getLevelSet()->getLevel(levelName);
@ -2465,11 +2481,14 @@ bool StopMotion::exportImageSequence() {
sourceFile = actualLevelFp.withFrame(cellNumber); sourceFile = actualLevelFp.withFrame(cellNumber);
} }
TFilePath sourceRawFile(sourceFile.getQString().replace(sourceFile.getQString().lastIndexOf("jpg"), 3, "cr2"));
if (!TFileStatus(sourceFile).doesExist()) { if (!TFileStatus(sourceFile).doesExist()) {
DVGui::error(tr("Could not find the source file.")); DVGui::error(tr("Could not find the source file."));
return false; return false;
} }
exportFile = exportFilePath.withFrame(exportFrameNumber); exportFile = exportFilePath.withFrame(exportFrameNumber);
TFilePath exportRawFile(exportFile.getQString().replace(exportFile.getQString().lastIndexOf("jpg"), 3, "cr2"));
if (TFileStatus(exportFile).doesExist()) { if (TFileStatus(exportFile).doesExist()) {
QString question = tr("Overwrite existing files?"); QString question = tr("Overwrite existing files?");
int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"),
@ -2477,6 +2496,9 @@ bool StopMotion::exportImageSequence() {
if (ret == 0 || ret == 2) return false; if (ret == 0 || ret == 2) return false;
} }
TSystem::copyFile(exportFile, sourceFile); TSystem::copyFile(exportFile, sourceFile);
if (TSystem::doesExistFileOrLevel(sourceRawFile)) {
TSystem::copyFile(exportRawFile, sourceRawFile);
}
exportFrameNumber++; exportFrameNumber++;
if (!TFileStatus(exportFile).doesExist()) { if (!TFileStatus(exportFile).doesExist()) {
DVGui::error(tr("An error occurred. Aborting.")); DVGui::error(tr("An error occurred. Aborting."));

View file

@ -90,7 +90,7 @@ public:
bool m_isTimeLapse = false; bool m_isTimeLapse = false;
int m_reviewTime = 2; int m_reviewTime = 2;
bool m_isTestShot = false; bool m_isTestShot = false;
QString m_tempFile; QString m_tempFile, m_tempRaw;
TXshSimpleLevel* m_sl; TXshSimpleLevel* m_sl;
// timers // timers