确定BLOB的高度和宽度

Bar*_*han 3 sql oracle plsql blob oracle12c

我意识到,在我们的数据库中,某些人的图像文件是定向的,而所有图像文件都应该是纵向的。因此,我需要确定哪个文件的宽度大于其高度。

我想知道是否有任何方法可以获取类型列的heightwidthBLOB例如dbms_lob.getlength函数,该函数返回CLOB/ BLOB列中的字符数(字节)。

MT0*_*MT0 8

A BLOB是二进制数据-它本质上没有格式(例如JPEG / PNG / BMP),因此也不是图像,因此询问其宽度/高度是没有意义的。

您需要做的是将二进制数据(BLOB)从其(未知)二进制格式(即JPG / PNG / BMP / etc)中提取出来,然后使用图片阅读器从文件的元数据中读取尺寸(这样您不必加载整个文件)。

您可以编写一个Java类,该类具有一个功能,该功能采用BLOB /二进制流和图像格式,然后使用ImageIOImageReaderImageInputStream(例如,作为我从二进制数据读取图像时发现的第一批命中;从报头[解决方案/库)提取物的尺寸12 ]和返回它。

然后,要将该类加载到Oracle数据库中,请使用该loadjava实用程序CREATE OR REPLACE AND COMPILE JAVA SOURCE例如用于解压缩存储在Oracle BLOB中的压缩字符串的示例)。

然后编写一个SQL函数来包装Java实现,以便它将BLOB传递给Java函数并返回width或height(或包含两个值的结构)。


Java代码

import java.io.IOException;
import java.sql.Blob;
import java.sql.SQLException;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;

public class ImageMetaDataReader {
    public static Integer getHeight(
            final Blob   blob,
            final String fileType
    ) throws SQLException
    {
        Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix( fileType );
        while(iter.hasNext())
        {
            ImageReader reader = iter.next();
            try
            {
                ImageInputStream stream = new MemoryCacheImageInputStream( blob.getBinaryStream() );
                reader.setInput(stream);
                return reader.getHeight(reader.getMinIndex());
            } catch ( IOException e ) {
            } finally {
                reader.dispose();
            }
        }
        return null;
    }

    public static Integer getWidth(
            final Blob   blob,
            final String fileType
    ) throws SQLException
    {
        Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix( fileType );
        while(iter.hasNext())
        {
            ImageReader reader = iter.next();
            try
            {
                ImageInputStream stream = new MemoryCacheImageInputStream( blob.getBinaryStream() );
                reader.setInput(stream);
                return reader.getWidth(reader.getMinIndex());
            } catch ( IOException e ) {
            } finally {
                reader.dispose();
            }
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.SQLException;

public class MockBlob implements Blob {
    private final File file;

    public MockBlob(
            final File file
    )
    {
        this.file = file;
    }

    @Override
    public long length() throws SQLException {
        return file.length();
    }

    @Override
    public InputStream getBinaryStream() throws SQLException {
        try
        {
            return new FileInputStream( this.file );
        }
        catch( FileNotFoundException e )
        {
            throw new SQLException( e.getMessage() );
        }
    }

    @Override public byte[] getBytes(long pos, int length) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
    @Override public long position(byte[] pattern, long start) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
    @Override public long position(Blob pattern, long start) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
    @Override public int setBytes(long pos, byte[] bytes) throws SQLException { throw new UnsupportedOperationException("Not supported yet.");  }
    @Override public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { throw new UnsupportedOperationException("Not supported yet.");  }
    @Override public OutputStream setBinaryStream(long pos) throws SQLException { throw new UnsupportedOperationException("Not supported yet.");  }
    @Override public void truncate(long len) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
    @Override public void free() throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
    @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { throw new UnsupportedOperationException("Not supported yet."); }
}
Run Code Online (Sandbox Code Playgroud)
import java.io.File;
import java.sql.Blob;
import java.sql.SQLException;

public class ImageTest {
    public static void main(
            final String[] args
    ) throws SQLException
    {
        File file = new File( "/path/to/test.png" );
        Blob blob = new MockBlob( file );
        System.out.println(
                "height: "
                + ImageMetaDataReader.getHeight( blob, "png" )
        );
        System.out.println(
                "width: "
                + ImageMetaDataReader.getWidth( blob, "png" )
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

SQL

CREATE AND COMPILE JAVA SOURCE NAMED "ImageMetaDataReader" AS
<the java code from above>
/

CREATE FUNCTION getImageHeight(
  file     IN BLOB,
  fileType IN VARCHAR2
) RETURN NUMBER
AS LANGUAGE JAVA
name 'ImageMetaDataReader.getHeight( java.sql.Blob, String) return Integer';
/

CREATE FUNCTION getImageWidth(
  file     IN BLOB,
  fileType IN VARCHAR2
) RETURN NUMBER
AS LANGUAGE JAVA
name 'ImageMetaDataReader.getWidth( java.sql.Blob, String) return Integer';
/
Run Code Online (Sandbox Code Playgroud)

(由于我目前没有要处理的实例,因此该代码未经Oracle数据库测试)。