コード例 #1
0
                def read_and_convert_using_qt_to_toif(handler, filename,
                                                      hs_cols, hs_rows):
                    img = QImage(filename)
                    if img.isNull():
                        handler.show_error(
                            _('Could not load the image {} -- unknown format or other error'
                              ).format(os.path.basename(filename)))
                        return
                    if (img.width(), img.height()) != (
                            hs_cols, hs_rows):  # do we need to scale it ?
                        img = img.scaled(
                            hs_cols, hs_rows, Qt.IgnoreAspectRatio,
                            Qt.SmoothTransformation
                        )  # force to our dest size. Note that IgnoreAspectRatio guarantess the right size. Ther other modes don't
                        if img.isNull() or (img.width(), img.height()) != (
                                hs_cols, hs_rows):
                            handler.show_error(
                                _("Could not scale image to {} x {} pixels").
                                format(hs_cols, hs_rows))
                            return
                    target_fmt = QImage.Format_RGB888
                    img = img.convertToFormat(
                        QImage.Format_Indexed8
                    ).convertToFormat(
                        target_fmt
                    )  # dither it down to 256 colors to reduce image complexity then back up to 24 bit for easy reading
                    if img.isNull():
                        handler.show_error(
                            _("Could not dither or re-render image"))
                        return

                    def qimg_to_toif(img, handler):
                        try:
                            import struct, zlib
                        except ImportError as e:
                            handler.show_error(
                                _("Could not convert image, a required library is missing: {}"
                                  ).format(e))
                            return
                        data, pixeldata = bytearray(), bytearray()
                        data += b'TOIf'
                        for y in range(img.width()):
                            for x in range(img.height()):
                                rgb = img.pixel(x, y)
                                r, g, b = qRed(rgb), qGreen(rgb), qBlue(rgb)
                                c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (
                                    (b & 0xF8) >> 3)
                                pixeldata += struct.pack(">H", c)
                        z = zlib.compressobj(level=9, wbits=10)
                        zdata = z.compress(bytes(pixeldata)) + z.flush()
                        zdata = zdata[2:-4]  # strip header and checksum
                        data += struct.pack("<HH", img.width(), img.height())
                        data += struct.pack("<I", len(zdata))
                        data += zdata
                        return bytes(data)

                    return qimg_to_toif(img, handler)
コード例 #2
0
                def read_and_convert_using_qt_to_raw_mono(
                        handler, filename, hs_cols, hs_rows, invert=True):
                    img = QImage(filename)
                    if img.isNull():
                        handler.show_error(
                            _('Could not load the image {} -- unknown format or other error'
                              ).format(os.path.basename(filename)))
                        return
                    if (img.width(), img.height()) != (
                            hs_cols, hs_rows):  # do we need to scale it ?
                        img = img.scaled(
                            hs_cols, hs_rows, Qt.IgnoreAspectRatio,
                            Qt.SmoothTransformation
                        )  # force to our dest size. Note that IgnoreAspectRatio guarantess the right size. Ther other modes don't
                        if img.isNull() or (img.width(), img.height()) != (
                                hs_cols, hs_rows):
                            handler.show_error(
                                _("Could not scale image to {} x {} pixels").
                                format(hs_cols, hs_rows))
                            return
                    bm = QBitmap.fromImage(
                        img, Qt.MonoOnly)  # ensures 1bpp, dithers any colors
                    if bm.isNull():
                        handler.show_error(
                            _('Could not convert image to monochrome'))
                        return
                    target_fmt = QImage.Format_Mono
                    img = bm.toImage().convertToFormat(
                        target_fmt,
                        Qt.MonoOnly | Qt.ThresholdDither | Qt.AvoidDither
                    )  # ensures MSB bytes again (above steps may have twiddled the bytes)
                    lineSzOut = hs_cols // 8  # bits -> num bytes per line
                    bimg = bytearray(hs_rows *
                                     lineSzOut)  # 1024 bytes for a 128x64 img
                    bpl = img.bytesPerLine()
                    if bpl < lineSzOut:
                        handler.show_error(
                            _("Internal error converting image"))
                        return
                    # read in 1 scan line at a time since the scan lines may be > our target packed image
                    for row in range(hs_rows):
                        # copy image scanlines 1 line at a time to destination buffer
                        ucharptr = img.constScanLine(
                            row)  # returned type is basically void*
                        ucharptr.setsize(
                            bpl)  # inform python how big this C array is
                        b = bytes(ucharptr)  # aaand.. work with bytes.

                        begin = row * lineSzOut
                        end = begin + lineSzOut
                        bimg[begin:end] = b[0:lineSzOut]
                        if invert:
                            for i in range(begin, end):
                                bimg[i] = ~bimg[i] & 0xff  # invert b/w
                    return bytes(bimg)
コード例 #3
0
ファイル: QImageViewer.py プロジェクト: antonpat/QFilemanager
class ImageViewer(QMainWindow):
    def __init__(self):
        super(ImageViewer, self).__init__()

        self.myimage = QImage()
        self.filename = ""
        self.scaleFactor = 1.778 #0.56

        self.imageLabel = QLabel()
        self.imageLabel.setBackgroundRole(QPalette.Base)
        mp = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imageLabel.setSizePolicy(mp)
        self.imageLabel.setScaledContents(True)
        self.setCentralWidget(self.imageLabel)

        self.setWindowTitle("Image Viewer")
        w = 400
        h = int(400 / self.scaleFactor)
        self.resize(w, h)
        self.move(0, 0)

    def resizeEvent(self, event):
        if not self.myimage.isNull():
           self.updateView()

    def updateView(self):
        if self.scaleFactor < 1:
            self.imageLabel.resize(self.height() * self.scaleFactor, self.height())
        else:
            self.imageLabel.resize(self.width(), (self.width() / self.scaleFactor))
        w = self.imageLabel.width()
        h = self.imageLabel.height()
        self.resize(w, h)

    def loadFile(self, fileName):
        if self.filename:
            self.myimage = QImage(self.filename)
            if self.myimage.isNull():
                QMessageBox.information(self, "Image Viewer",
                        "Cannot load %s." % self.filename)
                return
            self.imageLabel.setPixmap(QPixmap.fromImage(self.myimage))
            self.scaleFactor = int(self.myimage.width()) / int(self.myimage.height())
            f = round(self.scaleFactor, 3)
            if self.scaleFactor < 1:
                self.resize(600 * self.scaleFactor, 600)
            else:
                self.resize(600, 600 / self.scaleFactor)
            self.setWindowTitle(os.path.splitext(str(self.filename))[0].split("/")[-1])
コード例 #4
0
ファイル: image.py プロジェクト: cangfengzhe/indigo-GUI
    def open_image(self, fileName):
        # fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
        #         QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                        "Cannot load %s." % fileName)
                return
            qpix = QPixmap.fromImage(image)
            self.imageLabel.setPixmap(qpix)
            self.image_obj = qpix
            # myScaledPixmap = myPixmap.scaled(self.label.size(), Qt.KeepAspectRatio)
            self.scaleFactor = 1.0

            # myPixmap = QPixmap(fileName)
            # myScaledPixmap = myPixmap.scaled(self.imageLabel.size(), Qt.KeepAspectRatio)
            # self.imageLabel.setPixmap(myScaledPixmap)

            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
            self.change_image_size()
コード例 #5
0
ファイル: BWindow.py プロジェクト: Esttelle/CuteImage
    def update_image_info(self, file_name):
        tmp_image = QImage(file_name)
        if tmp_image.isNull():
            return

        short_name = file_name.split("/")[-1]
        self.name_lbl.setText("Name: " + short_name)
        img_format = short_name.split(".")[-1]
        self.format_lbl.setText("Format: " + img_format + " image")
        self.size_lbl.setText("Size: " +
                              str(int(os.path.getsize(file_name) / 1024)) +
                              "kB")
        self.height_lbl.setText("Height: " + str(tmp_image.height()))
        self.width_lbl.setText("Width: " + str(tmp_image.width()))
        self.modified_time_lbl.setText("Created: " +
                                       time.ctime(os.path.getmtime(file_name)))
        self.created_time_lbl.setText("Modified: " +
                                      time.ctime(os.path.getatime(file_name)))
        self.color_space_lbl.setText("Color space: RGB")
        self.color_profile_lbl.setText("Color profile: sRGB IEC61966-2.1")
        self.path_lbl.setText(
            "Where: Pictures/" +
            file_name.split("Photos_Library_photoslibrary/")[-1])

        icon_name = "./thumbnails/" + short_name.replace(".", "@2x.")
        self.generate_icon(file_name, icon_name)

        self.icon_pixmap = QPixmap(icon_name)
        self.icon_pixmap = self.icon_pixmap.scaledToHeight(250)
        self.icon_pixmap = self.icon_pixmap.scaledToWidth(250)
        self.image_icon_lbl.setPixmap(self.icon_pixmap)
        self.image_icon_lbl.setFixedWidth(140)
コード例 #6
0
ファイル: image.py プロジェクト: cangfengzhe/indigo-GUI
    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
                QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                        "Cannot load %s." % fileName)
                return
            # myPixmap = QPixmap.fromImage(image)
            qpix = QPixmap.fromImage(image)
            self.image_obj = qpix
            self.flag = 1
            print(self.height/qpix.size().height())
            # self.scaleImage(0.8)

            self.imageLabel.setPixmap(qpix)
            self.scaleFactor = 1.0
            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()

            self.change_image_size()
コード例 #7
0
def main():
    USAGE = 'Usage:\n    python tempfile2clipboard.py [--delete] image_filepath\n'

    if len(sys.argv) > 1 and sys.argv[1] == '--delete':
        delete = True
        del sys.argv[1]
    else:
        delete = False

    if len(sys.argv) != 2:
        sys.stderr.write("Invalid arguments.\n" + USAGE)
        sys.exit(1)

    image_file = sys.argv[1]
    image = QImage(image_file)
    if delete:
        os.unlink(image_file)

    if image.isNull():
        sys.stderr.write("Invalid image file: {}.\n".format(image_file) + USAGE)
        sys.exit(1)

    app = QApplication([])
    app.clipboard().setImage(image)

    # Keep running until the clipboard contents change to something else:
    app.clipboard().dataChanged.connect(app.quit)
    app.exec_()
コード例 #8
0
	def loadFile(self, fname):
		#print(fname)
		if fname is None:
			action = self.sender()
			if isinstance(action, QAction):
				fname = str(action.data().toString)
				if not self.okToContinue():
					return
			else:
				return
		if fname:
			self.filename = None
			image = QImage(fname)
			if image.isNull():
				message = 'failed to read {0}'.format(fname)
			else:
				self.addRecentFiles(fname)
				self.image = QImage()
				for action, check in self.resettableActions:
					action.setChecked(check)
				self.image = image
				self.filename = fname
				self.showImage()
				self.dirty = False
				self.sizeLabel.setText('{0} x {1}'.format(image.width(), image.height()))
				message = 'Loaded {0}'.format(os.path.basename(fname))
			self.updateStatus(message)
コード例 #9
0
    def _parse_image(
        self,
        width: int,
        height: int,
        bytes_per_line: int,
        has_alpha: bool,
        bits_per_color: int,
        channel_count: int,
        data: QByteArray,
    ) -> QImage:
        """Make sure the given image data is valid and return a QImage."""
        # Chromium limit?
        assert 0 < width <= 320
        assert 0 < height <= 320

        # Based on dunst:
        # https://github.com/dunst-project/dunst/blob/v1.6.1/src/icon.c#L336-L348
        # (A+7)/8 rounds up A to the next byte boundary
        pixelstride = (channel_count * bits_per_color + 7) // 8
        expected_len = (height - 1) * bytes_per_line + width * pixelstride
        assert len(data) == expected_len

        assert bits_per_color == 8
        assert channel_count == (4 if has_alpha else 3)
        assert bytes_per_line >= width * channel_count

        qimage_format = QImage.Format_RGBA8888 if has_alpha else QImage.Format_RGB888
        img = QImage(data, width, height, bytes_per_line, qimage_format)
        assert not img.isNull()
        assert img.width() == width
        assert img.height() == height

        return img
