Merge branch 'fix-report' into 'master'

change: compress html report image with quality 50

See merge request iesqa/httprunner!136
This commit is contained in:
李隆
2025-07-28 06:01:33 +00:00
4 changed files with 21 additions and 100 deletions
+2 -2
View File
@@ -64,7 +64,7 @@ func NewGA4Client(measurementID, apiSecret string, debug ...bool) *GA4Client {
apiSecret: apiSecret, apiSecret: apiSecret,
userID: userID, userID: userID,
httpClient: &http.Client{ httpClient: &http.Client{
Timeout: 5 * time.Second, Timeout: 10 * time.Second,
}, },
debug: dbg, debug: dbg,
} }
@@ -206,6 +206,6 @@ func SendGA4Event(name string, params map[string]interface{}) {
} }
err := ga4Client.SendEvent(event) err := ga4Client.SendEvent(event)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("send GA4 event failed") log.Debug().Err(err).Msg("send GA4 event failed")
} }
} }
+1 -1
View File
@@ -1 +1 @@
v5.0.0-250724 v5.0.0-250728
+2 -3
View File
@@ -343,9 +343,8 @@ func (g *HTMLReportGenerator) encodeImageToBase64(imagePath string) string {
return "" return ""
} }
// Read and compress the image using the unified compression function // Read and compress the image with quality 50
// Enable resize with max width 800px for HTML reports compressedData, err := uixt.CompressImageFile(imagePath, 50)
compressedData, err := uixt.CompressImageFile(imagePath, true, 800)
if err != nil { if err != nil {
log.Warn().Err(err).Str("path", imagePath).Msg("failed to compress image, using original") log.Warn().Err(err).Str("path", imagePath).Msg("failed to compress image, using original")
// Fallback to original image if compression fails // Fallback to original image if compression fails
+16 -94
View File
@@ -7,7 +7,6 @@ import (
"image" "image"
"image/color" "image/color"
"image/draw" "image/draw"
"image/gif"
"image/jpeg" "image/jpeg"
"image/png" "image/png"
"math" "math"
@@ -244,8 +243,8 @@ func getScreenShotBuffer(driver IDriver) (compressedBufSource *bytes.Buffer, err
"take screenshot failed %v", err) "take screenshot failed %v", err)
} }
// compress screenshot // compress screenshot with quality 95
compressBufSource, err := compressImageBufferWithOptions(bufSource, false, 800) compressBufSource, err := compressImageBufferWithOptions(bufSource, 95)
if err != nil { if err != nil {
return nil, errors.Wrapf(code.DeviceScreenShotError, return nil, errors.Wrapf(code.DeviceScreenShotError,
"compress screenshot failed %v", err) "compress screenshot failed %v", err)
@@ -262,11 +261,7 @@ func saveScreenShot(raw *bytes.Buffer, screenshotPath string) error {
log.Error().Err(err).Msg("copy screenshot buffer failed") log.Error().Err(err).Msg("copy screenshot buffer failed")
} }
img, format, err := image.Decode(copiedBuffer) // create file
if err != nil {
return errors.Wrap(err, "decode screenshot image failed")
}
file, err := os.Create(screenshotPath) file, err := os.Create(screenshotPath)
if err != nil { if err != nil {
return errors.Wrap(err, "create screenshot image file failed") return errors.Wrap(err, "create screenshot image file failed")
@@ -275,26 +270,10 @@ func saveScreenShot(raw *bytes.Buffer, screenshotPath string) error {
_ = file.Close() _ = file.Close()
}() }()
// compress image and save to file // directly write compressed JPEG data to avoid quality loss
switch format { _, err = file.Write(copiedBuffer.Bytes())
case "jpeg":
jpegOptions := &jpeg.Options{Quality: 95}
err = jpeg.Encode(file, img, jpegOptions)
case "png":
encoder := png.Encoder{
CompressionLevel: png.BestCompression,
}
err = encoder.Encode(file, img)
case "gif":
gifOptions := &gif.Options{
NumColors: 256,
}
err = gif.Encode(file, img, gifOptions)
default:
return fmt.Errorf("unsupported image format %s", format)
}
if err != nil { if err != nil {
return errors.Wrap(err, "save image file failed") return errors.Wrap(err, "write image file failed")
} }
var fileSize int64 var fileSize int64
@@ -303,14 +282,14 @@ func saveScreenShot(raw *bytes.Buffer, screenshotPath string) error {
fileSize = fileInfo.Size() fileSize = fileInfo.Size()
} }
log.Info().Str("path", screenshotPath). log.Info().Str("path", screenshotPath).
Int("rawBytes", raw.Len()).Int64("saveBytes", fileSize). Int64("fileSize", fileSize).
Msg("save screenshot file success") Msg("save screenshot file success")
return nil return nil
} }
// compressImageBufferWithOptions compresses image buffer with advanced options // compressImageBufferWithOptions compresses image buffer with advanced options
func compressImageBufferWithOptions(raw *bytes.Buffer, enableResize bool, maxWidth int) (compressed *bytes.Buffer, err error) { func compressImageBufferWithOptions(raw *bytes.Buffer, quality int) (compressed *bytes.Buffer, err error) {
rawSize := raw.Len() rawSize := raw.Len()
// decode image from buffer // decode image from buffer
img, format, err := image.Decode(raw) img, format, err := image.Decode(raw)
@@ -318,32 +297,12 @@ func compressImageBufferWithOptions(raw *bytes.Buffer, enableResize bool, maxWid
return nil, err return nil, err
} }
// Get original image dimensions
bounds := img.Bounds()
originalWidth := bounds.Dx()
originalHeight := bounds.Dy()
// Calculate new dimensions for compression if resize is enabled
var newWidth, newHeight int
var resizedImg image.Image = img
if enableResize && originalWidth > maxWidth {
ratio := float64(maxWidth) / float64(originalWidth)
newWidth = maxWidth
newHeight = int(float64(originalHeight) * ratio)
resizedImg = resizeImage(img, newWidth, newHeight)
} else {
newWidth = originalWidth
newHeight = originalHeight
}
jpegQuality := 95
var buf bytes.Buffer var buf bytes.Buffer
switch format { switch format {
case "jpeg", "jpg", "png": case "jpeg", "jpg", "png":
// compress with compression rate of 95 // compress with compression rate
jpegOptions := &jpeg.Options{Quality: jpegQuality} jpegOptions := &jpeg.Options{Quality: quality}
err = jpeg.Encode(&buf, resizedImg, jpegOptions) err = jpeg.Encode(&buf, img, jpegOptions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -354,55 +313,18 @@ func compressImageBufferWithOptions(raw *bytes.Buffer, enableResize bool, maxWid
compressedSize := buf.Len() compressedSize := buf.Len()
log.Debug(). log.Debug().
Int("rawSize", rawSize). Int("rawSize", rawSize).
Int("originalWidth", originalWidth). Int("quality", quality).
Int("originalHeight", originalHeight).
Int("newWidth", newWidth).
Int("newHeight", newHeight).
Int("jpegQuality", jpegQuality).
Int("compressedSize", compressedSize). Int("compressedSize", compressedSize).
Bool("resized", enableResize && originalWidth > maxWidth).
Msg("compress image buffer") Msg("compress image buffer")
// return compressed image buffer // return compressed image buffer
return &buf, nil return &buf, nil
} }
// resizeImage resizes an image using simple nearest neighbor algorithm
func resizeImage(src image.Image, width, height int) image.Image {
srcBounds := src.Bounds()
srcWidth := srcBounds.Dx()
srcHeight := srcBounds.Dy()
// Create a new image with the target dimensions
dst := image.NewRGBA(image.Rect(0, 0, width, height))
// Simple nearest neighbor resizing
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
// Map destination coordinates to source coordinates
srcX := x * srcWidth / width
srcY := y * srcHeight / height
// Ensure we don't go out of bounds
if srcX >= srcWidth {
srcX = srcWidth - 1
}
if srcY >= srcHeight {
srcY = srcHeight - 1
}
// Copy pixel from source to destination
dst.Set(x, y, src.At(srcBounds.Min.X+srcX, srcBounds.Min.Y+srcY))
}
}
return dst
}
// CompressImageFile compresses an image file and returns the compressed data // CompressImageFile compresses an image file and returns the compressed data
func CompressImageFile(imagePath string, enableResize bool, maxWidth int) ([]byte, error) { func CompressImageFile(imagePath string, quality int) ([]byte, error) {
log.Debug().Str("imagePath", imagePath).Bool("enableResize", enableResize). log.Debug().Str("imagePath", imagePath).
Int("maxWidth", maxWidth).Msg("compress image file") Int("quality", quality).Msg("compress image file")
// Read the original image file // Read the original image file
file, err := os.Open(imagePath) file, err := os.Open(imagePath)
@@ -419,7 +341,7 @@ func CompressImageFile(imagePath string, enableResize bool, maxWidth int) ([]byt
} }
// Compress using the buffer compression function // Compress using the buffer compression function
compressedBuf, err := compressImageBufferWithOptions(&buf, enableResize, maxWidth) compressedBuf, err := compressImageBufferWithOptions(&buf, quality)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to compress image: %w", err) return nil, fmt.Errorf("failed to compress image: %w", err)
} }