def browse(self): formats = "Image File (*.jpg *.png *.exr)" imgPath = QFileDialog.getOpenFileName(self, "Select preview-image", self.imgPath, formats)[0] if imgPath != "": if os.path.splitext(imgPath)[1] == ".exr": qimg = QImage(self.core.pb.shotPrvXres, self.core.pb.shotPrvYres, QImage.Format_RGB16) if self.oiioLoaded: imgSrc = oiio.ImageBuf(str(imgPath)) rgbImgSrc = oiio.ImageBuf() oiio.ImageBufAlgo.channels(rgbImgSrc, imgSrc, (0, 1, 2)) imgWidth = rgbImgSrc.spec().full_width imgHeight = rgbImgSrc.spec().full_height xOffset = 0 yOffset = 0 if (imgWidth / float(imgHeight)) > 1.7778: newImgWidth = self.core.pb.shotPrvXres newImgHeight = self.core.pb.shotPrvXres / float( imgWidth) * imgHeight else: newImgHeight = self.core.pb.shotPrvYres newImgWidth = self.core.pb.shotPrvYres / float( imgHeight) * imgWidth imgDst = oiio.ImageBuf( oiio.ImageSpec(int(newImgWidth), int(newImgHeight), 3, oiio.UINT8)) oiio.ImageBufAlgo.resample(imgDst, rgbImgSrc) sRGBimg = oiio.ImageBuf() oiio.ImageBufAlgo.pow(sRGBimg, imgDst, (1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)) bckImg = oiio.ImageBuf( oiio.ImageSpec(int(newImgWidth), int(newImgHeight), 3, oiio.UINT8)) oiio.ImageBufAlgo.fill(bckImg, (0.5, 0.5, 0.5)) oiio.ImageBufAlgo.paste(bckImg, xOffset, yOffset, 0, 0, sRGBimg) qimg = QImage(int(newImgWidth), int(newImgHeight), QImage.Format_RGB16) for i in range(int(newImgWidth)): for k in range(int(newImgHeight)): rgb = qRgb( bckImg.getpixel(i, k)[0] * 255, bckImg.getpixel(i, k)[1] * 255, bckImg.getpixel(i, k)[2] * 255) qimg.setPixel(i, k, rgb) pmsmall = QPixmap.fromImage(qimg) elif self.wandLoaded: with wand.image.Image(filename=imgPath) as img: imgWidth, imgHeight = [img.width, img.height] img.depth = 8 imgArr = numpy.fromstring( img.make_blob('RGB'), dtype='uint{}'.format(img.depth)).reshape( imgHeight, imgWidth, 3) qimg = QImage(imgArr, imgWidth, imgHeight, QImage.Format_RGB888) pm = QPixmap.fromImage(qimg) if (pm.width() / float(pm.height())) > 1.7778: pmsmall = pm.scaledToWidth(self.core.pb.shotPrvXres) else: pmsmall = pm.scaledToHeight(self.core.pb.shotPrvYres) else: QMessageBox.critical( self.core.messageParent, "Error", "No image loader available. Unable to read the file.") return else: pm = self.core.pb.getImgPMap(imgPath) if pm.width() == 0: warnStr = "Cannot read image: %s" % imgPath msg = QMessageBox(QMessageBox.Warning, "Warning", warnStr, QMessageBox.Ok, parent=self.core.messageParent) msg.setFocus() msg.exec_() return if (pm.width() / float(pm.height())) > 1.7778: pmsmall = pm.scaledToWidth(self.core.pb.shotPrvXres) else: pmsmall = pm.scaledToHeight(self.core.pb.shotPrvYres) self.pmap = pmsmall self.l_shotPreview.setMinimumSize(self.pmap.width(), self.pmap.height()) self.l_shotPreview.setPixmap(self.pmap)
def publish(self): if self.cb_shot.currentText() == "": QMessageBox.warning(self.core.messageParent, "Shotgun Publish", "No %s exists in the Shotgun project. Publish canceled" % self.ptype ) return if self.cb_task.currentText() == "": QMessageBox.warning(self.core.messageParent, "Shotgun Publish", "No task is selected. Publish canceled.") return curShotId = [x['id'] for x in self.sgShots if x['code'] == self.cb_shot.currentText()][0] curTaskId = [x['id'] for x in self.sgTasks if x['content'] == self.cb_task.currentText()] if len(curTaskId) > 0: curTaskId = curTaskId[0] else: fields = ["code", "short_name", "entity_type"] # sgSteps = { x['short_name'] : x for x in self.sg.find("Step", [], fields) if x['entity_type'] is not None} data = { 'project': {'type': 'Project','id': self.sgPrjId}, 'content': self.cb_task.currentText(), 'sg_status_list': 'ip', 'entity' : {'type': self.ptype, 'id': curShotId} # 'step' : {'type': 'Step', 'id': sgSteps["ren"]['id'] } } try: result = self.sg.create('Task', data) except Exception as e: if "Entity of type Task cannot be created by this user." in str(e): QMessageBox.warning(self.core.messageParent, "Warning", "This shotgun account cannot create tasks.\n\nPublish canceled.") return else: raise e curTaskId = result["id"] pubVersions = [] for source in self.fileSources: versionName = "%s_%s_%s" % (self.cb_shot.currentText(), self.cb_task.currentText(), self.taskVersion) if len(self.fileSources) > 1: versionName += "_%s" % os.path.splitext(os.path.basename(source[0]))[0] baseName, extension = os.path.splitext(source[0]) videoInput = extension in [".mp4", ".mov"] if videoInput: sequenceName = source[0] else: try: int(baseName[-4:]) sequenceName = baseName[:-4] + "####" + extension except: sequenceName = source[0] tmpFiles = [] ffmpegIsInstalled = False if platform.system() == "Windows": ffmpegPath = os.path.join(self.core.prismRoot, "Tools", "FFmpeg" ,"bin", "ffmpeg.exe") if os.path.exists(ffmpegPath): ffmpegIsInstalled = True elif platform.system() == "Linux": ffmpegPath = "ffmpeg" try: subprocess.Popen([ffmpegPath]) ffmpegIsInstalled = True except: pass elif platform.system() == "Darwin": ffmpegPath = os.path.join(self.core.prismRoot, "Tools", "ffmpeg") if os.path.exists(ffmpegPath): ffmpegIsInstalled = True imgPath = source[0] if extension in [".exr", ".mp4", ".mov"]: inputpath = source[0].replace("\\", "/") outputpath = os.path.splitext(inputpath)[0] + ".jpg" if ffmpegIsInstalled: if videoInput: nProc = subprocess.Popen([ffmpegPath, "-apply_trc", "iec61966_2_1", "-i", inputpath, "-pix_fmt", "yuv420p", "-vf", "select=gte(n\,%s)" % source[1], "-frames", "1", outputpath, "-y"]) else: nProc = subprocess.Popen([ffmpegPath, "-apply_trc", "iec61966_2_1", "-i", inputpath, "-pix_fmt", "yuv420p", outputpath, "-y"]) result = nProc.communicate() imgPath = outputpath tmpFiles.append(imgPath) data = { 'project': {'type': 'Project','id': self.sgPrjId}, 'code': versionName, 'description': self.te_description.toPlainText(), 'sg_path_to_frames': sequenceName, 'sg_status_list': 'rev', 'entity': {'type': self.ptype, 'id': curShotId}, 'sg_task': {'type': 'Task', 'id': curTaskId} } if self.sgUserId is not None: data['user'] = {'type': 'HumanUser', 'id': self.sgUserId} if os.path.exists(imgPath): data['image'] = imgPath try: createdVersion = self.sg.create('Version', data) except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() erStr = ("ERROR:\n%s" % traceback.format_exc()) QMessageBox.warning(self.core.messageParent, "Shotgun Publish", erStr) return if self.chb_proxyVid.isChecked() and ffmpegIsInstalled: proxyPath = "" inputpath = source[0].replace("\\", "/") mp4File = os.path.join(os.path.dirname(inputpath) + "(mp4)", os.path.basename(inputpath))[:-9] + ".mp4" if os.path.exists(mp4File): proxyPath = mp4File else: isSequence = False if not videoInput: try: x = int(inputpath[-8:-4]) isSequence = True except: pass if os.path.splitext(inputpath)[1] in [".jpg", ".jpeg", ".JPG", ".png", ".tif", ".tiff"]: size = QImage(inputpath).size() pwidth = size.width() pheight = size.height() elif os.path.splitext(inputpath)[1] in [".exr"]: oiioLoaded = False try: from oiio1618 import OpenImageIO as oiio oiioLoaded = True except: pass if oiioLoaded: imgSpecs = oiio.ImageBuf(str(inputpath)).spec() pwidth = imgSpecs.full_width pheight = imgSpecs.full_height else: try: import numpy import wand, wand.image except: pass with wand.image.Image(filename=inputpath) as img: pwidth = img.width pheight = img.height elif os.path.splitext(inputpath)[1] in [".mp4", ".mov"]: try: import imageio except: pass vidReader = imageio.get_reader(inputpath, 'ffmpeg') pwidth = vidReader._meta["size"][0] pheight = vidReader._meta["size"][1] if int(pwidth)%2 == 1 or int(pheight)%2 == 1: QMessageBox.warning(self.core.messageParent,"Media conversion", "Media with odd resolution can't be converted to mp4. No proxy video could be generated.") else: if isSequence or videoInput: if isSequence: inputpath = inputpath[:-8] + "%04d" + inputpath[-4:] outputpath = inputpath[:-9] + ".mp4" nProc = subprocess.Popen([ffmpegPath, "-start_number", str(self.startFrame), "-framerate", "24", "-apply_trc", "iec61966_2_1", "-i", inputpath, "-pix_fmt", "yuv420p", "-start_number", str(self.startFrame), outputpath, "-y"]) else: outputpath = inputpath[:-9] + "(proxy).mp4" nProc = subprocess.Popen([ffmpegPath, "-apply_trc", "iec61966_2_1", "-i", inputpath, "-pix_fmt", "yuv420p", "-start_number", str(self.startFrame), outputpath, "-y"]) mp4Result = nProc.communicate() proxyPath = outputpath tmpFiles.append(proxyPath) if proxyPath != "" and os.path.exists(proxyPath) and os.stat(proxyPath).st_size != 0: try: self.sg.upload("Version", createdVersion['id'], proxyPath, 'sg_uploaded_movie') except Exception as e: QMessageBox.warning(self.core.messageParent, "Warning", "Uploading proxy video failed:\n\n%s" % str(e)) if self.gb_playlist.isChecked(): fields = ['id', 'versions'] filters = [ ['project','is', {'type': 'Project','id': self.sgPrjId}], ['code', 'is', self.cb_playlist.currentText()] ] sgPlaylists = self.sg.find("Playlist", filters, fields) if len(sgPlaylists) > 0: vers = sgPlaylists[0]['versions'] vers.append(createdVersion) data = { 'versions': vers} self.sg.update('Playlist', sgPlaylists[0]['id'], data) else: data = { 'project': {'type': 'Project','id': self.sgPrjId}, 'code': self.cb_playlist.currentText(), 'description': 'dailies_01', 'sg_status': 'opn', 'versions': [createdVersion] } try: createdPlaylist = self.sg.create('Playlist', data) except: data.pop("sg_status") createdPlaylist = self.sg.create('Playlist', data) for i in tmpFiles: try: os.remove(i) except: pass pubVersions.append(versionName) sgSite = self.core.getConfig('shotgun', "site", configPath=self.core.prismIni) sgSite += "/detail/Version/" + str(createdVersion["id"]) versionInfoPath = os.path.join(os.path.dirname(source[0]), "versionInfo.ini") if not os.path.exists(versionInfoPath): versionInfoPath = os.path.join(os.path.dirname(os.path.dirname(source[0])), "versionInfo.ini") if os.path.exists(versionInfoPath): vConfig = ConfigParser() vConfig.read(versionInfoPath) vConfig.set("information", "shotgun-url", sgSite) with open(versionInfoPath, 'w') as versionFile: vConfig.write(versionFile) else: vConfig = ConfigParser() vConfig.add_section("information") vConfig.set("information", "shotgun-url", sgSite) with open(versionInfoPath, 'w') as versionFile: vConfig.write(versionFile) msgStr = "Successfully published:" for i in pubVersions: msgStr += "\n%s" % i msg = QMessageBox(QMessageBox.Information, "Shotgun Publish", msgStr, parent=self.core.messageParent) msg.addButton("Open version in Shotgun", QMessageBox.YesRole) msg.addButton("Close", QMessageBox.YesRole) msg.setFocus() action = msg.exec_() if action == 0: import webbrowser webbrowser.open(sgSite) self.accept()