package main

import (
    //"encoding/json"
    "fmt"
    //"os"
    //"io/ioutil"
    "github.com/nfnt/resize"
    "image/jpeg"
    "io"
    "log"
    "os"
    "path/filepath"
    "strconv"
    // "flag"
    "bufio"
    "image"
    "image/png"
    "strings"
    "time"
)

func imageCompress(
    getReadSizeFile func() (io.Reader, error),
    getDecodeFile func() (*os.File, error),
    to string,
    Quality,
    base int,
    format string) bool {
    /** 读取文件 */
    file_origin, err := getDecodeFile()
    defer file_origin.Close()
    if err != nil {
        fmt.Println("os.Open(file)错误")
        log.Fatal(err)
        return false
    }
    var origin image.Image
    var config image.Config
    var temp io.Reader
    /** 读取尺寸 */
    temp, err = getReadSizeFile()
    if err != nil {
        fmt.Println("os.Open(temp)")
        log.Fatal(err)
        return false
    }
    var typeImage int64
    format = strings.ToLower(format)
    /** jpg 格式 */
    if format == "jpg" || format == "jpeg" {
        typeImage = 1
        origin, err = jpeg.Decode(file_origin)
        if err != nil {
            fmt.Println("jpeg.Decode(file_origin)")
            log.Fatal(err)
            return false
        }
        temp, err = getReadSizeFile()
        if err != nil {
            fmt.Println("os.Open(temp)")
            log.Fatal(err)
            return false
        }
        config, err = jpeg.DecodeConfig(temp)
        if err != nil {
            fmt.Println("jpeg.DecodeConfig(temp)")
            return false
        }
    } else if format == "png" {
        typeImage = 0
        origin, err = png.Decode(file_origin)
        if err != nil {
            fmt.Println("png.Decode(file_origin)")
            log.Fatal(err)
            return false
        }
        temp, err = getReadSizeFile()
        if err != nil {
            fmt.Println("os.Open(temp)")
            log.Fatal(err)
            return false
        }
        config, err = png.DecodeConfig(temp)
        if err != nil {
            fmt.Println("png.DecodeConfig(temp)")
            return false
        }
    }
    /** 做等比缩放 */
    width := uint(base) /** 基准 */
    height := uint(base * config.Height / config.Width)

canvas := resize.Thumbnail(width, height, origin, resize.Lanczos3)
    file_out, err := os.Create(to)
    defer file_out.Close()
    if err != nil {
        log.Fatal(err)
        return false
    }
    if typeImage == 0 {
        err = png.Encode(file_out, canvas)
        if err != nil {
            fmt.Println("压缩图片失败")
            return false
        }
    } else {
        err = jpeg.Encode(file_out, canvas, &jpeg.Options{Quality})
        if err != nil {
            fmt.Println("压缩图片失败")
            return false
        }
    }

return true
}

func getFilelist(path string) {
    /** 创建输出目录 */
    errC := os.MkdirAll(inputArgs.OutputPath, 0777)
    if errC != nil {
        fmt.Printf("%s", errC)
        return
    }
    err := filepath.Walk(path, func(pathFound string, f os.FileInfo, err error) error {
        if f == nil {
            return err
        }
        if f.IsDir() { /** 是否是目录 */
            return nil
        }
        // println(pathFound)
        /** 找到一个文件 */
        /** 判断是不是图片 */
        localPath, format, _ := isPictureFormat(pathFound)
        /** 随机数 */
        t := time.Now()
        millis := t.Nanosecond() /** 纳秒 */
        outputPath := inputArgs.OutputPath + strconv.FormatInt(int64(millis), 10) + "." + format
        if localPath != "" {
            if !imageCompress(
                func() (io.Reader, error) {
                    return os.Open(localPath)
                },
                func() (*os.File, error) {
                    return os.Open(localPath)
                },
                outputPath,
                inputArgs.Quality,
                inputArgs.Width,
                format) {
                fmt.Println("生成缩略图失败")
            } else {
                fmt.Println("生成缩略图成功 " + outputPath)
            }
        }
        return nil
    })
    if err != nil {
        fmt.Printf("输入的路径信息有误 %v\n", err)
    }
}

