Пример #1
0
    def test_png_rotate_has_alpha_transparency(self):
        ident = 'test.png'
        rotate = '45'
        request_path = '/%s/full/full/%s/default.png' % (ident, rotate)
        resp = self.client.get(request_path)

        self.assertEqual(resp.status_code, 200)

        image = None
        bytes = StringIO(resp.data)
        p = Parser()
        p.feed(bytes.read())  # all in one gulp!
        image = p.close()
        bytes.close()

        # Get the alpha channel as an itertools.imap
        alpha = self.get_alpha_channel(image)

        # Instantiate transparency as False
        transparency = False

        # Loop on the alpha channel and see if we have a value of
        # 0 which means there's a transparent pixel there
        if alpha != None:
            for i in alpha:
                if i == 0:
                    transparency = True

        self.assertTrue(transparency)
Пример #2
0
    def _run_transform(self, target_fp, image_request, image_info, kdu_cmd, fifo_fp):
        try:
            # Start the kdu shellout. Blocks until the pipe is empty
            kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1,
                stderr=subprocess.PIPE, env=self.env)
            with open(fifo_fp, 'rb') as f:
                # read from the named pipe
                p = Parser()
                while True:
                    s = f.read(1024)
                    if not s:
                        break
                    p.feed(s)
                im = p.close() # a PIL.Image
        finally:
            _, stderrdata = kdu_expand_proc.communicate()
            kdu_exit = kdu_expand_proc.returncode
            if kdu_exit != 0:
                map(logger.error, stderrdata)
            unlink(fifo_fp)

        try:
            if self.map_profile_to_srgb and image_info.color_profile_bytes:
                emb_profile = BytesIO(image_info.color_profile_bytes)
                im = self._map_im_profile_to_srgb(im, emb_profile)
        except PyCMSError as err:
            logger.warn('Error converting %r to sRGB: %r', im, err)

        self._derive_with_pil(
            im=im,
            target_fp=target_fp,
            image_request=image_request,
            image_info=image_info,
            crop=False
        )
Пример #3
0
    def _run_transform(self, target_fp, image_request, kdu_cmd, fifo_fp):
        try:
            # Start the kdu shellout. Blocks until the pipe is empty
            kdu_expand_proc = subprocess.Popen(kdu_cmd,
                                               shell=True,
                                               bufsize=-1,
                                               stderr=subprocess.PIPE,
                                               env=self.env)
            with open(fifo_fp, 'rb') as f:
                # read from the named pipe
                p = Parser()
                while True:
                    s = f.read(1024)
                    if not s:
                        break
                    p.feed(s)
                im = p.close()  # a PIL.Image
        finally:
            stdoutdata, stderrdata = kdu_expand_proc.communicate()
            kdu_exit = kdu_expand_proc.returncode
            if kdu_exit != 0:
                map(logger.error, stderrdata)
            unlink(fifo_fp)

        if self.map_profile_to_srgb and image_request.info.color_profile_bytes:  # i.e. is not None
            emb_profile = cStringIO.StringIO(
                image_request.info.color_profile_bytes)
            im = profileToProfile(im, emb_profile, self.srgb_profile_fp)

        self._derive_with_pil(im, target_fp, image_request, crop=False)
Пример #4
0
    def transform(self, src_fp, target_fp, image_request):
        # opj writes to this:
        fifo_fp = self._make_tmp_fp()

        # make the named pipe
        mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp)
        logger.debug('Calling %s', mkfifo_call)
        resp = subprocess.check_call(mkfifo_call, shell=True)
        if resp != 0:
            logger.error('Problem with mkfifo')
        # how to handle CalledProcessError; would have to be a 500?

        # opj_decompress command
        i = '-i "%s"' % (src_fp, )
        o = '-o %s' % (fifo_fp, )
        region_arg = self._region_to_opj_arg(image_request.region_param)
        reg = '-d %s' % (region_arg, ) if region_arg else ''
        reduce_arg = self._scales_to_reduce_arg(image_request)
        red = '-r %s' % (reduce_arg, ) if reduce_arg else ''

        opj_cmd = ' '.join((self.opj_decompress, i, reg, red, o))

        logger.debug('Calling: %s', opj_cmd)

        # Start the shellout. Blocks until the pipe is empty
        # TODO: If this command hangs, the server never returns.
        # Surely that can't be right!
        with open(devnull, 'w') as fnull:
            opj_decompress_proc = subprocess.Popen(opj_cmd,
                                                   shell=True,
                                                   bufsize=-1,
                                                   stderr=fnull,
                                                   stdout=fnull,
                                                   env=self.env)

        with open(fifo_fp, 'rb') as f:
            # read from the named pipe
            p = Parser()
            while True:
                s = f.read(1024)
                if not s:
                    break
                p.feed(s)
            im = p.close()  # a PIL.Image

        # finish opj
        opj_exit = opj_decompress_proc.wait()
        if opj_exit != 0:
            map(logger.error, opj_decompress_proc.stderr)
        unlink(fifo_fp)

        try:
            if self.map_profile_to_srgb and image_request.info.color_profile_bytes:  # i.e. is not None
                emb_profile = BytesIO(image_request.info.color_profile_bytes)
                im = self._map_im_profile_to_srgb(im, emb_profile)
        except PyCMSError as err:
            logger.warn('Error converting %r to sRGB: %r', im, err)

        self._derive_with_pil(im, target_fp, image_request, crop=False)