コード例 #10
0
    def insertImage(self):

        # Get image file name
        filename = QFileDialog.getOpenFileName(
            self, 'Insert image', ".",
            "Images (*.png *.xpm *.jpg *.bmp *.gif)")[0]

        if filename:

            # Create image object
            image = QImage(filename)

            # Error if unloadable
            if image.isNull():

                popup = QMessageBox(QMessageBox.Critical, "Image load error",
                                    "Could not load image file!",
                                    QMessageBox.Ok, self)
                popup.show()

            else:

                cursor = self.textCursor()

                cursor.insertImage(image, filename)
コード例 #11
0
    def loadRecentDocuments(self):
        self.recentDocuments = []
        recentDocumentsPaths = self.kritaInstance.recentDocuments()

        for path in recentDocumentsPaths:
            if path:
                thumbnail = None
                extension = Path(path).suffix
                page = None
                if extension == '.kra':
                    page = zipfile.ZipFile(path, "r")
                    thumbnail = QImage.fromData(page.read("mergedimage.png"))
                    if thumbnail.isNull():
                        thumbnail = QImage.fromData(page.read("preview.png"))
                else:
                    thumbnail = QImage(path)

                if thumbnail.isNull():
                    continue

                thumbSize = QSize(200 * self.devicePixelRatioF,
                                  150 * self.devicePixelRatioF)
                if thumbnail.width() <= thumbSize.width() or thumbnail.height(
                ) <= thumbSize.height():
                    thumbnail = thumbnail.scaled(thumbSize, Qt.KeepAspectRatio,
                                                 Qt.FastTransformation)
                else:
                    thumbnail = thumbnail.scaled(thumbSize, Qt.KeepAspectRatio,
                                                 Qt.SmoothTransformation)
                thumbnail.setDevicePixelRatio(self.devicePixelRatioF)
                self.recentDocuments.append(thumbnail)
        self.modelReset.emit()
コード例 #12
0
    def openRight(self):
        options = QFileDialog.Options()
        # fileName = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            'QFileDialog.getOpenFileName()',
            '',
            'Images (*.png *.jpeg *.jpg *.bmp *.gif)',
            options=options)
        if fileName:
            print(fileName)
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.imageLabelRight.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.scrollAreaRight.setVisible(True)
            self.window.printRightAct.setEnabled(True)
            self.window.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.window.fitToWindowAct.isChecked():
                self.imageLabelRight.adjustSize()
コード例 #13
0
ファイル: icons.py プロジェクト: Axel-Erfurt/pyqt5
    def changeIcon(self):
        icon = QIcon()

        for row in range(self.imagesTable.rowCount()):
            item0 = self.imagesTable.item(row, 0)
            item1 = self.imagesTable.item(row, 1)
            item2 = self.imagesTable.item(row, 2)

            if item0.checkState() == Qt.Checked:
                if item1.text() == "Normal":
                    mode = QIcon.Normal
                elif item1.text() == "Active":
                    mode = QIcon.Active
                elif item1.text() == "Disabled":
                    mode = QIcon.Disabled
                else:
                    mode = QIcon.Selected

                if item2.text() == "On":
                    state = QIcon.On
                else:
                    state = QIcon.Off

                fileName = item0.data(Qt.UserRole)
                image = QImage(fileName)
                if not image.isNull():
                    icon.addPixmap(QPixmap.fromImage(image), mode, state)

        self.previewArea.setIcon(icon)
コード例 #14
0
 def loadFile(self, actiontrigger=False, fname=None):
     if fname is None:
         action = self.sender()
         if isinstance(action, QAction):
             fname = str(action.data())
             if not self.okToContinue():
                 return
         else:
             return
     print(fname)
     if fname:
         self.filename = None
         image = QImage(fname)
         cvimg = cv2.imread(fname)
         if image.isNull():
             message = "Failed to read {0}".format(fname)
         else:
             self.addRecentFile(fname)
             self.originImage = QImage()
             for action, check in self.resetableActions:
                 action.setChecked(check)
             self.originImage = image
             self.currentImage = self.originImage
             self.imgStack.push(self.currentImage)
             self.cvimg = cvimg
             self.cvimgstack.push(self.cvimg)
             self.filename = fname
             self.showImage()
             self.dirty = False
             self.sizeLabel.setText("{0} x {1}".format(
                 image.width(), image.height()))
             message = "Loaded {0}".format(os.path.basename(fname))
         self.updateStatus(message)
コード例 #15
0
    def open(self, url):
        print("IN THE OPEN FUNCTION")
        # options = QFileDialog.Options()
        # fileName = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())
        # fileName, _ = QFileDialog.getOpenFileName(self, 'QFileDialog.getOpenFileName()', '',
        #                                           'Images (*.png *.jpeg *.jpg *.bmp *.gif)', options=options)

        fileName = url

        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.imageLabel[self.count].setPixmap(QPixmap.fromImage(image))
            # map(lambda obj: obj.setPixmap(QPixmap.fromImage(image)), self.imageLabel)
            # map(lambda obj: self._lay.addWidget(obj), self.imageLabel)
            self._lay.addWidget(self.imageLabel[self.count])
            self.count += 1
            self.scaleFactor = 1.0

            self.scrollArea.setVisible(True)
            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel[self.count].adjustSize()
コード例 #16
0
def render_avatar_image(image: QImage, size: float):
    if image.isNull():
        return None

    aspect_ratio = image.width() / image.height()
    if aspect_ratio > 1:
        width = size
        height = size / aspect_ratio
    else:
        width = size * aspect_ratio
        height = size

    x0 = (size - width) / 2
    y0 = (size - height) / 2

    path = QPainterPath()
    path.addEllipse(QRectF(x0, y0, width, height))
    picture = QPicture()
    painter = QPainter(picture)
    painter.setRenderHint(QPainter.Antialiasing, True)
    pen = QPen(Qt.black, 5)
    pen.setStyle(Qt.SolidLine)
    painter.setPen(pen)
    painter.setClipPath(path)
    painter.drawImage(
        QRectF(x0, y0, width, height),
        image,
    )
    painter.end()
    return picture
コード例 #17
0
    def open(self):
        options = QFileDialog.Options()
        self.fileName, _ = QFileDialog.getOpenFileName(MainWindow, 'QFileDialog.getOpenFileName()', '',
                                                  'Images (*.png *.jpeg *.jpg *.bmp *.gif)', options=options)

        if self.fileName:
            image = QImage(self.fileName)
            if image.isNull():
                QMessageBox.information(self.centralwidget, "Image Viewer", "Cannot load %s." % self.fileName)
                return

            pm = QPixmap.fromImage(image)
            w = pm.width()
            h = pm.height()

            if (w <= self.max_w and h <= self.max_h):
                self.imageLabel.setPixmap(pm)
            else:
                msg = QMessageBox()
                msg.setWindowTitle("Image Size Error")
                msg.setText("Image size is too big!")
                x = msg.exec_()  # this will show our messagebox


            self.scaleFactor = 1.0

            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.imageLabel.setAlignment(Qt.AlignCenter)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
コード例 #18
0
ファイル: imageviewer.py プロジェクト: zsalch/frescobaldi
class ImageViewer(QScrollArea):

    actualSizeChanged = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(ImageViewer, self).__init__(parent, alignment=Qt.AlignCenter)
        self._actualsize = True
        self._image = QImage()
        self.setBackgroundRole(QPalette.Dark)
        self.setWidget(ImageWidget(self))

    def setActualSize(self, enabled=True):
        if enabled == self._actualsize:
            return
        self.setWidgetResizable(not enabled)
        if enabled and not self._image.isNull():
            self.widget().resize(self._image.size())
        self._actualsize = enabled
        self.actualSizeChanged.emit(enabled)

    def actualSize(self):
        return self._actualsize

    def setImage(self, image):
        self._image = image
        self._pixmap = None
        self._pixmapsize = None
        if self._actualsize:
            self.widget().resize(image.size())
        self.widget().update()

    def image(self):
        return self._image

    def pixmap(self, size):
        """Returns (and caches) a scaled pixmap for the image."""
        if self._pixmapsize == size:
            return self._pixmap
        self._pixmap = QPixmap.fromImage(
            self._image.scaled(size, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        self._pixmapsize = size
        return self._pixmap

    def startDrag(self):
        image = self.image()
        data = QMimeData()
        data.setImageData(image)
        drag = QDrag(self)
        drag.setMimeData(data)
        if max(image.width(), image.height()) > 256:
            image = image.scaled(QSize(256, 256), Qt.KeepAspectRatio, Qt.SmoothTransformation)
        p = QPainter()
        p.begin(image)
        p.setCompositionMode(QPainter.CompositionMode_DestinationIn)
        p.fillRect(image.rect(), QColor(0, 0, 0, 160))
        p.end()
        pixmap = QPixmap.fromImage(image)
        drag.setPixmap(pixmap)
        drag.setHotSpot(pixmap.rect().center())
        drag.exec_(Qt.CopyAction)
コード例 #19
0
    def run(self):
        img = QImage(self.file_name)
        if img.isNull():
            return

        img = img.scaled(self.width, self.height)
        self.signals.about_image.emit(self.file_name, img)
コード例 #20
0
ファイル: quteprocess.py プロジェクト: spk/qutebrowser
    def get_screenshot(
            self,
            *,
            probe_pos: QPoint = None,
            probe_color: QColor = testutils.Color(0, 0, 0),
    ) -> QImage:
        """Get a screenshot of the current page.

        Arguments:
            probe: If given, only continue if the pixel at the given position isn't
                   black (or whatever is specified by probe_color).
        """
        for _ in range(5):
            tmp_path = self.request.getfixturevalue('tmp_path')
            path = tmp_path / 'screenshot.png'
            self.send_cmd(f':screenshot --force {path}')
            self.wait_for(message=f'Screenshot saved to {path}')

            img = QImage(str(path))
            assert not img.isNull()

            if probe_pos is None:
                return img

            probed_color = testutils.Color(img.pixelColor(probe_pos))
            if probed_color == probe_color:
                return img

            # Rendering might not be completed yet...
            time.sleep(0.5)

        raise ValueError(
            f"Pixel probing for {probe_color} failed (got {probed_color} on last try)"
        )
コード例 #21
0
ファイル: QtImageViewerPlus.py プロジェクト: WeiHao-19/TagLab
    def setChannel(self, channel, switch=False):
        """
        Set the image channel to visualize. If the channel has not been previously loaded it is loaded and cached.
        """

        if self.image is None:
            raise ("Image has not been previously set in ViewerPlus")

        self.channel = channel

        if channel.qimage is not None:
            img = channel.qimage
        else:
            QApplication.setOverrideCursor(Qt.WaitCursor)
            img = channel.loadData()
            QApplication.restoreOverrideCursor()

        if img.isNull():
            (channel.filename, filter) = QFileDialog.getOpenFileName(
                self, "Couldn't find the map, please select it:",
                QFileInfo(channel.filename).dir().path(),
                "Image Files (*.png *.jpg)")
            dir = QDir(os.getcwd())
            self.map_image_filename = dir.relativeFilePath(channel.filename)
            img = QImage(channel.filename)
            if img.isNull():
                raise Exception("Could not load or find the image: " +
                                channel.filename)

        if switch:
            self.setChannelImg(img, self.zoom_factor)
        else:
            self.setChannelImg(img)
コード例 #22
0
    def changeIcon(self):
        icon = QIcon()

        for row in range(self.imagesTable.rowCount()):
            item0 = self.imagesTable.item(row, 0)
            item1 = self.imagesTable.item(row, 1)
            item2 = self.imagesTable.item(row, 2)

            if item0.checkState() == Qt.Checked:
                if item1.text() == "Normal":
                    mode = QIcon.Normal
                elif item1.text() == "Active":
                    mode = QIcon.Active
                elif item1.text() == "Disabled":
                    mode = QIcon.Disabled
                else:
                    mode = QIcon.Selected

                if item2.text() == "On":
                    state = QIcon.On
                else:
                    state = QIcon.Off

                fileName = item0.data(Qt.UserRole)
                image = QImage(fileName)
                if not image.isNull():
                    icon.addPixmap(QPixmap.fromImage(image), mode, state)

        self.previewArea.setIcon(icon)
コード例 #23
0
    def abrirImagen(self):
        self.ruta, _ = QFileDialog.getOpenFileName(
            MainWindow, "Abrir imagen", QDir.currentPath(),
            "Image Files (*.png *.jpg *.bmp *.tif)")
        url = QUrl.fromLocalFile(self.ruta)
        if self.ruta:
            image = QImage(self.ruta)
            imageP = Image.open(self.ruta)

            if image.isNull():  # En caso de error mostrar un mensaje grafico
                QMessageBox.information(
                    self, "Visualizador de imagenes",
                    "No se pudo cargar la imagen %s" % (self.ruta))
                return
            self.painter.setPixmap(QPixmap.fromImage(image))
            self.painter.setAlignment(Qt.Qt.AlignCenter)

            self.label_size.setText("Tamaño: %d x %d" %
                                    (image.width(), image.height()))
            self.label_nombre.setText("Nombre: %s " % (url.fileName()))
            self.label_tipo.setText("Tipo: %s" % (imageP.mode))
            MainWindow.setWindowTitle(
                "Editor de imagenes - %s" % (url.fileName())
            )  # Agregamos el nombre de la imagen al titulo de la imagen
            self.spinAlto.setValue(image.height())
            self.spinAncho.setValue(image.width())
コード例 #24
0
ファイル: GitThread.py プロジェクト: zhrbing/PyQtClient
    def get_avatar(self, uid, avatar_url):
        try:
            req = requests.get(avatar_url)
            if req.status_code == 200:
                imgformat = req.headers.get(
                    'content-type', 'image/jpg').split('/')[1]
                Constants.ImageAvatar = os.path.join(
                    Constants.ImageDir, str(uid)).replace('\\', '/') + '.jpg'
                AppLog.debug('image type: {}'.format(imgformat))
                AppLog.debug(
                    'content length: {}'.format(len(req.content)))

                image = QImage()
                if image.loadFromData(req.content):
                    # 缩放图片
                    if not image.isNull():
                        image = image.scaled(130, 130, Qt.IgnoreAspectRatio,
                                             Qt.SmoothTransformation)
                        AppLog.debug('save to: {}'.format(
                            Constants.ImageAvatar))
                        image.save(Constants.ImageAvatar)
                    else:
                        AppLog.warn('avatar image is null')
                else:
                    AppLog.warn('can not load from image data')
        except Exception as e:
            AppLog.exception(e)
コード例 #25
0
    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
                QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                        "Cannot load %s." % fileName)
                return

            self.imageLabel.setPixmap(QPixmap.fromImage(image))

            self.scaleFactor = 1.0

            ratio = np.max([self.imageLabel.pixmap().width()/w,
                            self.imageLabel.pixmap().height()/h])

            self.minRatio = 1/ratio
            self.maxRatio = 1.0

            self.scaleImage(self.minRatio)


            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()

            self.scaleImage(1)
コード例 #26
0
            def mouseReleaseEvent(self, event):

                if self.selection.isVisible():
                    currentQRect = self.selection.geometry()
                    cropQPixmap = self.pixmap().copy(currentQRect)
                    cropQPixmap.save('output.png')

                    image = QImage("output.png")
                    if image.isNull():
                        QMessageBox.information(self.centralwidget, "Image Viewer", "Cannot load %s." % self.fileName)
                        return

                    pm = QPixmap.fromImage(image)
                    h = pm.height()
                    w = pm.width()

                    if (h > w):
                        self._parent_class.originalImageLabel.setPixmap(pm.scaledToHeight(400))

                    else:
                        self._parent_class.originalImageLabel.setPixmap(pm.scaledToWidth(400))



                    self.selection.hide()
コード例 #27
0
def _loadQtImage(path: str) -> QImage:
    reader = QImageReader(path)
    image = QImage(reader.read())
    if not image.isNull():
        return image
    else:
        return None
コード例 #28
0
ファイル: lvl_face.py プロジェクト: hanyh0807/lvl_face
    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
                                                  QDir.currentPath())
        if fileName:
            #            fileName = 'data/soojung/1513023157032.jpg'
            #    cv2.getTextSize('myungeun : 0.3513', cv2.FONT_HERSHEY_SIMPLEX, 0.5,1)
            #    cv2.rectangle(bgrImage, (dx+w, y), (dx+w+94, yo+3), (255,255,255), -1)

            outimg = self.findFaceAndClassify(fileName)
            outimg = cv2.cvtColor(outimg, cv2.COLOR_BGR2RGB)
            h, w, c = outimg.shape
            bytesPerLine = 3 * w
            image = QImage(outimg, w, h, bytesPerLine, QImage.Format_RGB888)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.imageLabel.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.fitToWindowAct.setEnabled(True)
            self.updateActions()
            self.resize(w, h)
            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
