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);
// We can't handle raw images yet, so make sure we are getting jpgs
if (getCurrentImageQuality().contains("RAW"))
setImageQuality("Large Fine Jpeg");
//if (getCurrentImageQuality().contains("RAW"))
// setImageQuality("Large Fine Jpeg");
EdsUInt32 saveto = kEdsSaveTo_Host;
m_error = EdsSetPropertyData(m_camera, kEdsPropID_SaveTo, 0,
@ -373,9 +373,7 @@ EdsError Canon::getAvailableImageQualities() {
while (i < count) {
QString quality = QString::fromStdString(
m_imageQualityMap[imageQualityDesc->propDesc[i]]);
if (!quality.contains("RAW")) {
m_imageQualityOptions.push_back(quality);
}
m_imageQualityOptions.push_back(quality);
i++;
}
}
@ -512,7 +510,9 @@ QString Canon::getCurrentImageQuality() {
err = EdsGetPropertyData(m_camera, kEdsPropID_ImageQuality, 0, sizeof(size),
&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;
EdsStreamRef stream = NULL;
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);
std::string itemName = dirItemInfo.szFileName;
if (itemName.at(itemName.length() - 1) == '2') {
isRaw = true;
}
err = EdsCreateMemoryStream(0, &stream);
err = EdsDownload(object, dirItemInfo.size, stream);
err = EdsCreateMemoryStream(0, &jpgStream);
if (isRaw) {
err = EdsDownload(object, dirItemInfo.size, stream);
}
else {
err = EdsDownload(object, dirItemInfo.size, jpgStream);
}
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
UInt64 mySize = 0;
UInt64 jpgStreamSize = 0;
UInt64 rawStreamSize = 0;
#else
unsigned __int64 mySize = 0;
unsigned __int64 jpgStreamSize = 0;
unsigned __int64 rawStreamSize = 0;
#endif
unsigned char* data = NULL;
err = EdsGetPointer(stream, (EdsVoid**)&data);
err = EdsGetLength(stream, &mySize);
unsigned char* jpgStreamData = NULL;
unsigned char* rawStreamData = NULL;
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.
// For now, we are only dealing with jpg files, so lets get some jpg info.
int width, height, pixelFormat;
int inSubsamp, inColorspace;
tjhandle tjInstance = NULL;
unsigned char* imgBuf = NULL;
tjInstance = tjInitDecompress();
tjDecompressHeader3(tjInstance, data, mySize, &width, &height, &inSubsamp,
&inColorspace);
pixelFormat = TJPF_BGRX;
int pixelSize = tjPixelSize[pixelFormat];
UINT bufferSize = width * height * pixelSize;
imgBuf = (unsigned char*)tjAlloc(bufferSize);
int flags = 0;
flags |= TJFLAG_BOTTOMUP;
if (!isRaw) {
int pixelFormat, pixelSize;
int inSubsamp, inColorspace;
tjhandle tjInstance = NULL;
// don't scale using jpg turbo, you can't control the size exactly
// get all the image info uncompressed and put into imgBuf
tjDecompress2(tjInstance, data, mySize, imgBuf, width, width * pixelSize,
height, pixelFormat, flags);
tjInstance = tjInitDecompress();
tjDecompressHeader3(tjInstance, jpgStreamData, jpgStreamSize, &width, &height, &inSubsamp,
&inColorspace);
pixelFormat = TJPF_BGRX;
pixelSize = tjPixelSize[pixelFormat];
bufferSize = width * height * pixelSize;
imgBuf = (unsigned char*)tjAlloc(bufferSize);
int flags = 0;
flags |= TJFLAG_BOTTOMUP;
// don't scale using jpg turbo, you can't control the size exactly
// get all the image info uncompressed and put into imgBuf
tjDecompress2(tjInstance, jpgStreamData, jpgStreamSize, imgBuf, width, width * pixelSize,
height, pixelFormat, flags);
tjDestroy(tjInstance);
tjInstance = NULL;
}
// Get camera size info
TCamera* camera =
@ -844,16 +920,21 @@ bool Canon::downloadImage(EdsBaseRef object) {
// end tj code
// OpenCV image material - note width and height are flipped
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);
}
uchar* origBuf = imgOriginal.data;
memcpy(origBuf, imgBuf, bufferSize);
// got the image, free the jpeg turbo stuff
tjFree(imgBuf);
imgBuf = NULL;
tjDestroy(tjInstance);
tjInstance = NULL;
else {
uchar* origBuf = imgOriginal.data;
memcpy(origBuf, imgBuf, bufferSize);
tjFree(imgBuf);
imgBuf = NULL;
}
// calculate the size of the new image
// and resize it down
@ -877,15 +958,30 @@ bool Canon::downloadImage(EdsBaseRef object) {
// write out the full res file
QFile fullImage(StopMotion::instance()->m_tempFile);
fullImage.open(QIODevice::WriteOnly);
QDataStream dataStream(&fullImage);
dataStream.writeRawData((const char*)data, mySize);
fullImage.close();
if (!isRaw) {
QFile fullImage(StopMotion::instance()->m_tempFile);
fullImage.open(QIODevice::WriteOnly);
QDataStream dataStream(&fullImage);
dataStream.writeRawData((const char*)jpgStreamData, jpgStreamSize);
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
if (isRaw) {
EdsRelease(imgRef);
}
EdsRelease(stream);
EdsRelease(jpgStream);
stream = NULL;
jpgStream = NULL;
if (object) EdsRelease(object);
if (err == EDS_ERR_OK) {

View file

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

View file

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

View file

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