Пример #5
0
    def transform(self, src_fp, target_fp, image_request):
        # opj writes to this:
        fifo_fp = self._make_tmp_fp()

        # make the named pipe
        mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp)
        logger.debug('Calling %s' % (mkfifo_call, ))
        resp = subprocess.check_call(mkfifo_call, shell=True)
        if resp != 0:
            logger.error('Problem with mkfifo')
        # how to handle CalledProcessError; would have to be a 500?

        # opj_decompress command
        i = '-i "%s"' % (src_fp, )
        o = '-o %s' % (fifo_fp, )
        region_arg = self._region_to_opj_arg(image_request.region_param)
        reg = '-d %s' % (region_arg, ) if region_arg else ''
        reduce_arg = self._scales_to_reduce_arg(image_request)
        red = '-r %s' % (reduce_arg, ) if reduce_arg else ''

        opj_cmd = ' '.join((self.opj_decompress, i, reg, red, o))

        logger.debug('Calling: %s' % (opj_cmd, ))

        # Start the shellout. Blocks until the pipe is empty
        with open(devnull, 'w') as fnull:
            opj_decompress_proc = subprocess.Popen(opj_cmd,
                                                   shell=True,
                                                   bufsize=-1,
                                                   stderr=fnull,
                                                   stdout=fnull,
                                                   env=self.env)

        f = open(fifo_fp, 'rb')
        logger.debug('Opened %s' % fifo_fp)

        # read from the named pipe
        p = Parser()
        while True:
            s = f.read(1024)
            if not s:
                break
            p.feed(s)
        im = p.close()  # a PIL.Image

        # finish opj
        opj_exit = opj_decompress_proc.wait()
        if opj_exit != 0:
            map(logger.error, opj_decompress_proc.stderr)
        unlink(fifo_fp)

        if self.map_profile_to_srgb and image_request.info.color_profile_bytes:  # i.e. is not None
            emb_profile = cStringIO.StringIO(
                image_request.info.color_profile_bytes)
            im = profileToProfile(im, emb_profile, self.srgb_profile_fp)

        self._derive_with_pil(im, target_fp, image_request, crop=False)
 def __init__(self, **kw):
     object.__init__(self)
     [self.__setattr__(k, kw[k]) for k in page.keys]
     quietFns = {False: (self._prnfn, self._nlfn), True: (nopfn, nopfn)}
     self.prnfn, self.nlfn = quietFns[self.quiet]
     if self.contents:
         parser = Parser()
         parser.feed(kw["infile"])
         self.orig = parser.close()
     else:
         self.orig = Image.open(self.infile)
     self.img = self._prepare()
     self.frames = self._getFrames()
Пример #7
0
def mk_tile_subproc():
    opj_bin = '/usr/local/bin/opj_decompress'
    opj_lib = '/usr/local/lib/libopenjp2.so'
    pipe_o = '/tmp/mypipe.bmp'
    out_jpg = '/tmp/test.jpg'
    mkfifo_cmd = '/usr/bin/mkfifo %s' % (pipe_o, )
    rmfifo_cmd = '/bin/rm %s' % (pipe_o, )
    i = '../tests/img/01/02/0001.jp2'
    r = 2  # reduce
    # d = '256,256,512,512'
    d = '0,0,256,256'

    opj_cmd = '%s -i %s -o %s -d %s -r %s' % (opj_bin, i, pipe_o, d, r)

    # make a named pipe
    mkfifo_resp = subprocess.check_call(mkfifo_cmd, shell=True)
    if mkfifo_resp != 0:
        sys.stderr.write('mkfifo not OK\n')

    # write opj_decompress's output to the named pipe
    opj_proc = subprocess.Popen(opj_cmd,
                                shell=True,
                                bufsize=-1,
                                stderr=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                env={'LD_LIBRARY_PATH': opj_lib})

    # open the named pipe and parse the stream
    im = None
    with open(pipe_o, 'rb') as f:
        p = Parser()
        while True:
            s = f.read(1024)
            if not s:
                break
            p.feed(s)
        im = p.close()

    # finish opj
    opj_exit = opj_proc.wait()
    if opj_exit != 0:
        map(sys.stderr.write, opj_proc.stderr)
    else:
        # opj was successful, save to a jpg
        # map(sys.stdout.write, opj_proc.stdout)
        im.save(out_jpg, quality=95)

    # remove the named pipe
    rmfifo_resp = subprocess.check_call(rmfifo_cmd, shell=True)
    if rmfifo_resp != 0:
        sys.stderr.write('rm fifo not OK\n')
