disintegration / imaging

Imaging is a simple image processing package for Go
MIT License
5.23k stars 435 forks source link

tiff decode result is wrong! #101

Closed sotex closed 5 years ago

sotex commented 5 years ago

When my picture is GeoTiff(128x128 BlockSize LZW compress), the Resize result is wrong.

code:

                src, err = imaging.Open("D:/Document/data/qdcaichu3.tif")
        log.Println(src.Bounds())
        dst := imaging.Resize(src, 512, 512, imaging.NearestNeighbor)
        log.Println(dst.Bounds(), dst.ColorModel())
        err = imaging.Encode(w, dst, imaging.JPEG)

Output Result: 图片 Origin Picture: 图片

As long as you convert this image to another format or save another copy, there is no error. But software such as GlobalMap can be read correctly.

Origin file:https://c-t.work/s/77dc0228ef574e Number: 322420

disintegration commented 5 years ago

Thank you for the report!

For some reason I cannot reproduce your results. I've downloaded the TIFF file using the above link (qdcaichu.tif). I'm not sure what does Number: 322420 mean. Could you please provide more information on that?

Here are the md5 and sha256 checksums of the downloaded file:

$ md5sum qdcaichu.tif 
a6f5a83568a54e2ec234b595626a5858  qdcaichu.tif

$ sha256sum qdcaichu.tif 
9379258df229a120c541eec2e257cdca5163a070ab8da925591f698bae5123c7  qdcaichu.tif

I've modified your code slightly to add error handling and to make it a runnable example.

package main

import (
    "log"

    "github.com/disintegration/imaging"
)

func main() {
    src, err := imaging.Open("qdcaichu.tif")
    if err != nil {
        log.Fatalf("failed to open image: %v", err)
    }

    log.Println(src.Bounds())
    dst := imaging.Resize(src, 512, 512, imaging.NearestNeighbor)
    log.Println(dst.Bounds(), dst.ColorModel())

    if err := imaging.Save(dst, "out.jpg"); err != nil {
        log.Fatalf("failed to save image: %v", err)
    }
}

I get the following image decoding error when running this example:

$ go run main.go 
2019/07/25 00:38:41 failed to open image: unexpected EOF
exit status 1

Looks like the golang.org/x/image/tiff package, used internally by imaging, cannot decode this image.

I get the same result when using the tiff package directly:

package main

import (
    "log"
    "os"

    "golang.org/x/image/tiff"
)

func main() {
    f, err := os.Open("qdcaichu.tif")
    if err != nil {
        log.Fatalf("failed to open image: %v", err)
    }
    defer f.Close()

    src, err := tiff.Decode(f)
    if err != nil {
        log.Fatalf("failed to decode image: %v", err)
    }

    log.Println(src.Bounds())
}
$ go run main.go 
2019/07/25 00:50:17 failed to decode image: unexpected EOF
exit status 1
sotex commented 5 years ago

Thank you. You download the image file checksum is correct. I am trying to convert this image to BIGTIFF and output the following information after running with your code: disintegration/imaging

go run main.go 
2019/08/01 14:13:05 failed to open image: image: unknown format
exit status 1

golang.org/x/image/tiff

go run main.go 
2019/08/01 14:10:25 failed to decode image: tiff: invalid format: malformed header

If converted into common TIFF, rather than BIGTIFF there is no error.

I can read this image using the GDAL library.