/** 是否是图片 */
func isPictureFormat(path string) (string, string, string) {
    temp := strings.Split(path, ".")
    if len(temp) <= 1 {
        return "", "", ""
    }
    mapRule := make(map[string]int64)
    mapRule["jpg"] = 1
    mapRule["png"] = 1
    mapRule["jpeg"] = 1
    // fmt.Println(temp[1]+"---")
    /** 添加其他格式 */
    if mapRule[temp[1]] == 1 {
        println(temp[1])
        return path, temp[1], temp[0]
    } else {
        return "", "", ""
    }
}

func execute() {
    /** 获取输入 */
    //str := ""
    //fmt.Scanln (&str) /** 不要使用 scanf,它不会并以一个新行结束输入 */

reader := bufio.NewReader(os.Stdin)
    data, _, _ := reader.ReadLine()
    /** 分割 */
    strPice := strings.Split(string(data), " ") /** 空格 */
    if len(strPice) < 3 {
        fmt.Printf("输入有误,参数数量不足,请重新输入或退出程序:")
        execute()
        return
    }

inputArgs.LocalPath = strPice[0]
    inputArgs.Quality, _ = strconv.Atoi(strPice[1])
    inputArgs.Width, _ = strconv.Atoi(strPice[2])

pathTemp, format, top := isPictureFormat(inputArgs.LocalPath)
    if pathTemp == "" {
        /** 目录 */
        /** 如果输入目录,那么是批量 */
        fmt.Println("开始批量压缩...")
        rs := []rune(inputArgs.LocalPath)
        end := len(rs)
        substr := string(rs[end-1 : end])
        if substr == "/" {
            /** 有 / */
            rs := []rune(inputArgs.LocalPath)
            end := len(rs)
            substr := string(rs[0 : end-1])
            endIndex := strings.LastIndex(substr, "/")
            inputArgs.OutputPath = string(rs[0:endIndex]) + "/LghImageCompress/"
        } else {
            endIndex := strings.LastIndex(inputArgs.LocalPath, "/")
            inputArgs.OutputPath = string(rs[0:endIndex]) + "/LghImageCompress/"
        }
        getFilelist(inputArgs.LocalPath)
        fmt.Println("图片保存在文件夹 " + inputArgs.OutputPath)
    } else {
        /** 单个 */
        /** 如果输入文件,那么是单个,允许自定义路径 */
        fmt.Println("开始单张压缩...") //C:\Users\lzq\Desktop\Apk.jpg 75 200
        inputArgs.OutputPath = top + "_compress." + format
        if !imageCompress(
            func() (io.Reader, error) {
                return os.Open(inputArgs.LocalPath)
            },
            func() (*os.File, error) {
                return os.Open(inputArgs.LocalPath)
            },
            inputArgs.OutputPath,
            inputArgs.Quality,
            inputArgs.Width,
            format) {
            fmt.Println("生成缩略图失败")
        } else {
            fmt.Println("生成缩略图成功 " + inputArgs.OutputPath)
            finish()
        }
    }

time.Sleep(5 * time.Minute) /** 如果不是自己点击退出,延时5分钟 */
}

func finish() {
    fmt.Printf("继续输入进行压缩或者退出程序:")
    execute()
}

func showTips() {
    tips := []string{
        "请输入文件夹或图片路径:",
        "如果输入文件夹,那么该目录的图片将会被批量压缩;",
        "如果是图片路径,那么将会被单独压缩处理。",
        "例如:",
        "C:/Users/lzq/Desktop/headImages/ 75 200",
        "指桌面 headImages 文件夹,里面的图片质量压缩到75%,宽分辨率为200,高是等比例计算",
        "C:/Users/lzq/Desktop/headImages/1.jpg 75 200",
        "指桌面的 headImages 文件夹里面的 1.jpg 图片,质量压缩到75%,宽分辨率为200,高是等比例计算 ",
        "请输入:"}
    itemLen := len(tips)
    for i := 0; i < itemLen; i++ {
        if i == itemLen-1 {
            fmt.Printf(tips[i])
        } else {
            fmt.Println(tips[i])
        }
    }
}

type InputArgs struct {
    OutputPath string /** 输出目录 */
    LocalPath  string /** 输入的目录或文件路径 */
    Quality    int    /** 质量 */
    Width      int    /** 宽度尺寸,像素单位 */
    Format     string /** 格式 */
}

var inputArgs InputArgs

func main() {
    showTips()
    execute()
    time.Sleep(5 * time.Minute) /** 如果不是自己点击退出,延时5分钟 */
}