Пример #8
0
    def test_allows_jp2_upsample(self):
        # Makes a request rather than building everything from scratch
        ident = self.test_jp2_color_id
        request_path = '/%s/full/pct:110/0/default.jpg' % (ident, )
        resp = self.client.get(request_path)

        self.assertEqual(resp.status_code, 200)

        image = None
        bytes = StringIO(resp.data)
        p = Parser()
        p.feed(bytes.read())  # all in one gulp!
        image = p.close()
        bytes.close()
        expected_dims = tuple(int(d * 1.10) for d in self.test_jp2_color_dims)

        self.assertEqual(expected_dims, image.size)
Пример #9
0
    def import_image(cls, file_path):
        image_parser = Parser()

        f = open(file_path, 'rb')
        while True:
            buf = f.read(8192)
            if buf:
                image_parser.feed(buf)
                continue
            break
        image_parser.close()
        im_hash = cls.hash_image(f)
        if cls.objects.filter(hash=im_hash).exists():
            print "Skipping duplicate (%s)" % im_hash
        else:
            cls.objects.create(
                image=File(f),
                hash=im_hash,
            )
Пример #10
0
 def __init__(self, **kw):
     """A page object.
     Valid keyword parameters:
     startRow (default:0):
         Which row to start analyzing from. This is typically used for analyzing the first
         page of a comic where some top part of the page contains the title (which we need
         to skip)
     lignore, rignore (default:0 for both):
         Scanned pages might have some non-white color on one or both of the edges which
         interfere with gutter detection. These paramters tell the gutter detection
         algorithm to adjust the left boundary by lignore and right boundary by
         rignore when locating gutters
     contents (default: True):
         True => "infile" is a string consisting of page contents
         False => "infile" is a string holding the name of the page file to open
     infile:
         A String holding page contents or the page file name (depending on the contents
         parameter)
     pgNum (default:1):
         Page number (used when processing a whole book)
     quiet:
         Don't print any status messages
     debug:
         Enable debug prints
     fwidth, fheight:
         Minimum width (height resp) of a frame"""
     object.__init__(self)
     [self.__setattr__(k, kw[k]) for k in page.keys]
     quietFns = {False: (self._prnfn, self._nlfn), True: (nopfn, nopfn)}
     self.prnfn, self.nlfn = quietFns[self.quiet]
     if self.contents:
         parser = Parser()
         parser.feed(kw["infile"])
         self.orig = parser.close()
     else:
         self.orig = Image.open(self.infile)
     self.img = self._prepare()
     self.frames = self._getFrames()
Пример #11
0
    def transform(self, src_fp, target_fp, image_request):

        # kdu writes to this:
        fifo_fp = self._make_tmp_fp()

        # kdu command
        q = '-quiet'
        t = '-num_threads %s' % (self.num_threads, )
        i = '-i "%s"' % (src_fp, )
        o = '-o %s' % (fifo_fp, )
        reduce_arg = self._scales_to_reduce_arg(image_request)
        red = '-reduce %s' % (reduce_arg, ) if reduce_arg else ''
        region_arg = self._region_to_kdu_arg(image_request.region_param)
        reg = '-region %s' % (region_arg, ) if region_arg else ''

        kdu_cmd = ' '.join((self.kdu_expand, q, i, t, reg, red, o))

        # make the named pipe
        mkfifo_call = '%s %s' % (self.mkfifo, fifo_fp)
        logger.debug('Calling %s' % (mkfifo_call, ))
        resp = subprocess.check_call(mkfifo_call, shell=True)

        try:
            # Start the kdu shellout. Blocks until the pipe is empty
            logger.debug('Calling: %s' % (kdu_cmd, ))
            kdu_expand_proc = subprocess.Popen(kdu_cmd,
                                               shell=True,
                                               bufsize=-1,
                                               stderr=subprocess.PIPE,
                                               env=self.env)

            f = open(fifo_fp, 'rb')
            logger.debug('Opened %s' % fifo_fp)

            # read from the named pipe
            p = Parser()
            while True:
                s = f.read(1024)
                if not s:
                    break
                p.feed(s)
            im = p.close()  # a PIL.Image

            # finish kdu
            kdu_exit = kdu_expand_proc.wait()
            if kdu_exit != 0:
                map(logger.error, kdu_expand_proc.stderr)

            if self.map_profile_to_srgb and image_request.info.color_profile_bytes:  # i.e. is not None
                emb_profile = cStringIO.StringIO(
                    image_request.info.color_profile_bytes)
                im = profileToProfile(im, emb_profile, self.srgb_profile_fp)

            self._derive_with_pil(im, target_fp, image_request, crop=False)
        except:
            raise
        finally:
            kdu_exit = kdu_expand_proc.wait()
            if kdu_exit != 0:
                map(logger.error, map(string.strip, kdu_expand_proc.stderr))
            unlink(fifo_fp)
