Golang修复jpeg错误的EOF格式

问题描述

对于某些jpeg图像,EOI并非以\xff\xd9结尾,在我的示例中,我看到的是\xff\x00,所以我尝试使用go修复它。

f,_ := os.Open("bad.jpeg")
img,_,err := image.Decode(f)
if err != nil {
    fmt.Println(err)
}
fmt.Println("successfully decoded")
opt := jpeg.Options{
    Quality: 100,}
f1,_ := os.Create("good.jpeg")
jpeg.Encode(f1,img,&opt)

但是,image.Decode(f)由于unexpected EOF而失败,我想知道如何解决格式错误的jpeg文件的结尾问题。

使用Python,我可以简单地执行以下操作,opensave自动为我修复EOI,这与Go中的任何等效方法一样?

from PIL import Image

im = Image.open("bad.jpeg")
im.save("good.jpeg",quality=100)

这是我正在测试的image

解决方法

这是一个非常幼稚的解决方案,仅适用于这种非常特殊的情况: 读取文件,尝试对其进行解码。如果解码失败,请检查最后两个字节,如果已知模式,则覆盖最后一个字节。尝试再次解码。如果成功,则将固定字节写入新文件。

package main

import (
  "bytes"
  "image"
  _ "image/jpeg"
  "io/ioutil"
) 
  
func main() {
  contents,err := ioutil.ReadFile("bad.jpeg")
  if err != nil {
    panic(err)
  }
  
  buffer := bytes.NewBuffer(contents)
  _,_,err = image.Decode(buffer)
  if err == nil {
    return
  }
  
  if err.Error() != "unexpected EOF" {
    panic(err)
  } 
  
  // Maybe wrong End-Of-Image.
  if contents[len(contents)-1] == '\x00' && contents[len(contents)-2] == '\xff' {
    contents[len(contents)-1] = '\xd9'
  } else {
    panic("don't know what to do")
  } 
  
  // Reset buffer and decode again.
  buffer = bytes.NewBuffer(contents)
  _,err = image.Decode(buffer)
  if err != nil {
    panic(err)
  }
  
  // Write fixed buffer to the new file.
  err = ioutil.WriteFile("good.jpeg",contents,0644)
  if err != nil {
    panic(err)
  }
}