コード例 #29
0
    def view(self):
        fileNameDir = "Data/1999_2017_landsat_time_series/roi/cut/fileNames.txt"
        if 'fileNameDir' in locals():
            pass
        else:
            raise AssertionError("FILE_NAME_DIR is not given!")

        with open(fileNameDir, "r") as file:
            imageFileNames = file.readlines()  # imageFiles is a list
            file.close()

        for fileName in imageFileNames:
            fileName = "Data/1999_2017_landsat_time_series/roi/cut/" + fileName[:
                                                                                -1] + ".tif"

            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.imageLabel.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            #self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
            app.processEvents()

            time.sleep(0.001)
        """
コード例 #30
0
ファイル: notification.py プロジェクト: mkonig/qutebrowser
    def _get_hints_arg(self, *, origin_url: QUrl,
                       icon: QImage) -> Dict[str, Any]:
        """Get the hints argument for present()."""
        origin_url_str = origin_url.toDisplayString()
        hints: Dict[str, Any] = {
            # Include the origin in case the user wants to do different things
            # with different origin's notifications.
            "x-qutebrowser-origin": origin_url_str,
            "desktop-entry": "org.qutebrowser.qutebrowser",
        }

        is_useful_origin = self._should_include_origin(origin_url)
        if self._capabilities.kde_origin_name and is_useful_origin:
            hints["x-kde-origin-name"] = origin_url_str

        if icon.isNull():
            filename = 'icons/qutebrowser-64x64.png'
            icon = QImage.fromData(resources.read_file_binary(filename))

        key = self._quirks.icon_key or "image-data"
        data = self._convert_image(icon)
        if data is not None:
            hints[key] = data

        return hints
コード例 #31
0
    def on_imagePicker_textChanged(self, address):
        """
        Private slot handling changes of the image path.
        
        @param address image address (URL or local path)
        @type str
        """
        if address and "://" not in address:
            image = QImage(address)
            # load the file to set the size spin boxes
            if image.isNull():
                self.widthSpinBox.setValue(0)
                self.heightSpinBox.setValue(0)
                self.__originalImageSize = QSize()
                self.__aspectRatio = 1
            else:
                self.widthSpinBox.setValue(image.width())
                self.heightSpinBox.setValue(image.height())
                self.__originalImageSize = image.size()
                self.__aspectRatio = (
                    float(self.__originalImageSize.height()) /
                    self.__originalImageSize.width())
        else:
            self.widthSpinBox.setValue(0)
            self.heightSpinBox.setValue(0)
            self.__originalImageSize = QSize()
            self.__aspectRatio = 1

        self.__updateOkButton()
コード例 #32
0
    def open(self):
        #if self.maybeSave():
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Image",
                                                  QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "iScissor",
                                        "Cannot load %s." % fileName)
                return
            self.setCurrentFile(fileName)
            imageLabel = proj1_image.Image(fileName)  #QLabel()
            imageLabel.setBackgroundRole(QPalette.Base)
            imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
            imageLabel.setScaledContents(True)
            imageLabel.setPixmap(QPixmap.fromImage(image))

            self.graphicsView.setWidget(imageLabel)
            self.graphicsView.initForImage(fileName)
            self.scaleFactor = 1.0
            self.normalSize()
            self.iScissorStartAct.setEnabled(True)
            self.undoAct.setEnabled(True)
            self.normalSizeAct.setEnabled(True)
            self.zoomInAct.setEnabled(True)
            self.zoomOutAct.setEnabled(True)

            print(self.getCurrentFile())
        return
コード例 #33
0
ファイル: imageitem.py プロジェクト: death-finger/Scripts
    def createImage(self, transform):
        original = QImage(self.image)
        if original.isNull():
            return original

        size = transform.map(QPoint(self.maxWidth, self.maxHeight))
        w = size.x()
        h = size.y()

        # Optimization: if image is smaller than maximum allowed size, just
        # return the loaded image.
        if original.size().height() <= h and original.size().width() <= w and not self.adjustSize and self.scale == 1:
            return original

        # Calculate what the size of the final image will be.
        w = min(w, float(original.size().width()) * self.scale)
        h = min(h, float(original.size().height()) * self.scale)

        adjustx = 1.0
        adjusty = 1.0
        if self.adjustSize:
            adjustx = min(transform.m11(), transform.m22())
            adjusty = max(transform.m22(), adjustx)
            w *= adjustx
            h *= adjusty

        # Create a new image with correct size, and draw original on it.
        image = QImage(int(w + 2), int(h + 2),
                QImage.Format_ARGB32_Premultiplied)
        image.fill(QColor(0, 0, 0, 0).rgba())
        painter = QPainter(image)
        painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
        if self.adjustSize:
            painter.scale(adjustx, adjusty)
        if self.scale != 1:
            painter.scale(self.scale, self.scale)
        painter.drawImage(0, 0, original)

        if not self.adjustSize:
            # Blur out edges.
            blur = 30

            if h < original.height():
                brush1 = QLinearGradient(0, h - blur, 0, h)
                brush1.setSpread(QLinearGradient.PadSpread)
                brush1.setColorAt(0.0, QColor(0, 0, 0, 0))
                brush1.setColorAt(1.0, Colors.sceneBg1)
                painter.fillRect(0, int(h) - blur, original.width(), int(h),
                        brush1)

            if w < original.width():
                brush2 = QLinearGradient(w - blur, 0, w, 0)
                brush2.setSpread(QLinearGradient.PadSpread)
                brush2.setColorAt(0.0, QColor(0, 0, 0, 0))
                brush2.setColorAt(1.0, Colors.sceneBg1)
                painter.fillRect(int(w) - blur, 0, int(w), original.height(),
                        brush2)

        return image
コード例 #34
0
ファイル: CustomObjects.py プロジェクト: afester/CodeSamples
    def setName(self, imageName):
        '''Sets the file name of the image. Either an absolute path name or 
           a path relative to the current working directory.'''

        self.imageName = imageName
        img = QImage(imageName)
        if not img.isNull():
            self.bufferedImage = img
コード例 #35
0
    def setName(self, imageName):
        '''Sets the file name of the image. Either an absolute path name or 
           a path relative to the current working directory.'''

        self.imageName = imageName
        img = QImage(imageName)
        if not img.isNull():
            self.bufferedImage = img
コード例 #36
0
ファイル: EditorWidget.py プロジェクト: afester/CodeSamples
 def insertImage(self):
     filePath = QFileDialog.getOpenFileName(self, caption='Select Image file')[0]
     # print('{}: "{}" {}'.format(type(filePath), filePath, len(filePath)))
     if len(filePath) > 0:
         image = QImage(filePath)
         if image.isNull():
             QMessageBox.information(self, "Error", '"{}"\nis not a valid image file'.format(filePath))
         else:
             self.editView.insertImage(image)
コード例 #37
0
ファイル: executors.py プロジェクト: Pewpews/happypanda
def _task_load_thumbnail(ppath, thumb_size, on_method=None, **kwargs):
	if ppath:
		img = QImage(ppath)
		if not img.isNull():
			size = img.size()
			if size.width() != thumb_size[0]:
				# TODO: use _task_thumbnail
				img = _rounded_qimage(img.scaled(thumb_size[0], thumb_size[1], Qt.KeepAspectRatio, Qt.SmoothTransformation), 5)
			if on_method:
				on_method(img, **kwargs)
			return img
コード例 #38
0
ファイル: __init__.py プロジェクト: hgoldfish/quickpanel
 def useDefaultBackground(self):
     filename = "background.png"
     if not os.path.exists(filename):
         filename = os.path.join(os.path.dirname(__file__), filename)
     if os.path.exists(filename):
         image = QImage(filename)
         if not image.isNull():
             self._makeBackground(image)
             moveToCenter(self)
             self.canvas.positWidgets()
             self.update()
     settings = self.platform.getSettings()
     settings.remove("background")
コード例 #39
0
ファイル: __init__.py プロジェクト: hydrargyrum/pyfdthumbnail
	def get_info(self, path):
		from PyQt5.QtGui import QImage

		img = QImage(path)
		if img.isNull():
			return

		try:
			return {
				'mtime': int(float(img.text(KEY_MTIME) or 0)),
				'uri': img.text(KEY_URI),
			}
		except ValueError:
			return
コード例 #40
0
ファイル: __init__.py プロジェクト: hydrargyrum/pyfdthumbnail
	def update_metadata(self, dest, moreinfo=None):
		from PyQt5.QtGui import QImage

		img = QImage(dest)
		if img.isNull():
			return

		self.setattributes(img, moreinfo)
		img.setText(KEY_WIDTH, str(img.size().width()))
		img.setText(KEY_HEIGHT, str(img.size().height()))

		tmp = _mkstemp(dest)
		img.save(tmp)
		os.rename(tmp, dest)
		return dest
コード例 #41
0
ファイル: interface.py プロジェクト: kmyk/nantoka-agent
    def loadImage(self, fileName):
        image = QImage(fileName)
        assert not image.isNull()

        pixmap = QPixmap.fromImage(image)
        mask = pixmap.createMaskFromColor(QColor(image.pixel(0,0)), Qt.MaskInColor)
        if self.use_title_bar:
            pixmap.setMask(mask)
            self.imageLabel.setMask(mask)
        else:
            self.setMask(mask)

        self.imageLabel.setPixmap(pixmap)
        self.imageLabel.adjustSize()
        self.setFixedSize(image.size())

        self.landOnScreen()
コード例 #42
0
ファイル: imageviewer.py プロジェクト: death-finger/Scripts
    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File", QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer", "Cannot load %s." % fileName)
                return

            self.imageLabel.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
コード例 #43
0
ファイル: executors.py プロジェクト: Pewpews/happypanda
def _task_thumbnail(gallery_or_path, img=None, width=app_constants.THUMB_W_SIZE,
						height=app_constants.THUMB_H_SIZE):
	"""
	"""
	log_i("Generating thumbnail")
	# generate a cache dir if required
	if not os.path.isdir(db_constants.THUMBNAIL_PATH):
		os.mkdir(db_constants.THUMBNAIL_PATH)

	try:
		if not img:
			img_path = utils.get_gallery_img(gallery_or_path)
		else:
			img_path = img
		if not img_path:
			raise IndexError
		for ext in utils.IMG_FILES:
			if img_path.lower().endswith(ext):
				suff = ext # the image ext with dot

		# generate unique file name
		file_name = str(uuid.uuid4()) + ".png"
		new_img_path = os.path.join(db_constants.THUMBNAIL_PATH, (file_name))
		if not os.path.isfile(img_path):
			raise IndexError

		# Do the scaling
		try:
			im_data = utils.PToQImageHelper(img_path)
			image = QImage(im_data['data'], im_data['im'].size[0], im_data['im'].size[1], im_data['format'])
			if im_data['colortable']:
				image.setColorTable(im_data['colortable'])
		except ValueError:
			image = QImage()
			image.load(img_path)
		if image.isNull():
			raise IndexError
		radius = 5
		image = image.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
		r_image = _rounded_qimage(image, radius)
		r_image.save(new_img_path, "PNG", quality=80)
	except IndexError:
		new_img_path = app_constants.NO_IMAGE_PATH

	return new_img_path
コード例 #44
0
ファイル: desktop_icon.py プロジェクト: hgoldfish/quickpanel
 def changeFileIcon(self):
     "用户点击了更换图标按钮。"
     filename, selectedFilter = QFileDialog.getOpenFileName(self, self.windowTitle())
     if not filename:
         return
     image = QImage(filename)
     if not image.isNull():
         self.shortcutIcon = QIcon(QPixmap.fromImage(image))
     else:
         ip = QFileIconProvider()
         shortcutIcon = ip.icon(QFileInfo(filename))
         if shortcutIcon.isNull():
             QMessageBox.information(self, self.tr("更换图标"),
                     self.tr("您选择的文件不包含任何可以使用的图标。"))
             return
         self.shortcutIcon = shortcutIcon
     self.iconPath = filename
     self.btnFace.setIcon(self.shortcutIcon)
コード例 #45
0
    def show_image(self):
        """docstring for show_image"""
        if self.output_path:
            image = QImage(self.output_path)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                        "Cannot load %s." % self.output_path)
                return

            self.imageLabel.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()
コード例 #46
0
ファイル: __init__.py プロジェクト: hydrargyrum/pyfdthumbnail
	def create_thumbnail(self, src, dest, size):
		from PyQt5.QtCore import Qt
		from PyQt5.QtGui import QImage

		img = QImage(str(src))
		if img.isNull():
			return

		res = {
			KEY_MTIME: _any2mtime(src),
			KEY_WIDTH: img.width(),
			KEY_HEIGHT: img.height(),
		}

		img = img.scaled(size, size, Qt.KeepAspectRatio, Qt.SmoothTransformation)

		img.save(dest)
		return res
コード例 #47
0
ファイル: gallerydb.py プロジェクト: peaceandpizza/happypanda
def gen_thumbnail(gallery, width=gui_constants.THUMB_W_SIZE,
				height=gui_constants.THUMB_H_SIZE, img=None):
	"""Generates a thumbnail with unique filename in the cache dir.
	Returns absolute path to the created thumbnail
	"""
	assert isinstance(gallery, Gallery), "gallery should be an instance of Gallery class"

	img_path_queue = queue.Queue()
	# generate a cache dir if required
	if not os.path.isdir(db_constants.THUMBNAIL_PATH):
		os.mkdir(db_constants.THUMBNAIL_PATH)

	try:
		if not img:
			if gallery.is_archive:
				img_path = get_gallery_img(gallery.chapters[0], gallery.path)
			else:
				img_path = get_gallery_img(gallery.chapters[0])
		else:
			img_path = img
		if not img_path:
			raise IndexError
		for ext in IMG_FILES:
			if img_path.lower().endswith(ext):
				suff = ext # the image ext with dot

		# generate unique file name
		file_name = str(uuid.uuid4()) + suff
		new_img_path = os.path.join(db_constants.THUMBNAIL_PATH, (file_name))
		if not os.path.isfile(img_path):
			raise IndexError
		# Do the scaling
		image = QImage()
		image.load(img_path)
		if image.isNull():
			raise IndexError
		image = image.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
		image.save(new_img_path, quality=100)
	except IndexError:
		new_img_path = gui_constants.NO_IMAGE_PATH

	abs_path = os.path.abspath(new_img_path)
	return abs_path
コード例 #48
0
ファイル: PixmapDiagram.py プロジェクト: testmana2/test
 def __showPixmap(self, filename):
     """
     Private method to show a file.
     
     @param filename name of the file to be shown (string)
     @return flag indicating success (boolean)
     """
     image = QImage(filename)
     if image.isNull():
         E5MessageBox.warning(
             self,
             self.tr("Pixmap-Viewer"),
             self.tr(
                 """<p>The file <b>{0}</b> cannot be displayed."""
                 """ The format is not supported.</p>""").format(filename))
         return False
     
     self.pixmapLabel.setPixmap(QPixmap.fromImage(image))
     self.pixmapLabel.adjustSize()
     return True
コード例 #49
0
def qimage_of_bgr(bgr):
    """ A QImage representation of a BGR numpy array
    """
    import cv2
    import numpy as np

    bgr = cv2.cvtColor(bgr.astype('uint8'), cv2.COLOR_BGR2RGB)
    bgr = np.ascontiguousarray(bgr)
    qt_image = QImage(
        bgr.data, bgr.shape[1], bgr.shape[0], bgr.strides[0],
        QImage.Format_RGB888
    )

    if qt_image.isNull():
        raise ValueError('Unable to create QImage')
    else:
        # QImage does not take a deep copy of np_arr.data so hold a reference
        # to it
        assert(not hasattr(qt_image, 'bgr_array'))
        qt_image.bgr_array = bgr
        return qt_image
コード例 #50
0
ファイル: thumbnail.py プロジェクト: Grumbel/dirtool
    def set_thumbnail_image(self, image: QImage) -> None:
        if image is None:
            self.status = ThumbnailStatus.THUMBNAIL_UNAVAILABLE
            self.pixmap = None
        else:
            assert not image.isNull()
            self.status = ThumbnailStatus.THUMBNAIL_READY
            self.pixmap = QPixmap(image)
            try:
                mtime_txt = image.text("Thumb::MTime")
                self.mtime = int(mtime_txt)

                # Thumb::MTime only has 1 second resolution, thus it
                # is quite possible for an thumbnail to be out of date
                # when the file was modified while the thumbnail was
                # extracting (e.g. looking at an extracting archive).
                if int(self.file_item.fileinfo.mtime()) != self.mtime:
                    self.reset()
            except ValueError as err:
                logger.error("%s: couldn't read Thumb::MTime tag on thumbnail: %s",
                             self.file_item.fileinfo.location(), err)
コード例 #51
0
ファイル: ImageReader.py プロジェクト: TinkerGnome/Cura
    def preRead(self, file_name, *args, **kwargs):
        img = QImage(file_name)

        if img.isNull():
            Logger.log("e", "Image is corrupt.")
            return MeshReader.PreReadResult.failed

        width = img.width()
        depth = img.height()

        largest = max(width, depth)
        width = width / largest * self._ui.default_width
        depth = depth / largest * self._ui.default_depth

        self._ui.setWidthAndDepth(width, depth)
        self._ui.showConfigUI()
        self._ui.waitForUIToClose()

        if self._ui.getCancelled():
            return MeshReader.PreReadResult.cancelled
        return MeshReader.PreReadResult.accepted
コード例 #52
0
ファイル: __init__.py プロジェクト: hgoldfish/quickpanel
 def changeBackground(self):
     filename, selectedFilter = QFileDialog.getOpenFileName(self, self.tr("Change Background"), \
         QStandardPaths.writableLocation(QStandardPaths.PicturesLocation), \
         self.tr("Image Files (*.png *.gif *.jpg *.jpeg *.bmp *.mng *ico)"))
     if not filename:
         return
     image = QImage(filename)
     if image.isNull():
         QMessageBox.information(self, self.tr("Change Background"), \
                 self.tr("不能读取图像文件,请检查文件格式是否正确,或者图片是否已经损坏。"))
         return
     if image.width() < 800 or image.height() < 600:
         answer = QMessageBox.information(self, self.tr("Change Background"), \
                 self.tr("不建议设置小于800x600的图片作为背景图案。如果继续,可能会使快捷面板显示错乱。是否继续?"),
                 QMessageBox.Yes | QMessageBox.No,
                 QMessageBox.No)
         if answer == QMessageBox.No:
             return
     self._makeBackground(image)
     moveToCenter(self)
     self.canvas.positWidgets()
     self.update()
     with self.platform.getSettings() as settings:
         settings.setValue("background", filename)
コード例 #53
0
ファイル: lepttool.py プロジェクト: zdenop/pyTesseractDemo
def pix_to_qimage(leptonica, pix_image):
    """ Convert leptonica PIX to QT QImage
    """
    # TODO(zdenop): 8509_001.4B.tif crash this -> implement PIX structure
    if not leptonica:
        return None
    width = leptonica.pixGetWidth(pix_image)
    height = leptonica.pixGetHeight(pix_image)
    depth = leptonica.pixGetDepth(pix_image)

    if depth == 1:
        image_format = QImage.Format_Mono
    elif depth == 8:
        image_format = QImage.Format_Indexed8
    elif depth == 32:
        image_format = QImage.Format_RGB32
    else:
        #  Convert other depths to 32
        pix_image = leptonica.pixConvertTo32(pix_image)
        image_format = QImage.Format_RGB32

    bytes_per_line = leptonica.pixGetWpl(pix_image) * 4
    image_datas = leptonica.pixEndianByteSwapNew(pix_image)
    datas = leptonica.pixGetData(image_datas)

    result = QImage(datas, width, height, bytes_per_line, image_format)

    result.setColorTable(_grayscaleCT)  # (depth == 8)
    if depth == 1:
        result.setColorTable(_bwCT)

    if result.isNull():
        none = QImage(0, 0, QImage.Format_Invalid)
        print('Invalid format!!!')
        return none
    return result.rgbSwapped()
コード例 #54
0
ファイル: make_patch.py プロジェクト: Ffahath/open-numismat
                    query = QSqlQuery(db)
                    query.prepare("""INSERT INTO photos (image)
                            VALUES (?)""")
                    ba = QtCore.QByteArray(img_data)
                    query.addBindValue(ba)
                    query.exec_()
                    img_id = query.lastInsertId()
                    coin.setValue(field_name, img_id)

                    if (field_name == 'obverseimg' and is_obverse_enabled) or \
                       (field_name == 'reverseimg' and is_reverse_enabled):
                        image.loadFromData(img_data)
                        image = image.scaledToHeight(height,
                                                    Qt.SmoothTransformation)

            if not image.isNull():
                ba = QtCore.QByteArray()
                buffer = QtCore.QBuffer(ba)
                buffer.open(QtCore.QIODevice.WriteOnly)
                # Store as PNG for better view
                image.save(buffer, 'png')
                coin.setValue('image', ba)

            if action == 'update_desc':
                dest_model.insertRecord(-1, coin)
                coin_id += 1
                for i in range(coin.count()):
                    if coin.fieldName(i) not in ('id', 'title', 'subjectshort', 'series', 'obversevar'):
                        coin.setNull(i)
                dest_model.insertRecord(-1, coin)
                coin_id += 1
コード例 #55
0
ファイル: main.py プロジェクト: gimu/hitagi-reader.py
 def open_image(self, path):
     """Open specific image via path."""
     image = QImage(str(path))
     if not image.isNull():
         self.model.image_path = path
         self.canvas.update_image(self.settings.getint('Viewport', 'selection'), image)
コード例 #56
0
def exportToMobile(model, params):
    IMAGE_FORMAT = 'jpg'
    IMAGE_COMPRESS = 50
    USED_FIELDS = ('title', 'unit', 'country', 'year', 'mint', 'mintmark',
        'issuedate', 'type', 'series', 'subjectshort', 'material', 'fineness',
        'diameter', 'thickness', 'weight', 'mintage', 'rarity',
        'obverseimg', 'reverseimg', 'subject', 'price1', 'price2', 'price3', 'price4')

    if os.path.isfile(params['file']):
        os.remove(params['file'])

    db = QSqlDatabase.addDatabase('QSQLITE', 'mobile')
    db.setDatabaseName(params['file'])
    if not db.open():
        print(db.lastError().text())
        QMessageBox.critical(None, "Create mobile collection", "Can't open collection")
        return

    sql = """CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US')"""
    QSqlQuery(sql, db)
    sql = """INSERT INTO "android_metadata" VALUES ('en_US')"""
    QSqlQuery(sql, db)

    mobile_settings = {'Version': 1, 'Type': 'MobilePro', 'Filter': params['filter']}

    sql = """CREATE TABLE settings (
        title CHAR NOT NULL UNIQUE,
        value CHAR)"""
    QSqlQuery(sql, db)
    for key, value in mobile_settings.items():
        query = QSqlQuery(db)
        query.prepare("""INSERT INTO settings (title, value)
                VALUES (?, ?)""")
        query.addBindValue(key)
        query.addBindValue(str(value))
        query.exec_()

    sql = """CREATE TABLE updates (
        title CHAR NOT NULL UNIQUE,
        value CHAR)"""
    QSqlQuery(sql, db)

    sql = """INSERT INTO updates (title, value)
                VALUES ('160203', '2016-02-03T10:19:00')"""
    QSqlQuery(sql, db)

    sql = """CREATE TABLE photos (
        id INTEGER PRIMARY KEY,
        image BLOB)"""
    QSqlQuery(sql, db)

    sql = """CREATE TABLE coins (
        id INTEGER PRIMARY KEY,
        description_id INTEGER,
        grade INTEGER,
        createdat STRING)"""
    QSqlQuery(sql, db)

    sql = """CREATE INDEX coins_descriptions ON coins(description_id)"""
    QSqlQuery(sql, db)

    sqlFields = []
    fields = CollectionFieldsBase()
    for field in fields:
        if field.name == 'id':
            sqlFields.append('id INTEGER PRIMARY KEY')
        elif field.name == 'image':
            sqlFields.append('image INTEGER')
        elif field.name in USED_FIELDS:
            sqlFields.append("%s %s" % (field.name, Type.toSql(field.type)))

    sql = "CREATE TABLE descriptions (" + ", ".join(sqlFields) + ")"
    QSqlQuery(sql, db)

    while model.canFetchMore():
        model.fetchMore()

    dest_model = QSqlTableModel(None, db)
    dest_model.setEditStrategy(QSqlTableModel.OnManualSubmit)
    dest_model.setTable('descriptions')
    dest_model.select()

    height = 64
    if params['density'] == 'HDPI':
        height *= 1.5
    elif params['density'] == 'XHDPI':
        height *= 2
    elif params['density'] == 'XXHDPI':
        height *= 3
    elif params['density'] == 'XXXHDPI':
        height *= 4
    maxHeight = height * 4

    is_obverse_enabled = params['image'] in (ExportDialog.IMAGE_OBVERSE, ExportDialog.IMAGE_BOTH)
    is_reverse_enabled = params['image'] in (ExportDialog.IMAGE_REVERSE, ExportDialog.IMAGE_BOTH)

    fields = CollectionFieldsBase()
    count = model.rowCount()
    progressDlg = Gui.ProgressDialog("Exporting records",
                                    "Cancel", count, None)

    for i in range(count):
        progressDlg.step()
        if progressDlg.wasCanceled():
            break

        coin = model.record(i)
        if coin.value('status') in ('pass', 'sold'):
            continue

        dest_record = dest_model.record()

        for field in fields:
            if field.name in ('id', 'image', 'obverseimg', 'reverseimg'):
                continue
            if field.name in USED_FIELDS:
                val = coin.value(field.name)
                if val is None or val == '':
                    continue

                dest_record.setValue(field.name, val)

        # Process images
        is_obverse_present = not coin.isNull('obverseimg')
        is_reverse_present = not coin.isNull('reverseimg')
        if is_obverse_present or is_reverse_present:
            obverseImage = QImage()
            reverseImage = QImage()

            if is_obverse_present:
                ba = QtCore.QByteArray()
                buffer = QtCore.QBuffer(ba)
                buffer.open(QtCore.QIODevice.WriteOnly)

                obverseImage.loadFromData(coin.value('obverseimg'))
                if not obverseImage.isNull() and not params['fullimage'] and obverseImage.height() > maxHeight:
                    scaledImage = obverseImage.scaled(maxHeight, maxHeight,
                            Qt.KeepAspectRatio, Qt.SmoothTransformation)
                    scaledImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS)
                    save_data = ba
                else:
                    if not obverseImage.isNull():
                        obverseImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS)
                        save_data = ba
                    else:
                        save_data = coin.value('obverseimg')

                query = QSqlQuery(db)
                query.prepare("""INSERT INTO photos (image)
                        VALUES (?)""")
                query.addBindValue(save_data)
                query.exec_()
                img_id = query.lastInsertId()
                dest_record.setValue('obverseimg', img_id)
            if not obverseImage.isNull():
                obverseImage = obverseImage.scaledToHeight(height,
                                                        Qt.SmoothTransformation)

            if is_reverse_present:
                ba = QtCore.QByteArray()
                buffer = QtCore.QBuffer(ba)
                buffer.open(QtCore.QIODevice.WriteOnly)

                reverseImage.loadFromData(coin.value('reverseimg'))
                if not reverseImage.isNull() and not params['fullimage'] and reverseImage.height() > maxHeight:
                    scaledImage = reverseImage.scaled(maxHeight, maxHeight,
                            Qt.KeepAspectRatio, Qt.SmoothTransformation)
                    scaledImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS)
                    save_data = ba
                else:
                    if not reverseImage.isNull():
                        reverseImage.save(buffer, IMAGE_FORMAT, IMAGE_COMPRESS)
                        save_data = ba
                    else:
                        save_data = coin.value('reverseimg')

                query = QSqlQuery(db)
                query.prepare("""INSERT INTO photos (image)
                        VALUES (?)""")
                query.addBindValue(save_data)
                query.exec_()
                img_id = query.lastInsertId()
                dest_record.setValue('reverseimg', img_id)
            if not reverseImage.isNull():
                reverseImage = reverseImage.scaledToHeight(height,
                                                    Qt.SmoothTransformation)

            if not is_obverse_enabled:
                obverseImage = QImage()
            if not is_reverse_enabled:
                reverseImage = QImage()

            image = QImage(obverseImage.width() + reverseImage.width(),
                                 height, QImage.Format_RGB32)
            image.fill(QColor(Qt.white).rgb())

            paint = QPainter(image)
            if is_obverse_present and is_obverse_enabled:
                paint.drawImage(QtCore.QRectF(0, 0, obverseImage.width(), height), obverseImage,
                                QtCore.QRectF(0, 0, obverseImage.width(), height))
            if is_reverse_present and is_reverse_enabled:
                paint.drawImage(QtCore.QRectF(obverseImage.width(), 0, reverseImage.width(), height), reverseImage,
                                QtCore.QRectF(0, 0, reverseImage.width(), height))
            paint.end()

            ba = QtCore.QByteArray()
            buffer = QtCore.QBuffer(ba)
            buffer.open(QtCore.QIODevice.WriteOnly)
            image.save(buffer, IMAGE_FORMAT, 75)

            query = QSqlQuery(db)
            query.prepare("""INSERT INTO photos (image)
                    VALUES (?)""")
            query.addBindValue(ba)
            query.exec_()
            img_id = query.lastInsertId()
            dest_record.setValue('image', img_id)

        dest_model.insertRecord(-1, dest_record)

    progressDlg.setLabelText("Saving...")
    dest_model.submitAll()

    progressDlg.setLabelText("Compact...")
    QSqlQuery("""UPDATE descriptions
SET
reverseimg = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.reverseimg = t1.id where t1.id <> t2.id and t3.id = descriptions.id)
WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.reverseimg = t1.id where t1.id <> t2.id)
""", db)
    QSqlQuery("""UPDATE descriptions
SET
obverseimg = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.obverseimg = t1.id where t1.id <> t2.id and t3.id = descriptions.id)
WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.obverseimg = t1.id where t1.id <> t2.id)
""", db)
    QSqlQuery("""UPDATE descriptions
SET
image = (select t2.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.image = t1.id where t1.id <> t2.id and t3.id = descriptions.id)
WHERE descriptions.id in (select t3.id from descriptions t3 join (select id, image from photos group by image having count(*) > 1) t2 on t1.image = t2.image join photos t1 on t3.image = t1.id where t1.id <> t2.id)
""", db)

    QSqlQuery("""DELETE FROM photos
        WHERE id NOT IN (SELECT id FROM photos GROUP BY image)""", db)

    db.close()

    progressDlg.setLabelText("Vacuum...")
    db = QSqlDatabase.addDatabase('QSQLITE', 'mobile')
    db.setDatabaseName(params['file'])
    if not db.open():
        print(db.lastError().text())
        QMessageBox.critical(None, "Create mobile collection", "Can't open collection")
        return
    QSqlQuery("VACUUM", db)
    db.close()

    progressDlg.reset()
