Lua – 使用离散余弦变换 (DCT) 编码 JPEG 的能力

huangapple go评论59阅读模式
英文:

Lua - Ability to encode JPEG using DCT (discrete cosine transform)

问题

我正在寻找一个库和/或指南,可以让我使用DCT(离散余弦变换)对图像进行编码,以便将其放入一个基本的1.0版PDF文件中(顺便说一下,我正在使用https://git.catseye.tc/pdf.lua/创建PDF文件)。

我已经在互联网上搜索了一些东西,但是找不到任何关于使用Lua来编码JPEG图像的信息。有没有人在Stack Overflow上了解使用Lua来进行JPEG图像DCT编码的内容?

更新:

根据反馈,这里是我提出问题的一些额外信息:

如果你打开一个PDF文件,存储的JPEG数据将显示在XObject图像中。以下是一个示例。

14 0 obj
<<
/Intent/RelativeColorimetric
/Type/XObject
/ColorSpace/DeviceGray
/Subtype/Image
/Name/X
/Width 2988
/BitsPerComponent 8
/Length 134030
/Height 2286
/Filter/DCTDecode
>>
stream (二进制数据) endstream

/Type显示这是一幅图像。关键部分是/Filter的值 - DCTDecode,它表示一个JPEG图像(JPX显示JPEG2000也可以)。我需要的数据应该位于stream和endstream之间。

我正在寻求帮助,以了解如何将图像转换为所需的DCT格式。

英文:

I’m looking to find a library and/or guide that would allow me to encode an image with DCT (discrete cosine transform ) so I can place it in a basic 1.0 pdf file. (FYI I’m using https://git.catseye.tc/pdf.lua/ to create the pdf.

I’ve search the internet for something’s but couldn’t find anything is anyone on SO aware of something using Lua to encode an JPEG with DCT..

Update:

Based on feedback, here’s some additional information on my ask

If you open up a PDF file, the stored JPEG data will appear in the XObject image. Here is an example.

14 0 obj
&lt;&lt;
/Intent/RelativeColorimetric
/Type/XObject
/ColorSpace/DeviceGray
/Subtype/Image
/Name/X
/Width 2988
/BitsPerComponent 8
/Length 134030
/Height 2286
/Filter/DCTDecode
&gt;&gt;
stream (binary data) endstream

The /Type shows that this is an image. The key section is the /Filter value – DCTDecode , which indicates a JPEG (JPX shows a JPEG2000) which also works. The data i need is to go between stream and endstream.

I’m looking for help in how I can get an image converted into the DCT format needed..

答案1

得分: 1

DCT/JPG在PDF中的主要区别在于PDF中的.jpeg必须是“基线”,就像[1992][1]中所示,也可以参考(https://ia801003.us.archive.org/5/items/pdf320002008/PDF32000_2008.pdf#page=42),这就是MS画图(或任何命令驱动的图形应用程序)将保存为“简单”.jpeg(而不是任何奇异的类型),所以在右边是来自MSPaint的everyday.jpeg,从PNG或任何其他复杂格式的转换,以及当被PDF编写器导入时的/DCT解码对象,位于左边。

[![enter image description here][2]][2]

因此,如果我们从PDF中导出图像,我们将得到Jpeg(而不是源PNG)。如何检查它们是否相同是复制和粘贴或使用提取器。
因此,用于我的cmd线包装的image.jpg为“5,757字节”,从PDF中提取的图像也为“5,757字节”,因此我们可以期望匹配。

检查它们是否是相同的二进制文件(输入什么,输出什么,对于PDF来说非常罕见)

C:\Apps\Programming\pdf demo&gt;fc /B input.jpg extracted.jpg
比较文件 input.jpg 和 EXTRACTED.JPG
FC: 未遇到任何差异

因此,要从图像制作一个页面PDF,您只需要一个标题

%PDF-1.7
%ANSI

1 0 obj &lt;&lt;/Type/Catalog/Pages 2 0 R&gt;&gt; endobj
2 0 obj &lt;&lt;/Type/Pages/Count 1/Kids [ 3 0 R ]&gt;&gt; endobj
3 0 obj &lt;&lt;/Type/Page/MediaBox [ 0 0 841.5 594.75 ]/Rotate 0/Resources 4 0 R/Contents 5 0 R/Parent 2 0 R&gt;&gt; endobj
4 0 obj &lt;&lt;/XObject &lt;&lt;/Img1 6 0 R&gt;&gt;&gt;&gt; endobj
5 0 obj &lt;&lt;/Length 61&gt;&gt;
stream
1 0 0 -1 -0 594.75 cm 841.5 0 0 -594.75 0 594.75 cm /Img1 Do
endstream
endobj
6 0 obj &lt;&lt;/Type/XObject/Subtype/Image/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode
/Width 1123/Height 794/Length 202537 &gt;&gt;stream

其中,Windows命令行或任何其他脚本语言可以使用正确的值编写最后一行。然后是一个尾部,这可能会变得混乱。因此,为了使尾部写得尽可能少,尽可能多的尾部被移到了头部。我已经为视频和音频做了类似的cmd行嵌入,因此DCT(Jpeg)图像不应该是一个问题(除非我更喜欢无损像素完美的PNG,那样就更难)。

这是上面标题的匹配尾部

endstream
endobj
xref
0 7
0000000000 65535 f 
0000000016 00000 n 
0000000061 00000 n 
0000000115 00000 n 
0000000228 00000 n 
0000000272 00000 n 
0000000380 00000 n 

trailer
&lt;&lt;/Size 7/Info &lt;&lt;/Producer (Cmd2PDF)&gt;&gt;/Root 1 0 R&gt;&gt;
startxref
203076
%%EOF

您只需要确保startxref正确

因此,工作程序首先使用任何图形应用程序来准备宽度、高度和长度,并将维度和因此偏移量应用到标题和尾部的末尾,然后简要地

copy /b 8bitHead.txt + 8bit.jpg + 8bitTail.txt 8bitColour.pdf

由于Jpg是二进制的压缩编码,您不能使用任何纯文本的复制和粘贴,因为它会破坏每个字节的最高8位,破坏了jpeg,因此在文本方式下无法建立,因此需要在两个文本部分之间进行二进制夹层,因此使用copy /b

[![enter image description here][3]][3]

[稍后编辑]

我上面提供了对象5的相当复杂的值,可以简化为这样,假设我们有一个要缩放为500 pt x 477 pt并居中的图像,我们可以使用额外宽度的一半和额外高度的一半作为偏移,因此简化为 W 0 0 H dx/2 dy/2,其中dx是宽度的白色空间,dy也是高度的白色空间。

5 0 obj &lt;&lt;/Length 61&gt;&gt; stream
500.000 0 0 477.000 170.750 53.873 cm /Img1 Do               
endstream
endobj

[稍后编辑]
对于另一个问题,我重新审视了使用一个更简单的cmd文件来自动化单个完美像素的jpg添加所需的方法。与上面的方法差异不大,需要一些润色以用于生产。但它展示了如何自动化各种源图像,并可以改进以用于循环中的一组图像,这只是一个起点。

@echo off
set &quot;filename=%~f1&quot;

REM 清理任何失败的运行!
if exist %temp%\output1.txt del %temp%\output1.txt
if exist %temp%\output2.txt del %temp%\output2.txt
if exist %temp%\output.pdf del %temp%\output.pdf

REM 我们可以在这里写一个文本标题

<details>
<summary>英文:</summary>

The prime difference for DCT/JPG in PDF is that the .jpeg in a PDF must be &quot;baseline&quot; much as it was in [1992][1] see also (https://ia801003.us.archive.org/5/items/pdf320002008/PDF32000_2008.pdf#page=42) and that&#39;s what MS paint (or any command driven graphics app) will save as &quot;simple&quot; .jpeg (not any exotic type) so here on the right is the everyday.jpeg from MSPaint conversion from PNG or any other complex format, and here is the exact same /DCTdecode object when imported by a PDF writer, on the left. 

[![enter image description here][2]][2]

So If we export the image from the PDF we will get the Jpeg (not the source PNG). How to check they are identical is copy and paste or use extractor.  
So the image.jpg used for my cmd line wrap as a pdf is `5,757 bytes` the extracted from PDF image is `5,757 bytes`, thus we can expect a match.

Check they are the identical binary files (What goes in, comes out, very rare for a PDF)

C:\Apps\Programming\pdf demo>fc /B input.jpg extracted.jpg
Comparing files input.jpg and EXTRACTED.JPG
FC: no differences encountered


So to make a page PDF from an image you simply need a header

%PDF-1.7
%ANSI

1 0 obj <</Type/Catalog/Pages 2 0 R>> endobj
2 0 obj <</Type/Pages/Count 1/Kids [ 3 0 R ]>> endobj
3 0 obj <</Type/Page/MediaBox [ 0 0 841.5 594.75 ]/Rotate 0/Resources 4 0 R/Contents 5 0 R/Parent 2 0 R>> endobj
4 0 obj <</XObject <</Img1 6 0 R>>>> endobj
5 0 obj <</Length 61>>
stream
1 0 0 -1 -0 594.75 cm 841.5 0 0 -594.75 0 594.75 cm /Img1 Do
endstream
endobj
6 0 obj <</Type/XObject/Subtype/Image/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode
/Width 1123/Height 794/Length 202537 >>stream

where a windows command line or any other script language, can write that last line with the correct values. And a trailer, which is where it may then get messy. So as much of the tail was moved to the head to keep the trailer writing minimal. I have done similar cmd line embedding for Video and Audio, so DCT (Jpeg) images should not be a problem. (except I prefer lossless pixel perfect PNG and that&#39;s way harder).

here is a matching trailer for the header above

endstream
endobj
xref
0 7
0000000000 65535 f
0000000016 00000 n
0000000061 00000 n
0000000115 00000 n
0000000228 00000 n
0000000272 00000 n
0000000380 00000 n

trailer
<</Size 7/Info <</Producer (Cmd2PDF)>>/Root 1 0 R>>
startxref
203076
%%EOF

You simply need to ensure the startxref is correct

So the working program is first use any graphics app to prep the width height and length and apply the dimensions and thus offset to end of header and trailer then briefly

copy /b 8bitHead.txt + 8bit.jpg + 8bitTail.txt 8bitColour.pdf


Since Jpg is a binary compressive encoding, you cant use any plain text copy and paste as it destroys the highest 8th bit of each byte corrupting the jpeg, hence its the pants for building in a textual fashion. Thus needs binary sandwich between the 2 text parts hence `copy /b` 

[![enter image description here][3]][3]

[Later Edit]

I gave a fairly complex value above for object 5, that can be simplified so say we have an image to be scaled as 500 pt by 477 pt and we want it centred, we can offset use by half of the extra width and half the extra height so  simplifieed to `W 0 0 H dx/2 dy/2` where dx is the width of whitespace and similar for dy height.

5 0 obj <</Length 61>> stream
500.000 0 0 477.000 170.750 53.873 cm /Img1 Do
endstream
endobj


[Even LATER edit]
For a different question I revisited the methods needed to use a simpler cmd file to automate a single pixel perfect jpg addition. It is not much different to above and needs some spit and polish for production. However it shows how to automate for various source images and can be bettered for a set of images in a loop, but its a start point.  
[![enter image description here][4]][4]

@echo off
set "filename=%~f1"

REM cleanup any failed run !
if exist %temp%\output1.txt del %temp%\output1.txt
if exist %temp%\output2.txt del %temp%\output2.txt
if exist %temp%\output.pdf del %temp%\output.pdf

REM we could write a text header here but its faster to copy one prepared earlier
copy header.txt %temp%\output1.txt

REM Write current image data
@echo fsObj = new ActiveXObject("Scripting.FileSystemObject");var ARGS = WScript.Arguments;var img=new ActiveXObject("WIA.ImageFile");var filename=ARGS.Item(0);img.LoadFile(filename);WScript.StdOut.Write("/Width "+img.Width+"/Height "+img.Height);>"%temp%\dimimg.js"
@cscript //nologo "%temp%\dimimg.js" "%filename%">>%temp%\output1.txt
for %%I in ("%filename%") do @echo /Length %%~zI^>^>>>%temp%\output1.txt
echo stream>>%temp%\output1.txt

REM append image
copy /b %temp%\output1.txt+%filename% %temp%\output2.txt
echo/>>%temp%\output2.txt
echo endstream>>%temp%\output2.txt
echo endobj>>%temp%\output2.txt

REM prep the trailer
for %%I in ("%temp%\output2.txt") do set "startxref=%%~zI"
copy /b %temp%\output2.txt+trailer.txt %temp%\output.pdf
echo %startxref%>>%temp%\output.pdf
echo %%%%EOF>>%temp%\output.pdf

REM call the result
if exist %temp%\output1.txt del %temp%\output1.txt
if exist %temp%\output2.txt del %temp%\output2.txt
%temp%\output.pdf

A demo working set can be found here https://github.com/GitHubRulesOK/MyNotes/blob/master/jpgTOpdf.zip

  [1]: https://web.archive.org/web/20140903080533/http://www.jpeg.org/public/jfif.pdf
  [2]: https://i.stack.imgur.com/RtM2G.png
  [3]: https://i.stack.imgur.com/WKmrb.jpg
  [4]: https://i.stack.imgur.com/hx2Bj.png

</details>



huangapple
  • 本文由 发表于 2023年3月12日 07:24:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710190.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定