PL/SQL 获取 JPEG 图像的尺寸

PL/SQL Get Dimensions of JPEG Image

Oracle 19c 中删除了对 Oracle Multimedia 的支持,因此我从 JPEG 图像中提取尺寸的代码会引发错误。这个问题有解决方法吗?

对于 Oracle 12,我的代码如下所示:

    BEGIN
        img := ORDSYS.ORDImage.init('FILE', my_dir, my_img_name);
        img.setProperties();
        w := img.getWidth();
        h := img.getHeight();
    EXCEPTION
        WHEN OTHERS THEN
            w := NULL;
            h := NULL;
    END;

基于在 response to "Getting Image size of JPEG from its binary" 中找到的代码(我不确定是哪种语言),我想出了这个程序:

PROCEDURE p_jpegstats(directory_in IN  VARCHAR2,
                      filename_in  IN  VARCHAR2,
                      height_out   OUT INTEGER,
                      width_out    OUT INTEGER,
                      bpc_out      OUT INTEGER,  -- bits per channel
                      cps_out      OUT INTEGER   -- colors per component
                     ) IS
    file    bfile;
    pos     INTEGER:=1;
    h       VARCHAR2(4);
    w       VARCHAR2(4);
    mrkr    VARCHAR2(2);
    len     VARCHAR2(4);
    bpc     VARCHAR2(2);
    cps     VARCHAR2(2);

    --  Declare a quick helper procedure for readability
    PROCEDURE next_byte(buf out varchar2, amt INTEGER:=1) IS
        cnt     INTEGER;
    BEGIN
        cnt := amt;
        dbms_lob.read(file, cnt, pos, buf);
        pos := pos + cnt;
    END next_byte;
BEGIN
-- This code is based off of code found here: 

-- Open the file
    file := bfilename(directory_in, filename_in);
    dbms_lob.fileopen(file);

-- Init the output variables in case something goes awry.
    height_out := NULL;
    width_out  := NULL;
    bpc_out    := NULL;
    cps_out    := NULL;

    LOOP
    BEGIN
        LOOP
            next_byte(mrkr);
            EXIT WHEN mrkr <> 'FF';
        END LOOP;
        CONTINUE WHEN mrkr = 'D8';  -- Start of image (SOI)
        EXIT WHEN mrkr = 'D9';      -- End of image (EOI)
        CONTINUE WHEN mrkr BETWEEN 'D0' AND 'D7';
        CONTINUE WHEN mrkr = '01';  -- TEM
        next_byte(len, 2);
        IF mrkr = 'C0' THEN
            next_byte(bpc);    -- bits per channel
            next_byte(h, 2);   -- height
            next_byte(w, 2);   -- width
            next_byte(cps);    -- colors per component
            EXIT;
        END IF;
        pos := pos + to_number(len, 'XXXX') - 2;
    EXCEPTION WHEN OTHERS THEN EXIT; END;
    END LOOP;

-- Write back the values we found
    height_out := to_number(h, 'XXXX');
    width_out  := to_number(w, 'XXXX');
    bpc_out    := to_number(bpc, 'XX');
    cps_out    := to_number(cps, 'XX');

-- close out the file
    dbms_lob.fileclose(file);
END p_jpegstats;

如果目录无效或文件无法打开,这将引发错误。如果输出为 NULL,则存在其他问题。

它可能不是最有效或最优雅的代码(我不是 PL/SQL [还!])的专家,但它确实有效。这是一个示例用法:

DECLARE
    h       INTEGER;
    w       INTEGER;
    bpc     INTEGER;
    cps     INTEGER;
BEGIN
    p_jpegstats('MY_DIR', 'my_image.jpg', h, w, bpc, cps);
    DBMS_OUTPUT.PUT_LINE(w || ' x ' || h || '  ' || bpc || '  ' || cps);
END;
/

这应该return类似于

800 x 200  8  3

编辑:删除了未使用的变量。