Пример #12
0
def get_reduced_image_from_kdu(jp2, size):
    # This is basically like an IIIF op /full/!size,size/0/default.jpg
    # uses kdu via fifo as per Loris
    # returns PIL image object
    print 'making new pillow image for derivs at size', size
    im = None
    # extract the smallest possible resolution as the starting point for our transform ops
    req_w, req_h = confine(jp2.width, jp2.height, size, size)

    # mostly taken from transforms.py in Loris, but we want to return a Pillow image
    # color profile stuff has been removed for now

    n = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
    fifo_fp = os.path.join(TMP_DIR, n + '.bmp')

    # kdu command
    q = ''  # '-quiet'
    t = '-num_threads 4'
    i = '-i "%s"' % (jp2.path,)
    o = '-o %s' % (fifo_fp,)
    reduce_arg = scales_to_reduce_arg(jp2, size)
    red = '-reduce %s' % (reduce_arg,) if reduce_arg else ''

    # kdu_expand -usage:
    # -reduce <discard levels>
    #    Set the number of highest resolution levels to be discarded.  The image
    #    resolution is effectively divided by 2 to the power of the number of
    #    discarded levels.

    kdu_cmd = ' '.join((KDU_EXPAND, q, i, t, red, o))

    # make the named pipe
    mkfifo_call = '%s %s' % (MKFIFO, fifo_fp)
    print 'Calling %s' % (mkfifo_call,)
    resp = subprocess.check_call(mkfifo_call, shell=True)

    expand_env = {
        'LD_LIBRARY_PATH': KDU_LIB,
        'PATH': KDU_EXPAND
    }

    try:
        # Start the kdu shellout. Blocks until the pipe is empty
        print 'Calling: %s' % (kdu_cmd,)
        print '########### kdu ###############'
        kdu_expand_proc = subprocess.Popen(kdu_cmd, shell=True, bufsize=-1,
                                           stderr=subprocess.PIPE, env=expand_env)

        f = open(fifo_fp, 'rb')
        print 'Opened %s' % fifo_fp

        # read from the named pipe into PIL
        p = Parser()
        while True:
            s = f.read(1024)
            if not s:
                break
            p.feed(s)
        im = p.close()  # a PIL.Image

        # finish kdu
        kdu_exit = kdu_expand_proc.wait()
        if kdu_exit != 0:
            print 'KDU ERROR'
            for e in kdu_expand_proc.stderr:
                print e

        if im.mode != "RGB":
            im = im.convert("RGB")

        imw, imh = im.size
        print 'we now have a PIL image %s x %s' % (imw, imh)
        if imw != req_w or imh != req_h:
            im = im.resize((req_w, req_h), resample=Image.ANTIALIAS)

    except:
        raise
    finally:
        kdu_exit = kdu_expand_proc.wait()
        if kdu_exit != 0:
            # TODO : add logging!
            # map(logger.error, map(string.strip, kdu_expand_proc.stderr))
            pass
        os.unlink(fifo_fp)

    return im
Пример #13
0
# make a named pipe
mkfifo_resp = subprocess.check_call(mkfifo_cmd, shell=True)
if mkfifo_resp == 0:
    print 'mkfifo OK'

# write kdu_expand's output to the named pipe
kdu_expand_proc = subprocess.Popen(kdu_cmd,
                                   shell=True,
                                   bufsize=-1,
                                   stderr=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   env={'LD_LIBRARY_PATH': LIB_KDU})

# open the named pipe and parse the stream
with open(pipe_fp, 'rb') as f:
    p = Parser()
    while True:
        s = f.read(1024)
        if not s:
            break
        p.feed(s)
    im = p.close()

# finish kdu
kdu_exit = kdu_expand_proc.wait()
if kdu_exit != 0:
    map(sys.stderr.write, kdu_expand_proc.stderr)
else:
    # if kdu was successful, save to a jpg
    map(sys.stdout.write, kdu_expand_proc.stdout)
    im = im.resize((719, 900), resample=Image.ANTIALIAS)