コード例 #57
0
ファイル: ImageReader.py プロジェクト: TinkerGnome/Cura
    def _generateSceneNode(self, file_name, xz_size, peak_height, base_height, blur_iterations, max_size, image_color_invert):
        scene_node = SceneNode()

        mesh = MeshBuilder()

        img = QImage(file_name)

        if img.isNull():
            Logger.log("e", "Image is corrupt.")
            return None

        width = max(img.width(), 2)
        height = max(img.height(), 2)
        aspect = height / width

        if img.width() < 2 or img.height() < 2:
            img = img.scaled(width, height, Qt.IgnoreAspectRatio)

        base_height = max(base_height, 0)
        peak_height = max(peak_height, -base_height)

        xz_size = max(xz_size, 1)
        scale_vector = Vector(xz_size, peak_height, xz_size)

        if width > height:
            scale_vector = scale_vector.set(z=scale_vector.z * aspect)
        elif height > width:
            scale_vector = scale_vector.set(x=scale_vector.x / aspect)

        if width > max_size or height > max_size:
            scale_factor = max_size / width
            if height > width:
                scale_factor = max_size / height

            width = int(max(round(width * scale_factor), 2))
            height = int(max(round(height * scale_factor), 2))
            img = img.scaled(width, height, Qt.IgnoreAspectRatio)

        width_minus_one = width - 1
        height_minus_one = height - 1

        Job.yieldThread()

        texel_width = 1.0 / (width_minus_one) * scale_vector.x
        texel_height = 1.0 / (height_minus_one) * scale_vector.z

        height_data = numpy.zeros((height, width), dtype=numpy.float32)

        for x in range(0, width):
            for y in range(0, height):
                qrgb = img.pixel(x, y)
                avg = float(qRed(qrgb) + qGreen(qrgb) + qBlue(qrgb)) / (3 * 255)
                height_data[y, x] = avg

        Job.yieldThread()

        if image_color_invert:
            height_data = 1 - height_data

        for _ in range(0, blur_iterations):
            copy = numpy.pad(height_data, ((1, 1), (1, 1)), mode= "edge")

            height_data += copy[1:-1, 2:]
            height_data += copy[1:-1, :-2]
            height_data += copy[2:, 1:-1]
            height_data += copy[:-2, 1:-1]

            height_data += copy[2:, 2:]
            height_data += copy[:-2, 2:]
            height_data += copy[2:, :-2]
            height_data += copy[:-2, :-2]

            height_data /= 9

            Job.yieldThread()

        height_data *= scale_vector.y
        height_data += base_height

        heightmap_face_count = 2 * height_minus_one * width_minus_one
        total_face_count = heightmap_face_count + (width_minus_one * 2) * (height_minus_one * 2) + 2

        mesh.reserveFaceCount(total_face_count)

        # initialize to texel space vertex offsets.
        # 6 is for 6 vertices for each texel quad.
        heightmap_vertices = numpy.zeros((width_minus_one * height_minus_one, 6, 3), dtype = numpy.float32)
        heightmap_vertices = heightmap_vertices + numpy.array([[
            [0, base_height, 0],
            [0, base_height, texel_height],
            [texel_width, base_height, texel_height],
            [texel_width, base_height, texel_height],
            [texel_width, base_height, 0],
            [0, base_height, 0]
        ]], dtype = numpy.float32)

        offsetsz, offsetsx = numpy.mgrid[0: height_minus_one, 0: width - 1]
        offsetsx = numpy.array(offsetsx, numpy.float32).reshape(-1, 1) * texel_width
        offsetsz = numpy.array(offsetsz, numpy.float32).reshape(-1, 1) * texel_height

        # offsets for each texel quad
        heightmap_vertex_offsets = numpy.concatenate([offsetsx, numpy.zeros((offsetsx.shape[0], offsetsx.shape[1]), dtype=numpy.float32), offsetsz], 1)
        heightmap_vertices += heightmap_vertex_offsets.repeat(6, 0).reshape(-1, 6, 3)

        # apply height data to y values
        heightmap_vertices[:, 0, 1] = heightmap_vertices[:, 5, 1] = height_data[:-1, :-1].reshape(-1)
        heightmap_vertices[:, 1, 1] = height_data[1:, :-1].reshape(-1)
        heightmap_vertices[:, 2, 1] = heightmap_vertices[:, 3, 1] = height_data[1:, 1:].reshape(-1)
        heightmap_vertices[:, 4, 1] = height_data[:-1, 1:].reshape(-1)

        heightmap_indices = numpy.array(numpy.mgrid[0:heightmap_face_count * 3], dtype=numpy.int32).reshape(-1, 3)

        mesh._vertices[0:(heightmap_vertices.size // 3), :] = heightmap_vertices.reshape(-1, 3)
        mesh._indices[0:(heightmap_indices.size // 3), :] = heightmap_indices

        mesh._vertex_count = heightmap_vertices.size // 3
        mesh._face_count = heightmap_indices.size // 3

        geo_width = width_minus_one * texel_width
        geo_height = height_minus_one * texel_height

        # bottom
        mesh.addFaceByPoints(0, 0, 0, 0, 0, geo_height, geo_width, 0, geo_height)
        mesh.addFaceByPoints(geo_width, 0, geo_height, geo_width, 0, 0, 0, 0, 0)

        # north and south walls
        for n in range(0, width_minus_one):
            x = n * texel_width
            nx = (n + 1) * texel_width

            hn0 = height_data[0, n]
            hn1 = height_data[0, n + 1]

            hs0 = height_data[height_minus_one, n]
            hs1 = height_data[height_minus_one, n + 1]

            mesh.addFaceByPoints(x, 0, 0, nx, 0, 0, nx, hn1, 0)
            mesh.addFaceByPoints(nx, hn1, 0, x, hn0, 0, x, 0, 0)

            mesh.addFaceByPoints(x, 0, geo_height, nx, 0, geo_height, nx, hs1, geo_height)
            mesh.addFaceByPoints(nx, hs1, geo_height, x, hs0, geo_height, x, 0, geo_height)

        # west and east walls
        for n in range(0, height_minus_one):
            y = n * texel_height
            ny = (n + 1) * texel_height

            hw0 = height_data[n, 0]
            hw1 = height_data[n + 1, 0]

            he0 = height_data[n, width_minus_one]
            he1 = height_data[n + 1, width_minus_one]

            mesh.addFaceByPoints(0, 0, y, 0, 0, ny, 0, hw1, ny)
            mesh.addFaceByPoints(0, hw1, ny, 0, hw0, y, 0, 0, y)

            mesh.addFaceByPoints(geo_width, 0, y, geo_width, 0, ny, geo_width, he1, ny)
            mesh.addFaceByPoints(geo_width, he1, ny, geo_width, he0, y, geo_width, 0, y)

        mesh.calculateNormals(fast=True)

        scene_node.setMeshData(mesh.build())

        return scene_node
コード例 #58
0
ファイル: imageview.py プロジェクト: B-Rich/PPQT2
class ImageDisplay(QWidget):
    def __init__(self, my_book, parent=None):
        super().__init__(parent)
        self.my_book = my_book
        # register metadata readers and writers
        md = my_book.get_meta_manager()
        md.register(C.MD_IZ,self._zoom_read,self._zoom_write)
        md.register(C.MD_IX,self._link_read,self._link_write)
        # Create our widgets including cursor_to_image and
        # image_to_cursor pushbuttons.
        self._uic()
        # set defaults in case no metadata
        self.cursor_to_image.setChecked(True)
        self.image_to_cursor.setChecked(False)
        self.zoom_factor = 0.25
        self.png_path = None
        # disable all widgetry until we get some metadata
        self._disable()
        # end of __init__()

    # Disable our widgets because we have no image to show.
    def _disable(self):
        self.no_image = True
        self.last_index = None # compares unequal to any
        self.pix_map = QPixmap()
        self.image = QImage()
        self.cursor_to_image.setEnabled(False)
        self.image_to_cursor.setEnabled(False)
        self.zoom_pct.setEnabled(False)
        self.zoom_to_width.setEnabled(False)
        self.zoom_to_height.setEnabled(False)
        self.image_display.setPixmap(self.gray_image)
        self.image_display.setToolTip(
            _TR('Image view tooltip',
                'Display of one scanned page (no images available)')
            )

    # Enable our widgets, we have images to show. At this time the Book
    # has definitely created an edit view and a page model.
    def _enable(self):
        self.edit_view = self.my_book.get_edit_view()
        self.editor = self.edit_view.Editor # access to actual QTextEdit
        self.page_data = self.my_book.get_page_model()
        self.cursor_to_image.setEnabled(True)
        self.image_to_cursor.setEnabled(True)
        self.zoom_to_width.setEnabled(True)
        self.zoom_to_height.setEnabled(True)
        self.image_display.setToolTip(
            _TR('Image view tooltip',
                'Display of one scanned page from the book')
            )
        self.no_image = False
        self.zoom_pct.setEnabled(True)
        # the following triggers entry to _new_zoom_pct() below
        self.zoom_pct.setValue(int(100*self.zoom_factor))

    # Metadata: read or write the {{IMAGEZOOM f}} section.
    # Parameter f should be a decimal number between 0.15 and 2.0
    # but we do not depend on text the user could edit.
    def _zoom_read(self, qts, section, vers, parm):
        try:
            z = float(parm) # throws exception on a bad literal
            if math.isnan(z) or (z < 0.15) or (z > 2.0) :
                raise ValueError
            self.zoom_factor = z
        except:
            imageview_logger.error('Invalid IMAGEZOOM "{0}" ignored'.format(parm))

    def _zoom_write(self, qts, section):
        qts << metadata.open_line(section, str(self.zoom_factor))

    # Metadata: read or write the {{IMAGELINK b}} section. The parameter should
    # be an int 0/1/2/3. Bit 0 represents the state of cursor_to_image
    # (usually 1); bit 1 represents the state of image_to_cursor (usually 0).
    def _link_read(self, qts, section, vers, parm):
        try:
            b = int(parm) # exception on a bad literal
            if (b < 0) or (b > 3) : raise ValueError
            self.cursor_to_image.setChecked( True if b & 1 else False )
            self.image_to_cursor.setChecked( True if b & 2 else False )
        except :
            imageview_logger.error('Invalid IMAGELINKING "{0}" ignored'.format(parm))

    def _link_write(self, qts, section):
        b = 0
        if self.cursor_to_image.isChecked() : b |= 1
        if self.image_to_cursor.isChecked() : b |= 2
        qts << metadata.open_line(section, str(b))

    # The Book calls here after it has loaded a book with defined page data,
    # passing the path to the folder containing the book. If we can find a
    # folder named 'pngs' in it we record that path and enable our widgets,
    # and fake a cursorMoved signal to display the current edit page.
    def set_path(self,book_folder_path):
        book_dir = QDir(book_folder_path)
        if book_dir.exists('pngs') :
            self.png_dir = QDir(book_dir.absoluteFilePath('pngs'))
            self._enable()
            self.cursor_move()

    # Come here to display or re-display an image. The last-displayed
    # page image index (if any) is in self.last_index. The desired page
    # index is passed as the argument, which may be:
    # * the same as last_index, for example on a change of zoom%. Just
    #   redisplay the current page.
    # * negative or None if the cursor is "above" the first available page or on
    #   a Page-Up keystroke. Display the gray image.
    # * greater than page_data.page_count() on a Page-Down keystroke,
    #   display the last available page.
    # If different from last_index, try to load the .png file for that
    # page. If that fails, use the gray image. Otherwise display that
    # page and save it as last_index.

    def _show_page(self, page_index):
        if page_index != self.last_index :
            self.last_index = page_index
            # change of page, see if we have a filename for it
            self.pix_map = self.gray_image # assume failure...
            im_name = self.page_data.filename(page_index)
            if im_name :
                # pagedata has a filename; of course there is no guarantee
                # such a file exists now or ever did.
                im_name += '.png'
                if self.png_dir.exists(im_name) :
                    self.image = QImage(self.png_dir.absoluteFilePath(im_name))
                    if not self.image.isNull():
                        # we loaded it ok, make a full-scale pixmap for display
                        self.pix_map = QPixmap.fromImage(self.image,Qt.ColorOnly)
        # Whether new page or not, rescale to current zoom. The .resize method
        # takes a QSize; pix_map.size() returns one, and it supports * by a real.
        self.image_display.setPixmap(self.pix_map)
        self.image_display.resize( self.zoom_factor * self.pix_map.size() )

    # Slot to receive the cursorMoved signal from the editview widget. If we
    # are in no_image state, do nothing. If the cursor_to_image switch is
    # not checked, do nothing. Else get the character position of
    # the high-end of the current edit selection, and use that to get the
    # current page index from pagedata, and pass that to _show_page.
    def cursor_move(self):
        if self.no_image : return
        if self.cursor_to_image.isChecked() :
            pos = self.editor.textCursor().selectionEnd()
            self._show_page( self.page_data.page_index(pos) )

    # Slots to receive the signals from our zoom percent and zoom-to buttons.
    # The controls are disabled while we are in no_image state, so if a signal
    # arrives, we are not in that state.
    #
    # These are strictly internal hence _names.

    # Any change in the value of the zoom % spin-box including setValue().
    def _new_zoom_pct(self,new_value):
        self.zoom_factor = self.zoom_pct.value() / 100
        self._show_page(self.last_index)

    # Set a new zoom factor (a real) and update the zoom pct spinbox.
    # Setting zoom_pct triggers a signal to _new_zoom_pct above, and
    # thence to _show_page which repaints the page at the new scale value.
    def _set_zoom_real(self,new_value):
        zoom = max(new_value, ZOOM_FACTOR_MIN)
        zoom = min(zoom, ZOOM_FACTOR_MAX)
        self.zoom_factor = zoom
        self.zoom_pct.setValue(int(100*zoom))

    # Re-implement keyPressEvent in order to provide zoom and page up/down.
    #   ctrl-plus increases the image size by 1.25
    #   ctrl-minus decreases the image size by 0.8
    #   page-up displays the next-higher page
    #   page-down displays the next-lower page

    def keyPressEvent(self, event):
        # assume we will not handle this key and clear its accepted flag
        event.ignore()
        if self.no_image or (self.last_index is None) :
            return # ignore keys until we are showing some image
        # We have images to show, check the key value.
        modkey = int( int(event.key() | (int(event.modifiers()) & C.KEYPAD_MOD_CLEAR)) )
        if modkey in C.KEYS_ZOOM :
            event.accept()
            fac = (0.8) if (modkey == C.CTL_MINUS) else (1.25)
            self._set_zoom_real( fac * self.zoom_factor)
        elif (event.key() == Qt.Key_PageUp) or (event.key() == Qt.Key_PageDown) :
            event.accept()
            pgix = self.last_index + (1 if (event.key() == Qt.Key_PageDown) else -1)
            # If not paging off either end, show that page
            if pgix >= 0 and pgix < self.page_data.page_count() :
                self._show_page(pgix)
                if self.image_to_cursor.isChecked():
                    self.edit_view.show_position(self.page_data.position(pgix))

    # Zoom to width and zoom to height are basically the same thing:
    # 1. Using the QImage of the current page in self.image,
    #    scan its pixels to find the width (height) of the nonwhite area.
    # 2. Get the ratio of that to our image label's viewport width (height).
    # 3. Set that ratio as the zoom factor and redraw the image.
    # 5. Set the scroll position(s) of our scroll area to left-justify the text.
    #
    # We get access to the pixel data using QImage.bits() which gives us a
    # "sip.voidptr" object that we can index to get byte values.
    def _zoom_to_width(self):

        # Generic loop to scan inward from the left or right edge of one
        # column inward until a dark pixel is seen, returning that margin.
        def inner_loop(row_range, col_start, margin, col_step):
            pa, pb = 255, 255 # virtual white outside column
            for row in row_range:
                for col in range(col_start, margin, col_step):
                    pc = color_table[ bytes_ptr[row+col] ]
                    if (pa + pb + pc) < 24 : # black or dark gray trio
                        margin = col # new, narrower, margin
                        break # no need to look further on this row
                    pa, pb = pb, pc # else shift 3-pixel window
            return margin - (2*col_step) # allow for 3-px window

        if self.no_image or self.image.isNull() :
            return # nothing to do
        scale_factor = 4
        orig_rows = self.image.height() # number of pixels high
        orig_cols = self.image.width() # number of logical pixels across
        # Scale the image to 1/4 size (1/16 the pixel count) and then force
        # it to indexed-8 format, one byte per pixel.
        work_image = self.image.scaled(
            QSize(int(orig_cols/scale_factor),int(orig_rows/scale_factor)),
            Qt.KeepAspectRatio, Qt.FastTransformation)
        work_image = work_image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
        # Get a reduced version of the color table by extracting just the GG
        # values of each entry, as a dict keyed by the pixel byte value. For
        # PNG-2, this gives [0,255] but it could have 8, 16, even 256 elements.
        color_table = { bytes([c]): int((work_image.color(c) >> 8) & 255)
                         for c in range(work_image.colorCount()) }
        # Establish limits for the inner loop
        rows = work_image.height() # number of pixels high
        cols = work_image.width() # number of logical pixels across
        stride = (cols + 3) & (-4) # scan-line width in bytes
        bytes_ptr = work_image.bits() # uchar * a_bunch_o_pixels
        bytes_ptr.setsize(stride * rows) # make the pointer indexable

        # Scan in from left and from right to find the outermost dark spots.
        # Pages tend to start with many lines of white pixels so in hopes of
        # establishing a narrow margin quickly, scan from the middle to the
        # end, then do the top half.
        left_margin = inner_loop(
                        range(int(rows/2)*stride, (rows-1)*stride, stride*2),
                        0, int(cols/2), 1
        )
        left_margin = inner_loop(
                        range(0, int(rows/2)*stride, stride*2),
                        0, left_margin, 1
                        )
        # Now do exactly the same but for the right margin.
        right_margin = inner_loop(
                        range(int(rows/2)*stride, (rows-1)*stride, stride*2),
                        cols-1, int(cols/2), -1
                        )
        right_margin = inner_loop(
                        range(0, int(rows/2)*stride, stride*2),
                        cols-1, right_margin, -1
                        )
        # Adjust the margins by the scale factor to fit the full size image.
        #left_margin = max(0,left_margin*scale_factor-scale_factor)
        #right_margin = min(orig_cols,right_margin*scale_factor+scale_factor)
        left_margin = left_margin*scale_factor
        right_margin = right_margin*scale_factor
        text_size = right_margin - left_margin + 2
        port_width = self.scroll_area.viewport().width()
        # Set the new zoom factor, after limiting by min/max values
        self._set_zoom_real(port_width/text_size)
        # Set the scrollbar to show the page from its left margin.
        self.scroll_area.horizontalScrollBar().setValue(
                             int( left_margin * self.zoom_factor)
                         )
        # and that completes zoom-to-width

    def _zoom_to_height(self):
        def dark_row(row_start, cols):
            '''
            Scan one row of pixels and return True if it contains
            at least one 3-pixel blob of darkness, or False if not.
            '''
            pa, pb = 255, 255
            for c in range(row_start,row_start+cols):
                pc = color_table[ bytes_ptr[c] ]
                if (pa + pb + pc) < 24 : # black or dark gray trio
                    return True
                pa, pb = pb, pc
            return False # row was all-white-ish

        if self.no_image or self.image.isNull() :
            return # nothing to do
        scale_factor = 4
        orig_rows = self.image.height() # number of pixels high
        orig_cols = self.image.width() # number of logical pixels across
        # Scale the image to 1/4 size (1/16 the pixel count) and then force
        # it to indexed-8 format, one byte per pixel.
        work_image = self.image.scaled(
            QSize(int(orig_cols/scale_factor),int(orig_rows/scale_factor)),
            Qt.KeepAspectRatio, Qt.FastTransformation)
        work_image = work_image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
        # Get a reduced version of the color table by extracting just the GG
        # values of each entry, as a dict keyed by the pixel byte value. For
        # PNG-2, this gives [0,255] but it could have 8, 16, even 256 elements.
        color_table = { bytes([c]): int((work_image.color(c) >> 8) & 255)
                         for c in range(work_image.colorCount()) }
        rows = work_image.height() # number of pixels high
        cols = work_image.width() # number of logical pixels across
        stride = (cols + 3) & (-4) # scan-line width in bytes
        bytes_ptr = work_image.bits() # uchar * a_bunch_o_pixels
        bytes_ptr.setsize(stride * rows) # make the pointer indexable
        # Scan the image rows from the top down looking for one with darkness
        for top_row in range(rows):
            if dark_row(top_row*stride, cols): break
        if top_row > (rows/2) : # too much white, skip it
            return
        for bottom_row in range(rows-1, top_row, -1):
            if dark_row(bottom_row*stride, cols) : break
        # bottom_row has to be >= top_row. if they are too close together
        # set_zoom_real will limit the zoom to 200%.
        top_row = top_row*scale_factor
        bottom_row = bottom_row*scale_factor
        text_height = bottom_row - top_row + 1
        port_height = self.scroll_area.viewport().height()
        self._set_zoom_real(port_height/text_height)
        self.scroll_area.verticalScrollBar().setValue(
                         int( top_row * self.zoom_factor ) )
        # and that completes zoom-to-height

    # Build the widgetary contents. The widget consists mostly of a vertical
    # layout with two items: A scrollArea containing a QLabel used to display
    # an image, and a horizontal layout containing the zoom controls.
    # TODO: figure out design and location of two cursor-link tool buttons.
    def _uic(self):

        # Function to return the actual width of the label text
        # of a widget. Get the fontMetrics and ask it for the width.
        def _label_width(widget):
            fm = widget.fontMetrics()
            return fm.width(widget.text())

        # Create a gray field to use when no image is available
        self.gray_image = QPixmap(700,900)
        self.gray_image.fill(QColor("gray"))

        # Build the QLabel that displays the image pixmap. It gets all
        # available space and scales its contents to fit that space.
        self.image_display = QLabel()
        self.image_display.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.image_display.setScaledContents(True)

        # Create a scroll area within which to display the image. It will
        # create a horizontal and/or vertical scroll bar when
        # the image_display size exceeds the size of the scroll area.
        self.scroll_area = QScrollArea()
        self.scroll_area.setBackgroundRole(QPalette.Dark)
        self.scroll_area.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
        self.scroll_area.setWidget(self.image_display)
        # Make sure the scroll area does not swallow user keystrokes
        self.setFocusPolicy(Qt.ClickFocus) # focus into whole widget
        self.scroll_area.setFocusProxy(self) # you, pass it on.

        # Create the image-linking toolbuttons.
        # Cursor-to-image uses left-hands.
        c2i_on = QPixmap(':/hand-left-closed.png')
        c2i_off = QPixmap(':/hand-left-open.png')
        c2i_con = QIcon()
        c2i_con.addPixmap(c2i_on,QIcon.Normal,QIcon.On)
        c2i_con.addPixmap(c2i_off,QIcon.Normal,QIcon.Off)
        self.cursor_to_image = QToolButton()
        self.cursor_to_image.setCheckable(True)
        self.cursor_to_image.setContentsMargins(0,0,0,0)
        self.cursor_to_image.setIconSize(QSize(30,24))
        self.cursor_to_image.setMaximumSize(QSize(32,26))
        self.cursor_to_image.setIcon(c2i_con)
        # Image-to-cursor uses right-hands.
        i2c_on = QPixmap(':/hand-right-closed.png')
        i2c_off = QPixmap(':/hand-right-open.png')
        i2c_con = QIcon()
        i2c_con.addPixmap(i2c_on,QIcon.Normal,QIcon.On)
        i2c_con.addPixmap(i2c_off,QIcon.Normal,QIcon.Off)
        self.image_to_cursor = QToolButton()
        self.image_to_cursor.setCheckable(True)
        self.image_to_cursor.setContentsMargins(0,0,0,0)
        self.image_to_cursor.setIconSize(QSize(30,24))
        self.image_to_cursor.setMaximumSize(QSize(32,26))
        self.image_to_cursor.setIcon(i2c_con)

        # Create a spinbox to set the zoom from 15 to 200 and connect its
        # signal to our slot.
        self.zoom_pct = QSpinBox()
        self.zoom_pct.setRange(
            int(100*ZOOM_FACTOR_MIN),int(100*ZOOM_FACTOR_MAX))
        self.zoom_pct.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Set the magnification of the page image')
            )
        # Connect the valueChanged(int) signal as opposed to the
        # valueChanged(str) signal.
        self.zoom_pct.valueChanged['int'].connect(self._new_zoom_pct)
        # Create a label for the zoom spinbox. (the label is not saved as a
        # class member, its layout will keep it in focus) Not translating
        # the word "Zoom".
        pct_label = QLabel(
            '&Zoom {0}-{1}%'.format(
                str(self.zoom_pct.minimum() ),
                str(self.zoom_pct.maximum() )
                )
            )
        pct_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        pct_label.setBuddy(self.zoom_pct)

        # Create the to-width and to-height zoom buttons. Make
        # sure their widths are equal after translation.
        self.zoom_to_width = QPushButton(
            _TR('Imageview zoom control button name','to Width')
            )
        self.zoom_to_width.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Adjust the image to fill the window side to side.')
            )
        self.zoom_to_width.clicked.connect(self._zoom_to_width)
        self.zoom_to_height = QPushButton(
            _TR('Imageview zoom control button name','to Height')
            )
        self.zoom_to_height.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Adjust the image to fill the window top to bottom.')
            )
        self.zoom_to_height.clicked.connect(self._zoom_to_height)

        w = 20 + max(_label_width(self.zoom_to_height),_label_width(self.zoom_to_width))
        self.zoom_to_height.setMinimumWidth(w)
        self.zoom_to_width.setMinimumWidth(w)

        # Create an HBox for the top of the panel which contains only
        # the cursor-to-image link button.
        tophbox = QHBoxLayout()
        tophbox.setContentsMargins(0,0,0,0)
        tophbox.addWidget(self.cursor_to_image,0)
        tophbox.addStretch() # left-align the button
        # Create an HBox layout to contain the above controls, using
        # spacers left and right to center them and a spacers between
        # to control the spacing.

        zhbox = QHBoxLayout()
        zhbox.setContentsMargins(0,0,0,0)
        zhbox.addWidget(self.image_to_cursor,0)
        zhbox.addStretch(2) # left and right spacers have stretch 2
        zhbox.addWidget(pct_label,0)
        zhbox.addWidget(self.zoom_pct,0)
        zhbox.addStretch(1) # spacers between widgets are stretch 1
        zhbox.addWidget(self.zoom_to_height,0)
        zhbox.addSpacing(10) # juuuust a little space between buttons
        zhbox.addWidget(self.zoom_to_width,0)
        zhbox.addStretch(2) # right side spacer

        # With all the pieces in hand, create our layout with a stack of
        # image over row of controls.
        vbox = QVBoxLayout()
        vbox.setContentsMargins(0,0,0,0)
        vbox.addLayout(tophbox,0)
        # The image gets a high stretch and default alignment.
        vbox.addWidget(self.scroll_area,2)
        vbox.addLayout(zhbox,0)
        self.setLayout(vbox)
        # And that completes the UI setup.
コード例 #59
0
ファイル: separations.py プロジェクト: death-finger/Scripts
class Viewer(QMainWindow):
    # Brightness.
    Gloom, Quarter, Half, ThreeQuarters, Full = range(5)

    # Brightness value map.
    brightnessValueMap = {
        Gloom: 0,
        Quarter: 64,
        Half: 128,
        ThreeQuarters: 191,
        Full: 255,
    }

    def __init__(self):
        """ Constructor initializes a default value for the brightness, creates
            the main menu entries, and constructs a central widget that contains
            enough space for images to be displayed.
        """
        super(Viewer, self).__init__()

        self.scaledImage = QImage()
        self.menuMap = {}
        self.path = ''
        self.brightness = 255

        self.setWindowTitle("QImage Color Separations")

        self.createMenus()
        self.setCentralWidget(self.createCentralWidget())

    def createMenus(self):
        """ Creates a main menu with two entries: a File menu, to allow the image
            to be selected, and a Brightness menu to allow the brightness of the
            separations to be changed.
            Initially, the Brightness menu items are disabled, but the first entry in
            the menu is checked to reflect the default brightness.
        """
        self.fileMenu = QMenu("&File", self)
        self.brightnessMenu = QMenu("&Brightness", self)

        self.openAction = self.fileMenu.addAction("&Open...")
        self.openAction.setShortcut(QKeySequence('Ctrl+O'))
        self.saveAction = self.fileMenu.addAction("&Save...")
        self.saveAction.setShortcut(QKeySequence('Ctrl+S'))
        self.saveAction.setEnabled(False)
        self.quitAction = self.fileMenu.addAction("E&xit")
        self.quitAction.setShortcut(QKeySequence('Ctrl+Q'))

        self.noBrightness = self.brightnessMenu.addAction("&0%")
        self.noBrightness.setCheckable(True)
        self.quarterBrightness = self.brightnessMenu.addAction("&25%")
        self.quarterBrightness.setCheckable(True)
        self.halfBrightness = self.brightnessMenu.addAction("&50%")
        self.halfBrightness.setCheckable(True)
        self.threeQuartersBrightness = self.brightnessMenu.addAction("&75%")
        self.threeQuartersBrightness.setCheckable(True)
        self.fullBrightness = self.brightnessMenu.addAction("&100%")
        self.fullBrightness.setCheckable(True)

        self.menuMap[self.noBrightness] = self.Gloom
        self.menuMap[self.quarterBrightness] = self.Quarter
        self.menuMap[self.halfBrightness] = self.Half
        self.menuMap[self.threeQuartersBrightness] = self.ThreeQuarters
        self.menuMap[self.fullBrightness] = self.Full

        self.currentBrightness = self.fullBrightness
        self.currentBrightness.setChecked(True)
        self.brightnessMenu.setEnabled(False)

        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.brightnessMenu)

        self.openAction.triggered.connect(self.chooseFile)
        self.saveAction.triggered.connect(self.saveImage)
        self.quitAction.triggered.connect(QApplication.instance().quit)
        self.brightnessMenu.triggered.connect(self.setBrightness)

    def createCentralWidget(self):
        """ Constructs a central widget for the window consisting of a two-by-two
            grid of labels, each of which will contain an image. We restrict the
            size of the labels to 256 pixels, and ensure that the window cannot
            be resized.
        """
        frame = QFrame(self)
        grid = QGridLayout(frame)
        grid.setSpacing(8)
        grid.setContentsMargins(4, 4, 4, 4)

        self.layout().setSizeConstraint(QLayout.SetFixedSize)

        labelSize = QSize(256, 256)

        self.finalWidget = FinalWidget(frame, "Final image", labelSize)

        self.cyanWidget = ScreenWidget(frame, Qt.cyan, "Cyan",
                ScreenWidget.Cyan, labelSize)
        self.magentaWidget = ScreenWidget(frame, Qt.magenta, "Magenta",
                ScreenWidget.Magenta, labelSize)
        self.yellowWidget = ScreenWidget(frame, Qt.yellow, "Yellow",
                ScreenWidget.Yellow, labelSize)

        self.cyanWidget.imageChanged.connect(self.createImage)
        self.magentaWidget.imageChanged.connect(self.createImage)
        self.yellowWidget.imageChanged.connect(self.createImage)

        grid.addWidget(self.finalWidget, 0, 0, Qt.AlignTop | Qt.AlignHCenter)
        grid.addWidget(self.cyanWidget, 0, 1, Qt.AlignTop | Qt.AlignHCenter)
        grid.addWidget(self.magentaWidget, 1, 0, Qt.AlignTop | Qt.AlignHCenter)
        grid.addWidget(self.yellowWidget, 1, 1, Qt.AlignTop | Qt.AlignHCenter)

        return frame

    def chooseFile(self):
        """ Provides a dialog window to allow the user to specify an image file.
            If a file is selected, the appropriate function is called to process
            and display it.
        """
        imageFile, _ = QFileDialog.getOpenFileName(self,
                "Choose an image file to open", self.path, "Images (*.*)")

        if imageFile != '':
            self.openImageFile(imageFile)
            self.path = imageFile

    def setBrightness(self, action):
        """ Changes the value of the brightness according to the entry selected in the
            Brightness menu. The selected entry is checked, and the previously selected
            entry is unchecked.
            The color separations are updated to use the new value for the brightness.
        """
        if action not in self.menuMap or self.scaledImage.isNull():
            return

        self.brightness = self.brightnessValueMap.get(self.menuMap[action])
        if self.brightness is None:
            return

        self.currentBrightness.setChecked(False)
        self.currentBrightness = action
        self.currentBrightness.setChecked(True)

        self.createImage()

    def openImageFile(self, imageFile):
        """ Load the image from the file given, and create four pixmaps based
            on the original image.
            The window caption is set, and the Brightness menu enabled if the image file
            can be loaded.
        """
        originalImage = QImage()

        if originalImage.load(imageFile):
            self.setWindowTitle(imageFile)
            self.saveAction.setEnabled(True)
            self.brightnessMenu.setEnabled(True)

            self.scaledImage = originalImage.scaled(256, 256, Qt.KeepAspectRatio)

            self.cyanWidget.setImage(self.scaledImage)
            self.magentaWidget.setImage(self.scaledImage)
            self.yellowWidget.setImage(self.scaledImage)
            self.createImage()
        else:
            QMessageBox.warning(self, "Cannot open file",
                    "The selected file could not be opened.",
                    QMessageBox.Cancel, QMessageBox.NoButton,
                    QMessageBox.NoButton)

    def createImage(self):
        """ Creates an image by combining the contents of the three screens
            to present a page preview.
            The image associated with each screen is separated into cyan,
            magenta, and yellow components. We add up the values for each
            component from the three screen images, and subtract the totals
            from the maximum value for each corresponding primary color.
        """
        newImage = self.scaledImage.copy()

        image1 = self.cyanWidget.image()
        image2 = self.magentaWidget.image()
        image3 = self.yellowWidget.image()
        darkness = 255 - self.brightness

        for y in range(newImage.height()):
            for x in range(newImage.width()):
                # Create three screens, using the quantities of the source CMY
                # components to determine how much of each of the inks are to
                # be put on each screen.
                p1 = image1.pixel(x, y)
                cyan1 = float(255 - qRed(p1))
                magenta1 = float(255 - qGreen(p1))
                yellow1 = float(255 - qBlue(p1))

                p2 = image2.pixel(x, y)
                cyan2 = float(255 - qRed(p2))
                magenta2 = float(255 - qGreen(p2))
                yellow2 = float(255 - qBlue(p2))

                p3 = image3.pixel(x, y)
                cyan3 = float(255 - qRed(p3))
                magenta3 = float(255 - qGreen(p3))
                yellow3 = float(255 - qBlue(p3))

                newColor = QColor(
                    max(255 - int(cyan1 + cyan2 + cyan3) - darkness, 0),
                    max(255 - int(magenta1 + magenta2 + magenta3) - darkness, 0),
                    max(255 - int(yellow1 + yellow2 + yellow3) - darkness, 0))

                newImage.setPixel(x, y, newColor.rgb())

        self.finalWidget.setPixmap(QPixmap.fromImage(newImage))

    def saveImage(self):
        """ Provides a dialog window to allow the user to save the image file.
        """
        imageFile, _ = QFileDialog.getSaveFileName(self,
                "Choose a filename to save the image", "", "Images (*.png)")

        info = QFileInfo(imageFile)

        if info.baseName() != '':
            newImageFile = QFileInfo(info.absoluteDir(),
                    info.baseName() + '.png').absoluteFilePath()

            if not self.finalWidget.pixmap().save(newImageFile, 'PNG'):
                QMessageBox.warning(self, "Cannot save file",
                        "The file could not be saved.",
                        QMessageBox.Cancel, QMessageBox.NoButton,
                        QMessageBox.NoButton)
        else:
            QMessageBox.warning(self, "Cannot save file",
                    "Please enter a valid filename.", QMessageBox.Cancel,
                    QMessageBox.NoButton, QMessageBox.NoButton)