Beispiel #1
0
func Decode(r io.Reader) (img image.Image, er error) {
	/* Reading the whole file in may be inefficient, but libjpeg wants callbacks
	 * to functions to read in more data, and that is a nightmare to implement. We
	 * don't want to read the entire stream, however, which means pulling the header.
	 * We may be able to read enough to call jpeg_read_header with a [10]byte, but
	 * I'll change it later if need be, since this probably doesn't play nicely
	 * with a non-closing io.Reader */

	var wholeFile []byte
	if wholeFile, er = ioutil.ReadAll(r); er != nil {
		return
	}

	var cinfo C.struct_jpeg_decompress_struct
	var jerr C.struct_jpeg_error_mgr

	cinfo.err = C.jpeg_std_error(&jerr)
	C.jpeg_CreateDecompress(&cinfo, C.JPEG_LIB_VERSION, C.size_t(unsafe.Sizeof(cinfo)))

	C.jpeg_mem_src(&cinfo, (*C.uchar)(unsafe.Pointer(&wholeFile[0])), C.ulong(len(wholeFile)))

	if C.jpeg_read_header(&cinfo, C.TRUE) == C.JPEG_HEADER_OK {
		C.jpeg_start_decompress(&cinfo)

		if cinfo.num_components == 1 {
			img = decodeGrayscale(&cinfo)

		} else if cinfo.num_components == 3 {
			img = decodeRGB(&cinfo)

		} else if cinfo.num_components == 4 {
			img = decodeCMYK(&cinfo)

		} else {
			er = fmt.Errorf("Invalid number of components (%d)", cinfo.num_components)
		}

		if er == nil {
			C.jpeg_finish_decompress(&cinfo)
		}
	}

	C.jpeg_destroy_decompress(&cinfo)

	return
}