> gdalinfo qdcaichu.tif 
Driver: GTiff/GeoTIFF
Files: qdcaichu.tif
Size is 4150, 3131
Coordinate System is:
PROJCS["Xian_1980_3_Degree_GK_Zone_40",
    GEOGCS["GCS_Xian_1980",
        DATUM["Xian_1980",
            SPHEROID["Xian_1980",6378140,298.257,
                AUTHORITY["EPSG","7049"]],
            AUTHORITY["EPSG","6610"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",120],
    PARAMETER["scale_factor",1],
    PARAMETER["false_easting",40500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]]]
Origin = (40526979.924999997019768,3992527.875000000000000)
Pixel Size = (0.150000000000000,-0.149999999999970)
Metadata:
  AREA_OR_POINT=Area
  DataType=Generic
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (40526979.925, 3992527.875) (120d17'58.09"E, 36d 3'45.22"N)
Lower Left  (40526979.925, 3992058.225) (120d17'58.03"E, 36d 3'29.99"N)
Upper Right (40527602.425, 3992527.875) (120d18'22.96"E, 36d 3'45.16"N)
Lower Right (40527602.425, 3992058.225) (120d18'22.90"E, 36d 3'29.92"N)
Center      (40527291.175, 3992293.050) (120d18'10.50"E, 36d 3'37.57"N)
Band 1 Block=128x128 Type=Byte, ColorInterp=Red
  NoData Value=0
Band 2 Block=128x128 Type=Byte, ColorInterp=Green
  NoData Value=0
Band 3 Block=128x128 Type=Byte, ColorInterp=Blue
  NoData Value=0
disintegration commented 5 years ago

If converted into common TIFF, rather than BIGTIFF there is no error.

Do I need to do any additional conversion steps on the image before running the examples? Do you use go modules? If not, what is the revision of golang.org/x/image in your GOPATH?

I've tried a few different versions of golang.org/x/image/tiff package, but I'm still getting the same tiff.Decode error when trying to open the image you've provided: unexpected EOF.

sotex commented 5 years ago

@disintegration I converted it to normal TIFF and BIGTIFF using thegdal_translate. converted it to common GeoTIFF

gdal_translate -of GTiff  qdcaichu.tif qdcaichu_1.tif

converted it to BIGTIFF

gdal_translate -of GTiff -co "BIGTIFF=YES" qdcaichu.tif qdcaichu_1.tif
disintegration commented 5 years ago

Sorry for the late reply. I was away from computers for the last two weeks.

I just did what you suggested:

gdal_translate -of GTiff  qdcaichu.tif qdcaichu_1.tif

Now the example code works with qdcaichu_1.tif and it looks like it produces the expected result.

package main

import (
    "log"

    "github.com/disintegration/imaging"
)

func main() {
    src, err := imaging.Open("qdcaichu_1.tif")
    if err != nil {
        log.Fatalf("failed to open image: %v", err)
    }

    log.Println(src.Bounds())
    dst := imaging.Resize(src, 512, 512, imaging.NearestNeighbor)
    log.Println(dst.Bounds(), dst.ColorModel())

    if err := imaging.Save(dst, "out.jpg"); err != nil {
        log.Fatalf("failed to save image: %v", err)
    }
}
$ go run main.go 
2019/08/21 00:28:00 (0,0)-(4150,3131)
2019/08/21 00:28:00 (0,0)-(512,512) &{0x49cd30}

Here's the output image (out.jpg):

out

The output image you've attached to the first message looks truncated though. Maybe you need to flush the buffered writer?

sotex commented 5 years ago

Thank you. Convert to common Tiff is no error, you can try to convert to BIGTIFF.

gdal_translate -of GTiff  -co "BIGTIFF=YES" qdcaichu.tif qdcaichu_1.tif
disintegration commented 5 years ago

Running the example code on BigTIFF version of the image I get the same error as you do:

failed to open image: image: unknown format

It means that this type of image is not supported by golang.org/x/image/tiff package.

The imaging package doesn't implement image decoding by itself. The Open function is just a simple wrapper around image.Decode, which in turn calls individual image decoding packages depending on the image format (golang.org/x/image/tiff is used for TIFF). You can try opening an issue in the main Go repository if you need decode this type of images.

paolobarbolini commented 5 years ago

Yeah, if you take a look at the Go issue tracker you are going to find a lot of issues with the TIFF package.

The worst part of it is that since TIFF is still part of golang.org/x issues can take a long time to be fixed. I reported a TIFF issue myself a few days ago and while we already decided on what the fix should be like, looking at other issues I think it will take a long time before we get a fix.

disintegration commented 5 years ago

I'm closing the issue now. It looks like it's not relevant to the imaging package (see my previous comment).