golang图片压缩的更多相关文章

  1. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  2. 三款不错的图片压缩上传插件(webuploader+localResizeIMG4+LUploader)

    涉及到网页图片的交互,少不了图片的压缩上传,相关的插件有很多,相信大家都有用过,这里我就推荐三款,至于好处就仁者见仁喽: 1.名气最高的WebUploader,由Baidu FEX 团队开发,以H5为 ...

  3. 前端构建工具之gulp(一)「图片压缩」

    前端构建工具之gulp(一)「图片压缩」 已经很久没有写过博客了,现下终于事情少了,开始写博吧 今天网站要做一些优化:图片压缩,资源合并等 以前一直使用百度的FIS工具,但是FIS还没有提供图片压缩的 ...

  4. gulp图片压缩

    gulp图片压缩 网页性能优化,通常要处理图片,尤其图片量大的时候,更需要工具来批量处理,这里使用gulp,做个简单总结 image-resize压缩尺寸 var gulp = require('gu ...

  5. Android 图片压缩、照片选择、裁剪,上传、一整套图片解决方案

    1.Android一整套图片解决方案 http://mp.weixin.qq.com/s?__biz=MzAxMTI4MTkwNQ==&mid=2650820998&idx=1& ...

  6. Java中图片压缩处理

    原文http://cuisuqiang.iteye.com/blog/2045855 整理文档,搜刮出一个Java做图片压缩的代码,稍微整理精简一下做下分享. 首先,要压缩的图片格式不能说动态图片,你 ...

  7. android 图片压缩

    引用:http://104zz.iteye.com/blog/1694762 第一:我们先看下质量压缩方法: private Bitmap compressImage(Bitmap image) { ...

  8. HTML5 CANVAS 实现图片压缩和裁切

    原文地址:http://leonshi.com/2015/10/31/html5-canvas-image-compress-crop/?utm_source=tuicool&utm_medi ...

  9. C# 图片压缩

    /// <summary>        /// 图片压缩方法        /// </summary>        /// <param name="sF ...

随机推荐

  1. js 立即调用函数

    function makeCounter() { //不能立即执行 // 只能在makeCounter内部访问i var i = 0; return function () { console.log ...

  2. 【剑指Offer】59、按之字形顺序打印二叉树

      题目描述:   请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推.   解题思路:   这道题仍然是二 ...

  3. 类的定义与实例化、构造函数和初始化表(day04)

    十三 类的定义与实例化 类的一般形式 class/struct 类名:继承表{ 访问控制限定符: 类名(形参表):初始化表{}//构造函数 ~类名(void){}//析构函数 返回类型 函数名(形参表 ...

  4. ecshop中{$lang.}标签的修改

    {$lang.}之类的文字都是在语言包里边定义的,所以要修改这些文字的话,我们只需要修改语言包里的文件.首先需要看一下你使用的语言是哪种,如果是中文的话,修改  languages/zh_cn/com ...

  5. Bootstrap 表单控件状态(验证状态)

    在制作表单时,不免要做表单验证.同样也需要提供验证状态样式,在Bootstrap框架中同样提供这几种效果.1..has-warning:警告状态(黄色)2..has-error:错误状态(红色)3.. ...

  6. ecshop3 调用指定分类下推荐/热卖/新品商品,可指定调用数量

    第一步:--------------------------------------------------------------------------------------/** * 取指定分 ...

  7. 微信小程序获取登录手机号

    小程序获取登录用户手机号. 因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 <button> 组件的点击来触发. 首先,放置一个 button 按钮,将 ...

  8. 【hihocoder 1329】平衡树·Splay(Splay做法)

    [题目链接]:http://hihocoder.com/problemset/problem/1329 [题意] [题解] 插入操作:-,记住每次插入之后都要把它放到根节点去就好; 询问操作:对于询问 ...

  9. 关于约束ENABLE NOVALIDATE的一个疑问

    http://www.dbunix.com/?p=188 关于约束ENABLE NOVALIDATE的一个疑问 CREATE TABLE test (id varchar2(12), name var ...

  10. 使用ZooKeeper实现配置同步(转)

    前言 应用项目中都会有一些配置信息,这些配置信息数据量少,一般会保存到内存.文件或者数据库,有时候需要动态更新.当需要在多个应用服务器中修改这些配置文件时,需要做到快速.简单.不停止应用服务器的方式修 ...