예제 #1
0
    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)
예제 #2
0
	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()