Ejemplo n.º 1
0
    def __init__(self, data, size, palette):
        if not data:
            # dummy image
            self.pixbuf = Pixbuf.new(Colorspace.RGB, False, 8,
                                     size[0] * 8 * 2, size[1] * 8 * 2)
            self.pixbuf.fill(0xAAAAAAFF)
            return

        # slice into blocks
        blocks = cut(data, BLOCK)
        # slice block content
        blocks = [cut(b, ROW) for b in blocks]
        # rearrange into blockrows (y/x coordinates)
        blocks = cut(blocks, size[0])

        bytestring = []
        # for each block row
        for y in range(0, size[1]):
            # for each final row
            for i in range(0, int(BLOCK / ROW)):
                # for each block column
                for x in range(0, size[0]):
                    r = blocks[y][x][i]
                    # extract pixels from rows
                    for j in range(4):
                        bytestring.append(r[j] & 0x0F)  # first  (....AAAA)
                        bytestring.append(r[j] >> 4)    # second (BBBB....)

        # apply palette
        result = []
        for i in bytestring:
            result += palette.colors[i]

        # get result in binary format
        result = b''+bytearray(result)

        # create image
        self.pixbuf = Pixbuf.new_from_data(
            result, 0, False, 8,
            8 * size[0], 8 * size[1], 8 * size[0] * 3, None, None)
        self.pixbuf = self.pixbuf.scale_simple(
            8 * size[0] * 2, 8 * size[1] * 2, InterpType.NEAREST)
Ejemplo n.º 2
0
    def mask_pixbuf(self, pb, width, height):
        """
        Mask the pixbuf so there is no offscreen garbage on multimonitor setups
        """

        geometries = self.get_monitor_geometries()
        mask = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
        mask_cr = cairo.Context(mask)

        # fill transparent
        mask_cr.set_source_rgba(0, 0, 0, 0)
        mask_cr.fill()
        mask_cr.paint()
        for geo in geometries:
            mask_cr.rectangle(geo.x, geo.y, geo.width, geo.height)
            mask_cr.set_source_rgba(1, 1, 1, 1)
            mask_cr.fill()

        img = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)

        cr = cairo.Context(img)

        # fill with the dafault color
        cr.set_source_rgba(0, 0, 0, 1)
        cr.fill()
        cr.paint()

        # use the mask to paint from the pixbuf
        gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)
        cr.mask_surface(mask, 0, 0)
        cr.fill()

        stride = img.get_stride()
        pixels = img.get_data()
        data = bgra2rgba(pixels, width, height)

        new_pb = pixbuf.new_from_data(data, colorspace.RGB, True, 8, width,
                                      height, stride)

        return new_pb
Ejemplo n.º 3
0
    def on_instance_view_row_activated(self, view, row_index, column):
        print("on_instance_view_row_activated:", view, " row_index:",
              row_index)

        # clear in reverse order
        self.clear_current_image_and_pixel_data()

        model, treeiter = view.get_selection().get_selected_rows()
        self.sop_instance_uid = model[row_index][0]
        if True:
            # TODO visually present more parts of:
            instance_metadata = self.client.retrieve_instance_metadata(
                study_instance_uid=self.study_instance_uid,
                series_instance_uid=self.series_instance_uid,
                sop_instance_uid=self.sop_instance_uid)[0]
            self.image_height = try_get_attr(instance_metadata,
                                             '00280010')  # rows
            self.image_width = try_get_attr(instance_metadata,
                                            '00280011')  # columns
            self.image_bits_per_pixel = try_get_attr(
                instance_metadata, '00280100')  # bits per pixel
            self.frame_count = try_get_attr(
                instance_metadata, '00280008', '1'
            )  # only present for multi-frame image instances so default to 1
            transfer_syntax_uid = try_get_attr(instance_metadata, '00020010')
            if transfer_syntax_uid is not None:
                transfer_type = DICOM_TRANSFER_SYNTAXES[transfer_syntax_uid]

            image_format = None  # possible values are None (uncompressed/raw), 'jpeg', or 'jp2'
            try:
                start = time.time()
                frames = self.client.retrieve_instance_frames(
                    study_instance_uid=self.study_instance_uid,
                    series_instance_uid=self.series_instance_uid,
                    sop_instance_uid=self.sop_instance_uid,
                    frame_numbers=[1],
                    image_format=image_format)
                stop = time.time()
                print("Retrieving frame took {}".format(stop - start))
            except requests.exceptions.HTTPError:
                frames = []  # no frames
                pass

            # need to store frames because Pixbuf.new_from_data doesn't keep own
            # reference to data so Python will destroy it without Gtk knowing about it
            self.rgb_frames = len(frames) * [None]

            for image_index, frame in enumerate(frames):
                pixel_count = (self.image_width * self.image_height)
                rgb_frame_temp = bytearray(
                    3 * pixel_count)  # pre-allocate RGB pixels

                if image_format is None:  # raw pixels
                    start = time.time()
                    if self.image_bits_per_pixel == 8:
                        for j in range(0, pixel_count):
                            grey8 = frame[j]
                            rgb_frame_temp[3 * j + 0] = grey8
                            rgb_frame_temp[3 * j + 1] = grey8
                            rgb_frame_temp[3 * j + 2] = grey8
                    if self.image_bits_per_pixel == 16:
                        for j in range(0, pixel_count):
                            # 16-bit grey pixel value
                            grey16 = (256 * frame[2 * j + 1] +
                                      frame[2 * j + 0])
                            grey8 = int(grey16 /
                                        128)  # 16-bit to 8-bit conversion
                            rgb_frame_temp[3 * j + 0] = grey8
                            rgb_frame_temp[3 * j + 1] = grey8
                            rgb_frame_temp[3 * j + 2] = grey8
                    else:
                        raise Exception("Cannot handle bits_per_pixel being" +
                                        str(self.image_bits_per_pixel))
                    stop = time.time()
                    print("Converting frame to grey-scale RGB-image took {}".
                          format(stop - start))

                    # Ref: https://lazka.github.io/pgi-docs/#GdkPixbuf-2.0/classes/Pixbuf.html#GdkPixbuf.Pixbuf.new_from_data
                    # this better than `Pixbuf.new_from_bytes` which requires
                    # the data parameter to be wrapped in a GLib.Bytes object

                    # WARNING: be aware of that `new_from_data` is buggy. See for instance:
                    # https://stackoverflow.com/questions/29501835/gtk3-gdk-pixbuf-new-from-data-gives-segmentation-fault-core-dumped-error-13
                    start = time.time()
                    self.rgb_frames[image_index] = bytes(
                        rgb_frame_temp
                    )  # bytearray needs to be wrapped in a `bytes` and store here in order to enot loose ref
                    pixbuf = Pixbuf.new_from_data(
                        self.rgb_frames[image_index],  # data
                        Colorspace.RGB,  # colorspace
                        False,  # has_alpha
                        8,  # bits_per_sample
                        self.image_width,  # width
                        self.image_height,  # height
                        self.image_width *
                        3,  # rowstride, 3 because RGB has 3 bytes per pixel
                        None,
                        None)  # rely on Python for deallocation
                    if image_index == 0:
                        self.image_view.set_from_pixbuf(pixbuf)
                    stop = time.time()
                    print("Display image took {}".format(stop - start))
                elif image_format == 'jp2':
                    print("TODO Decode jp2 image...")
                    if False:
                        input_stream = Gio.MemoryInputStream.new_from_data(
                            frame, None)
                        pixbuf = Pixbuf.new_from_stream(input_stream, None)
                        if image_index == 0:
                            self.image_view.set_from_pixbuf(pixbuf)