func eval(t *testing.T, path string, f storage.Image, size image.Point, colors []int) string {
	var b []byte
	w := bytes.NewBuffer(b)
	p := processor.New()
	f.ValidatedWidth *= u
	f.ValidatedHeight *= u
	pixels, err := p.Preprocess(path)
	if err != nil {
		t.Fatalf("cannot preprocess image: error=%v", err)
	}

	f, err = f.Normalize(pixels.Bounds().Size())
	if err != nil {
		t.Fatalf("fail to normalize: error=%v", err)
	}

	if _, err := p.Process(pixels, w, f); err != nil {
		t.Fatalf("cannot process image: %v", err)
		return ""
	}

	r := bytes.NewReader(w.Bytes())
	img, format, err := image.Decode(r)
	if err != nil {
		t.Fatalf("cannot decode image: %v", err)
		return ""
	}

	expectedSize := size.Mul(u)
	rect := img.Bounds()
	actualSize := rect.Size()
	if !actualSize.Eq(expectedSize) {
		t.Fatalf("wrong size expected %v, but actual %v", expectedSize, actualSize)
		return ""
	}

	evalPixels(t, img, size, colors)

	return format
}
func BenchmarkProcess(b *testing.B) {
	if err := fetcher.Init(); err != nil {
		b.Fatal(err)
	}
	o, err := option.New(os.Args[1:])
	if err != nil {
		b.Fatal(err)
	}

	for i := 0; i < b.N; i++ {
		o, err := storage.NewImage(map[string][]string{
			"url":    []string{""},
			"width":  []string{"800"},
			"height": []string{"0"},
		}, o.Hosts)
		if err != nil {
			b.Fatalf("%s", err)
		}

		path, err := fetcher.Fetch(o.ValidatedURL)
		if err != nil {
			b.Fatalf("%s", err.Error())
		}

		var bs []byte
		w := bytes.NewBuffer(bs)
		p := processor.New()

		image, err := p.Preprocess(path)
		if err != nil {
			b.Fatalf("%s", err.Error())
		}

		if _, err := p.Process(image, w, o); err != nil {
			b.Fatalf("%s", err.Error())
		}
	}
}
Exemple #3
0
// operate は手続き的に一連のリサイズ処理を行う。
// エラーを画一的に扱うためにメソッドとして切り分けを行っている
func (h *Handler) operate(resp http.ResponseWriter, req *http.Request) error {
	t := log.Start()
	defer log.End(t)

	// 1. URLクエリからリクエストされているオプションを抽出する
	i, err := storage.NewImage(req.URL.Query(), h.Hosts)
	if err != nil {
		return err
	}

	// 3. バリデート済みオプションでリサイズをしたキャッシュがあるか調べる
	// 4. キャッシュがあればリサイズ画像のURLにリダイレクトする
	cache := storage.Image{}
	h.Storage.Where(&storage.Image{
		ValidatedHash:    i.ValidatedHash,
		ValidatedWidth:   i.ValidatedWidth,
		ValidatedHeight:  i.ValidatedHeight,
		ValidatedMethod:  i.ValidatedMethod,
		ValidatedFormat:  i.ValidatedFormat,
		ValidatedQuality: i.ValidatedQuality,
	}).First(&cache)
	log.Debugln(cache.ID)
	if cache.ID != 0 {
		log.Infof("validated cache %+v exists, requested with %+v", cache, i)
		url := h.Uploader.CreateURL(cache.Filename)
		http.Redirect(resp, req, url, http.StatusSeeOther)
		return nil
	}
	log.Infof("validated cache doesn't exist, requested with %+v", i)

	// 5. 元画像を取得する
	// 6. リサイズの前処理をする
	filename, err := fetcher.Fetch(i.ValidatedURL)
	defer func() {
		if err := fetcher.Clean(filename); err != nil {
			log.Errorf("fail to clean fetched file: %s", filename)
		}
	}()
	if err != nil {
		return err
	}
	var b []byte
	buf := bytes.NewBuffer(b)
	p := processor.New()
	pixels, err := p.Preprocess(filename)
	if err != nil {
		return err
	}

	// 7. 正規化する
	// 8. 正規化済みのオプションでリサイズをしたことがあるか調べる
	// 9. あればリサイズ画像のURLにリダイレクトする
	i, err = i.Normalize(pixels.Bounds().Size())
	if err != nil {
		return err
	}
	cache = storage.Image{}
	h.Storage.Where(&storage.Image{
		NormalizedHash:   i.NormalizedHash,
		DestWidth:        i.DestWidth,
		DestHeight:       i.DestHeight,
		ValidatedMethod:  i.ValidatedMethod,
		ValidatedFormat:  i.ValidatedFormat,
		ValidatedQuality: i.ValidatedQuality,
	}).First(&cache)
	if cache.ID != 0 {
		log.Infof("normalized cache %+v exists, requested with %+v", cache, i)
		url := h.Uploader.CreateURL(cache.Filename)
		http.Redirect(resp, req, url, http.StatusSeeOther)
		return nil
	}
	log.Infof("normalized cache doesn't exist, requested with %+v", i)

	// 10. リサイズする
	// 11. ファイルオブジェクトの処理結果フィールドを埋める
	// 12. レスポンスする
	size, err := p.Process(pixels, buf, i)
	if err != nil {
		return err
	}
	b = buf.Bytes()

	i.ETag = fmt.Sprintf("%x", md5.Sum(b))
	i.Filename = i.CreateFilename()
	i.ContentType = contentTypes[i.ValidatedFormat]
	i.CanvasWidth = size.X
	i.CanvasHeight = size.Y

	resp.Header().Add("Content-Type", i.ContentType)
	io.Copy(resp, bufio.NewReader(buf))

	// レスポンスを完了させるために非同期に処理する
	go h.save(b, i)

	return nil
}