我正在努力编写一个SQL数据库(Windows SQL Server)的报告,该报告要求某些人在将报告提交给客户端之前签署该报告。我们希望有一个系统,这些人可以在数据库中授权他们的签名,然后我们可以使用他们的签名图像存储在数据库中,并将其放在LaTeX生成的报告上。
签名图像创建为PNG,然后存储在数据库中varbinary
类型的字段中。为了在报告中使用签名,我需要将PNG重新组合成一个文件,我可以在LaTeX中使用\includegraphics
。
不幸的是,我似乎无法从数据库中重新创建PNG。由于我无法发布签名,我们将使用下面的图片作为示例。
在我的计算机上使用此图像,我可以将文件读取为原始文件,将其写入不同的文件,并在打开新文件时获取相同的图像。
#* It works to read the image from a file and rewrite it elsewhere
pal <- readBin("C:/[filepath]/ColorPalette.png",
what = "raw", n = 1e8)
writeBin(pal,
"C:/[filepath]/colors.png",
useBytes=TRUE)
现在,我已将相同的图像保存到数据库中,并使用RODBC,我可以像这样提取它:
#*** Capture the raw from the database
con <- odbcConnect("DATABASE")
Users <- sqlQuery(con, "SELECT * FROM dbo.[User]")
db_pal <- Users$Signature[Users$LastName == "MyName"]
#*** Write db_pal to a file, but the image won't render
#*** Window Photo Viewer can't open this picture because the file appears to be damaged, corrupted, or is too large (12KB)
writeBin(db_pal[[1]],
"C:/[filename]/db_colors.png",
useBytes=TRUE)
对象pal
和db_pal
在this Gist中定义(它们太长,无法放入允许的空间)
注意:db_pal
是一个原始矢量的列表。此外,它明显不同于原始向量pal
> length(pal)
[1] 2471
> length(db_pal[[1]])
[1] 9951
有关将图像从数据库中删除可能需要做些什么的想法?
答案 0 :(得分:2)
嗯,我们已经找到了解决方案。通过RODBC返回的原始向量与SQL数据库中的不匹配。在管道中的某个地方,来自SQL的varbinary
对象变得扭曲。我不确定为什么或怎么做。但this answer to a different problem激励我们重铸变量。一旦我们重铸它们,我们就能看到正确的表示。
下一个问题是我们所有的图像都超过8000个字节,而RODBC一次只允许8000个字符。所以我不得不摸索着我的方式。以下代码执行以下操作:
ImagePart1
,...,ImagePart[n]
),根据需要将图像分成多个部分,每个部分的最大长度为8000. 实际代码
library(RODBC)
lims <- odbcConnect("DATABASE")
#* 1. Determine the largest number of bytes in the largest image file
ImageLength <- sqlQuery(lims,
paste0("SELECT MaxLength = MAX(LEN(u.Image)) ",
"FROM dbo.[User] u"))
#* Create a query string to make a set of variables breaking
#* the images into as many parts as necessary, each with
#* max length 8000
n_img_vars <- ImageLength$MaxLength %/% 8000 + 1
start <- 1 + 8000 * (0:(n_img_vars - 1))
end <- 8000 + 8000 * (0:(n_img_vars - 1))
img_parts <- paste0("ImagePart", 1:n_img_vars,
" = CAST(SUBSTRING(u.Image, ", start,
", ", end, ") AS VARBINARY(8000))")
full_query <- paste0("SELECT u.OID, u.LastName, u.FirstName,\n",
paste0(img_parts, collapse =",\n"), "\n",
"FROM dbo.[User] u \n",
"WHERE LEN(u.Image) > 0")
#* 3. Query the database for all the images
Images <- sqlQuery(lims, full_query)
#* 4. Combine the images parts into a single object
Images$full_image <-
apply(Images[, grepl("ImagePart", names(Images))], 1,
function(x) do.call("c", x))
#* 5. Write the images to a local file
for(i in seq_len(nrow(Images))){
DIR <- "[FILE_DIR]"
FILENAME <- with(Images, paste0(OID[i], "-", LastName[i], ".png"))
writeBin(unlist(Images$full_image[i]),
file.path(DIR, FILENAME))
}
答案 1 :(得分:0)
我可能会误解这个问题,但raster
包可能会对您有所帮助。
library(raster)
your_image <- raster(nrows=587,ncols=496,values=db_pal[[1]])
plot(your_image)
但是db_pal[[1]]
的长度不是291,152(587 * 496)是没有意义的,所以有些事情并没有为我增加。你知道这些291,152值会被存储在哪里吗?