diff --git a/internal/pkg/converter/converter.go b/internal/pkg/converter/converter.go
index c0703c8..50e85ac 100644
--- a/internal/pkg/converter/converter.go
+++ b/internal/pkg/converter/converter.go
@@ -15,6 +15,7 @@ import (
 	"reflect"
 	"regexp"
 	"runtime"
+	"slices"
 	"strings"
 	"time"
 
@@ -131,7 +132,7 @@ func (c *Converter) InitParse() {
 	c.AddStringParam(&c.Options.Image.View.Color.Foreground, "foreground-color", c.Options.Image.View.Color.Foreground, "Foreground color in hexadecimal format RGB. Black=000, White=FFF")
 	c.AddStringParam(&c.Options.Image.View.Color.Background, "background-color", c.Options.Image.View.Color.Background, "Background color in hexadecimal format RGB. Black=000, White=FFF, Light Gray=DDD, Dark Gray=777")
 	c.AddBoolParam(&c.Options.Image.Resize, "resize", c.Options.Image.Resize, "Reduce image size if exceed device size")
-	c.AddStringParam(&c.Options.Image.Format, "format", c.Options.Image.Format, "Format of output images: jpeg (lossy), png (lossless)")
+	c.AddStringParam(&c.Options.Image.Format, "format", c.Options.Image.Format, "Format of output images: jpeg (lossy), png (lossless), copy (no processing)")
 	c.AddFloatParam(&c.Options.Image.View.AspectRatio, "aspect-ratio", c.Options.Image.View.AspectRatio, "Aspect ratio (height/width) of the output\n -1 = same as device\n  0 = same as source\n1.6 = amazon advice for kindle")
 	c.AddBoolParam(&c.Options.Image.View.PortraitOnly, "portrait-only", c.Options.Image.View.PortraitOnly, "Portrait only: force orientation to portrait only.")
 	c.AddIntParam(&c.Options.TitlePage, "titlepage", c.Options.TitlePage, "Title page\n0 = never\n1 = always\n2 = only if epub is split")
@@ -379,8 +380,8 @@ func (c *Converter) Validate() error {
 	}
 
 	// Format
-	if !(c.Options.Image.Format == "jpeg" || c.Options.Image.Format == "png") {
-		return errors.New("format should be jpeg or png")
+	if !slices.Contains([]string{"jpeg", "png", "copy"}, c.Options.Image.Format) {
+		return errors.New("format should be jpeg, png or copy")
 	}
 
 	// Aspect Ratio
diff --git a/internal/pkg/epubimage/epub_image.go b/internal/pkg/epubimage/epub_image.go
index 578e933..eb61663 100644
--- a/internal/pkg/epubimage/epub_image.go
+++ b/internal/pkg/epubimage/epub_image.go
@@ -73,6 +73,11 @@ func (i EPUBImage) EPUBImgPath() string {
 	return "OEBPS/" + i.ImgPath()
 }
 
+// MediaType of the epub image
+func (i EPUBImage) MediaType() string {
+	return "image/" + i.Format
+}
+
 // ImgStyle style to apply to the image.
 //
 // center by default.
diff --git a/internal/pkg/epubimagepassthrough/passthrough.go b/internal/pkg/epubimagepassthrough/passthrough.go
new file mode 100644
index 0000000..93a5297
--- /dev/null
+++ b/internal/pkg/epubimagepassthrough/passthrough.go
@@ -0,0 +1,432 @@
+package epubimagepassthrough
+
+import (
+	"archive/zip"
+	"bytes"
+	"errors"
+	"fmt"
+	"image"
+	"image/jpeg"
+	"image/png"
+	"io"
+	"io/fs"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
+	"github.com/nwaples/rardecode/v2"
+
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimage"
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimageprocessor"
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubprogress"
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubzip"
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/sortpath"
+	"github.com/celogeek/go-comic-converter/v3/pkg/epuboptions"
+)
+
+type ePUBImagePassthrough struct {
+	epuboptions.EPUBOptions
+}
+
+func (e ePUBImagePassthrough) Load() (images []epubimage.EPUBImage, err error) {
+	fi, err := os.Stat(e.Input)
+	if err != nil {
+		return
+	}
+
+	if fi.IsDir() {
+		return e.loadDir()
+	} else {
+		switch ext := strings.ToLower(filepath.Ext(e.Input)); ext {
+		case ".cbz", ".zip":
+			return e.loadCbz()
+		case ".cbr", ".rar":
+			return e.loadCbr()
+		default:
+			return nil, fmt.Errorf("unknown file format (%s): support .cbz, .zip, .cbr, .rar", ext)
+		}
+	}
+}
+
+func (e ePUBImagePassthrough) CoverTitleData(o epubimageprocessor.CoverTitleDataOptions) (epubzip.Image, error) {
+	return epubimageprocessor.New(e.EPUBOptions).CoverTitleData(o)
+}
+
+var errNoImagesFound = errors.New("no images found")
+
+func New(o epuboptions.EPUBOptions) epubimageprocessor.EPUBImageProcessor {
+	return ePUBImagePassthrough{o}
+}
+
+func (e ePUBImagePassthrough) loadDir() (images []epubimage.EPUBImage, err error) {
+	imagesPath := make([]string, 0)
+
+	input := filepath.Clean(e.Input)
+	err = filepath.WalkDir(input, func(path string, d fs.DirEntry, err error) error {
+		if err != nil {
+			return err
+		}
+
+		if !d.IsDir() && e.isSupportedImage(path) {
+			imagesPath = append(imagesPath, path)
+		}
+
+		return nil
+	})
+
+	if err != nil {
+		return
+	}
+
+	if len(imagesPath) == 0 {
+		err = errNoImagesFound
+		return
+	}
+
+	sort.Sort(sortpath.By(imagesPath, e.SortPathMode))
+
+	var imgStorage epubzip.StorageImageWriter
+	imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format)
+	if err != nil {
+		return
+	}
+	defer imgStorage.Close()
+
+	// processing
+	bar := epubprogress.New(epubprogress.Options{
+		Quiet:       e.Quiet,
+		Json:        e.Json,
+		Max:         len(imagesPath),
+		Description: "Copying",
+		CurrentJob:  1,
+		TotalJob:    2,
+	})
+	defer bar.Close()
+
+	for i, imgPath := range imagesPath {
+
+		var img epubimage.EPUBImage
+		img, err = e.copyRawDataToStorage(
+			imgStorage,
+			func() ([]byte, error) {
+				f, err := os.Open(imgPath)
+				if err != nil {
+					return nil, err
+				}
+				defer f.Close()
+				return io.ReadAll(f)
+			},
+			i,
+			input,
+			imgPath,
+		)
+		if err != nil {
+			return
+		}
+
+		images = append(images, img)
+		_ = bar.Add(1)
+	}
+
+	if len(images) == 0 {
+		err = errNoImagesFound
+	}
+
+	return
+
+}
+
+func (e ePUBImagePassthrough) loadCbz() (images []epubimage.EPUBImage, err error) {
+	images = make([]epubimage.EPUBImage, 0)
+
+	input := filepath.Clean(e.Input)
+	r, err := zip.OpenReader(input)
+	if err != nil {
+		return
+	}
+	defer r.Close()
+
+	imagesZip := make([]*zip.File, 0)
+	for _, f := range r.File {
+		if !f.FileInfo().IsDir() && e.isSupportedImage(f.Name) {
+			imagesZip = append(imagesZip, f)
+		}
+	}
+
+	if len(imagesZip) == 0 {
+		err = errNoImagesFound
+		return
+	}
+
+	var names []string
+	for _, img := range imagesZip {
+		names = append(names, img.Name)
+	}
+
+	sort.Sort(sortpath.By(names, e.SortPathMode))
+
+	indexedNames := make(map[string]int)
+	for i, name := range names {
+		indexedNames[name] = i
+	}
+
+	var imgStorage epubzip.StorageImageWriter
+	imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format)
+	if err != nil {
+		return
+	}
+	defer imgStorage.Close()
+
+	// processing
+	bar := epubprogress.New(epubprogress.Options{
+		Quiet:       e.Quiet,
+		Json:        e.Json,
+		Max:         len(imagesZip),
+		Description: "Copying",
+		CurrentJob:  1,
+		TotalJob:    2,
+	})
+	defer bar.Close()
+
+	for _, imgZip := range imagesZip {
+		if _, ok := indexedNames[imgZip.Name]; !ok {
+			continue
+		}
+
+		var img epubimage.EPUBImage
+		img, err = e.copyRawDataToStorage(
+			imgStorage,
+			func() ([]byte, error) {
+				f, err := imgZip.Open()
+				if err != nil {
+					return nil, err
+				}
+				defer f.Close()
+
+				return io.ReadAll(f)
+			},
+			indexedNames[imgZip.Name],
+			"",
+			imgZip.Name,
+		)
+
+		if err != nil {
+			return
+		}
+
+		images = append(images, img)
+		_ = bar.Add(1)
+	}
+
+	if len(images) == 0 {
+		err = errNoImagesFound
+	}
+
+	return
+}
+
+func (e ePUBImagePassthrough) loadCbr() (images []epubimage.EPUBImage, err error) {
+	images = make([]epubimage.EPUBImage, 0)
+
+	var isSolid bool
+	files, err := rardecode.List(e.Input)
+	if err != nil {
+		return
+	}
+
+	names := make([]string, 0)
+	for _, f := range files {
+		if !f.IsDir && e.isSupportedImage(f.Name) {
+			if f.Solid {
+				isSolid = true
+			}
+			names = append(names, f.Name)
+		}
+	}
+
+	if len(names) == 0 {
+		err = errNoImagesFound
+		return
+	}
+
+	sort.Sort(sortpath.By(names, e.SortPathMode))
+
+	indexedNames := make(map[string]int)
+	for i, name := range names {
+		indexedNames[name] = i
+	}
+
+	var imgStorage epubzip.StorageImageWriter
+	imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format)
+	if err != nil {
+		return
+	}
+	defer imgStorage.Close()
+
+	// processing
+	bar := epubprogress.New(epubprogress.Options{
+		Quiet:       e.Quiet,
+		Json:        e.Json,
+		Max:         len(names),
+		Description: "Copying",
+		CurrentJob:  1,
+		TotalJob:    2,
+	})
+	defer bar.Close()
+
+	if isSolid {
+		var r *rardecode.ReadCloser
+		r, err = rardecode.OpenReader(e.Input)
+		if err != nil {
+			return
+		}
+		defer r.Close()
+
+		for {
+			f, rerr := r.Next()
+			if rerr != nil {
+				if rerr == io.EOF {
+					break
+				}
+				err = rerr
+				return
+			}
+
+			if _, ok := indexedNames[f.Name]; !ok {
+				continue
+			}
+
+			var img epubimage.EPUBImage
+			img, err = e.copyRawDataToStorage(
+				imgStorage,
+				func() ([]byte, error) {
+					return io.ReadAll(r)
+				},
+				indexedNames[f.Name],
+				"",
+				f.Name,
+			)
+
+			if err != nil {
+				return
+			}
+
+			images = append(images, img)
+			_ = bar.Add(1)
+		}
+	} else {
+		for _, file := range files {
+			if i, ok := indexedNames[file.Name]; ok {
+				var img epubimage.EPUBImage
+				img, err = e.copyRawDataToStorage(
+					imgStorage,
+					func() ([]byte, error) {
+						f, err := file.Open()
+						if err != nil {
+							return nil, err
+						}
+						defer f.Close()
+						return io.ReadAll(f)
+					},
+					i,
+					"",
+					file.Name,
+				)
+
+				if err != nil {
+					return
+				}
+
+				images = append(images, img)
+				_ = bar.Add(1)
+			}
+		}
+	}
+
+	if len(images) == 0 {
+		err = errNoImagesFound
+	}
+
+	return
+}
+
+func (e ePUBImagePassthrough) isSupportedImage(path string) bool {
+	switch strings.ToLower(filepath.Ext(path)) {
+	case ".jpg", ".jpeg", ".png":
+		{
+			return !strings.HasPrefix(filepath.Base(path), ".")
+		}
+	}
+	return false
+}
+
+func (e ePUBImagePassthrough) copyRawDataToStorage(
+	imgStorage epubzip.StorageImageWriter,
+	getData func() ([]byte, error),
+	id int,
+	dirname string,
+	filename string,
+) (img epubimage.EPUBImage, err error) {
+	var uncompressedData []byte
+	uncompressedData, err = getData()
+	if err != nil {
+		return
+	}
+
+	p, fn := filepath.Split(filepath.Clean(filename))
+	if p == dirname {
+		p = ""
+	} else {
+		p = p[len(dirname)+1:]
+	}
+
+	var (
+		format       string
+		decodeConfig func(r io.Reader) (image.Config, error)
+		decode       func(r io.Reader) (image.Image, error)
+	)
+
+	switch filepath.Ext(fn) {
+	case ".png":
+		format = "png"
+		decodeConfig = png.DecodeConfig
+		decode = png.Decode
+	case ".jpg", ".jpeg":
+		format = "jpeg"
+		decodeConfig = jpeg.DecodeConfig
+		decode = jpeg.Decode
+	}
+
+	var config image.Config
+	config, err = decodeConfig(bytes.NewReader(uncompressedData))
+	if err != nil {
+		return
+	}
+
+	var rawImage image.Image
+	if id == 0 {
+		rawImage, err = decode(bytes.NewReader(uncompressedData))
+		if err != nil {
+			return
+		}
+	}
+
+	img = epubimage.EPUBImage{
+		Id:                  id,
+		Part:                0,
+		Raw:                 rawImage,
+		Width:               config.Width,
+		Height:              config.Height,
+		IsBlank:             false,
+		DoublePage:          config.Width > config.Height,
+		Path:                p,
+		Name:                fn,
+		Format:              format,
+		OriginalAspectRatio: float64(config.Height) / float64(config.Width),
+	}
+
+	err = imgStorage.AddRaw(img.EPUBImgPath(), uncompressedData)
+
+	return
+}
diff --git a/internal/pkg/epubimageprocessor/loader.go b/internal/pkg/epubimageprocessor/loader.go
index a120385..d6848fb 100644
--- a/internal/pkg/epubimageprocessor/loader.go
+++ b/internal/pkg/epubimageprocessor/loader.go
@@ -43,7 +43,7 @@ type task struct {
 var errNoImagesFound = errors.New("no images found")
 
 // only accept jpg, png and webp as source file
-func (e EPUBImageProcessor) isSupportedImage(path string) bool {
+func (e ePUBImageProcessor) isSupportedImage(path string) bool {
 	switch strings.ToLower(filepath.Ext(path)) {
 	case ".jpg", ".jpeg", ".png", ".webp", ".tiff":
 		{
@@ -53,8 +53,8 @@ func (e EPUBImageProcessor) isSupportedImage(path string) bool {
 	return false
 }
 
-// Load images from input
-func (e EPUBImageProcessor) load() (totalImages int, output chan task, err error) {
+// load images from input
+func (e ePUBImageProcessor) load() (totalImages int, output chan task, err error) {
 	fi, err := os.Stat(e.Input)
 	if err != nil {
 		return
@@ -78,7 +78,7 @@ func (e EPUBImageProcessor) load() (totalImages int, output chan task, err error
 	}
 }
 
-func (e EPUBImageProcessor) corruptedImage(path, name string) image.Image {
+func (e ePUBImageProcessor) corruptedImage(path, name string) image.Image {
 	var w, h float64 = 1200, 1920
 	f, _ := truetype.Parse(gomonobold.TTF)
 	face := truetype.NewFace(f, &truetype.Options{Size: 64, DPI: 72})
@@ -102,7 +102,7 @@ func (e EPUBImageProcessor) corruptedImage(path, name string) image.Image {
 }
 
 // load a directory of images
-func (e EPUBImageProcessor) loadDir() (totalImages int, output chan task, err error) {
+func (e ePUBImageProcessor) loadDir() (totalImages int, output chan task, err error) {
 	images := make([]string, 0)
 
 	input := filepath.Clean(e.Input)
@@ -191,7 +191,7 @@ func (e EPUBImageProcessor) loadDir() (totalImages int, output chan task, err er
 }
 
 // load a zip file that include images
-func (e EPUBImageProcessor) loadCbz() (totalImages int, output chan task, err error) {
+func (e ePUBImageProcessor) loadCbz() (totalImages int, output chan task, err error) {
 	r, err := zip.OpenReader(e.Input)
 	if err != nil {
 		return
@@ -277,7 +277,7 @@ func (e EPUBImageProcessor) loadCbz() (totalImages int, output chan task, err er
 }
 
 // load a rar file that include images
-func (e EPUBImageProcessor) loadCbr() (totalImages int, output chan task, err error) {
+func (e ePUBImageProcessor) loadCbr() (totalImages int, output chan task, err error) {
 	var isSolid bool
 	files, err := rardecode.List(e.Input)
 	if err != nil {
@@ -393,7 +393,7 @@ func (e EPUBImageProcessor) loadCbr() (totalImages int, output chan task, err er
 }
 
 // extract image from a pdf
-func (e EPUBImageProcessor) loadPdf() (totalImages int, output chan task, err error) {
+func (e ePUBImageProcessor) loadPdf() (totalImages int, output chan task, err error) {
 	pdf := pdfread.Load(e.Input)
 	if pdf == nil {
 		err = fmt.Errorf("can't read pdf")
diff --git a/internal/pkg/epubimageprocessor/processor.go b/internal/pkg/epubimageprocessor/processor.go
index bb2c368..ad2adf6 100644
--- a/internal/pkg/epubimageprocessor/processor.go
+++ b/internal/pkg/epubimageprocessor/processor.go
@@ -17,16 +17,21 @@ import (
 	"github.com/celogeek/go-comic-converter/v3/pkg/epuboptions"
 )
 
-type EPUBImageProcessor struct {
+type EPUBImageProcessor interface {
+	Load() (images []epubimage.EPUBImage, err error)
+	CoverTitleData(o CoverTitleDataOptions) (epubzip.Image, error)
+}
+
+type ePUBImageProcessor struct {
 	epuboptions.EPUBOptions
 }
 
 func New(o epuboptions.EPUBOptions) EPUBImageProcessor {
-	return EPUBImageProcessor{o}
+	return ePUBImageProcessor{o}
 }
 
 // Load extract and convert images
-func (e EPUBImageProcessor) Load() (images []epubimage.EPUBImage, err error) {
+func (e ePUBImageProcessor) Load() (images []epubimage.EPUBImage, err error) {
 	images = make([]epubimage.EPUBImage, 0)
 	imageCount, imageInput, err := e.load()
 	if err != nil {
@@ -136,7 +141,7 @@ func (e EPUBImageProcessor) Load() (images []epubimage.EPUBImage, err error) {
 	return images, nil
 }
 
-func (e EPUBImageProcessor) createImage(src image.Image, r image.Rectangle) draw.Image {
+func (e ePUBImageProcessor) createImage(src image.Image, r image.Rectangle) draw.Image {
 	if e.EPUBOptions.Image.GrayScale {
 		return image.NewGray(r)
 	}
@@ -169,7 +174,7 @@ func (e EPUBImageProcessor) createImage(src image.Image, r image.Rectangle) draw
 
 // transform image into 1 or 3 images
 // only doublepage with autosplit has 3 versions
-func (e EPUBImageProcessor) transformImage(input task, part int, right bool) epubimage.EPUBImage {
+func (e ePUBImageProcessor) transformImage(input task, part int, right bool) epubimage.EPUBImage {
 	g := gift.New()
 	src := input.Image
 	srcBounds := src.Bounds()
@@ -286,7 +291,7 @@ type CoverTitleDataOptions struct {
 	BorderSize  int
 }
 
-func (e EPUBImageProcessor) Cover16LevelOfGray(bounds image.Rectangle) draw.Image {
+func (e ePUBImageProcessor) cover16LevelOfGray(bounds image.Rectangle) draw.Image {
 	return image.NewPaletted(bounds, color.Palette{
 		color.Gray{},
 		color.Gray{Y: 0x11},
@@ -308,20 +313,20 @@ func (e EPUBImageProcessor) Cover16LevelOfGray(bounds image.Rectangle) draw.Imag
 }
 
 // CoverTitleData create a title page with the cover
-func (e EPUBImageProcessor) CoverTitleData(o CoverTitleDataOptions) (epubzip.Image, error) {
+func (e ePUBImageProcessor) CoverTitleData(o CoverTitleDataOptions) (epubzip.Image, error) {
 	// Create a blur version of the cover
 	g := gift.New(epubimagefilters.CoverTitle(o.Text, o.Align, o.PctWidth, o.PctMargin, o.MaxFontSize, o.BorderSize))
 	var dst draw.Image
 	if o.Name == "cover" && e.Image.GrayScale {
-		dst = e.Cover16LevelOfGray(o.Src.Bounds())
+		dst = e.cover16LevelOfGray(o.Src.Bounds())
 	} else {
 		dst = e.createImage(o.Src, g.Bounds(o.Src.Bounds()))
 	}
 	g.Draw(dst, o.Src)
 
 	return epubzip.CompressImage(
-		"OEBPS/Images/"+o.Name+"."+e.Image.Format,
-		e.Image.Format,
+		"OEBPS/Images/"+o.Name+".jpeg",
+		"jpeg",
 		dst,
 		e.Image.Quality,
 	)
diff --git a/internal/pkg/epubtemplates/content.go b/internal/pkg/epubtemplates/content.go
index 7de258d..abd87f9 100644
--- a/internal/pkg/epubtemplates/content.go
+++ b/internal/pkg/epubtemplates/content.go
@@ -144,7 +144,7 @@ func (o Content) getManifest() []tag {
 	var imageTags, pageTags, spaceTags []tag
 	addTag := func(img epubimage.EPUBImage, withSpace bool) {
 		imageTags = append(imageTags,
-			tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": o.ImageOptions.MediaType()}, ""},
+			tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": img.MediaType()}, ""},
 		)
 		pageTags = append(pageTags,
 			tag{"item", tagAttrs{"id": img.PageKey(), "href": img.PagePath(), "media-type": "application/xhtml+xml"}, ""},
@@ -160,13 +160,13 @@ func (o Content) getManifest() []tag {
 		{"item", tagAttrs{"id": "toc", "href": "toc.xhtml", "properties": "nav", "media-type": "application/xhtml+xml"}, ""},
 		{"item", tagAttrs{"id": "css", "href": "Text/style.css", "media-type": "text/css"}, ""},
 		{"item", tagAttrs{"id": "page_cover", "href": "Text/cover.xhtml", "media-type": "application/xhtml+xml"}, ""},
-		{"item", tagAttrs{"id": "img_cover", "href": "Images/cover." + o.ImageOptions.Format, "media-type": o.ImageOptions.MediaType()}, ""},
+		{"item", tagAttrs{"id": "img_cover", "href": "Images/cover.jpeg", "media-type": "image/jpeg"}, ""},
 	}
 
 	if o.HasTitlePage {
 		items = append(items,
 			tag{"item", tagAttrs{"id": "page_title", "href": "Text/title.xhtml", "media-type": "application/xhtml+xml"}, ""},
-			tag{"item", tagAttrs{"id": "img_title", "href": "Images/title." + o.ImageOptions.Format, "media-type": o.ImageOptions.MediaType()}, ""},
+			tag{"item", tagAttrs{"id": "img_title", "href": "Images/title.jpeg", "media-type": "image/jpeg"}, ""},
 		)
 
 		if !o.ImageOptions.View.PortraitOnly {
diff --git a/internal/pkg/epubzip/image.go b/internal/pkg/epubzip/image.go
index df87c4f..af479a6 100644
--- a/internal/pkg/epubzip/image.go
+++ b/internal/pkg/epubzip/image.go
@@ -66,3 +66,39 @@ func CompressImage(filename string, format string, img image.Image, quality int)
 		cdata.Bytes(),
 	}, nil
 }
+
+func CompressRaw(filename string, uncompressedData []byte) (Image, error) {
+	var (
+		cdata bytes.Buffer
+		err   error
+	)
+	wcdata, err := flate.NewWriter(&cdata, flate.BestCompression)
+	if err != nil {
+		return Image{}, err
+	}
+
+	_, err = wcdata.Write(uncompressedData)
+	if err != nil {
+		return Image{}, err
+	}
+
+	err = wcdata.Close()
+	if err != nil {
+		return Image{}, err
+	}
+
+	t := time.Now()
+	//goland:noinspection GoDeprecation
+	return Image{
+		&zip.FileHeader{
+			Name:               filename,
+			CompressedSize64:   uint64(cdata.Len()),
+			UncompressedSize64: uint64(len(uncompressedData)),
+			CRC32:              crc32.Checksum(uncompressedData, crc32.IEEETable),
+			Method:             zip.Deflate,
+			ModifiedTime:       uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11),
+			ModifiedDate:       uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9),
+		},
+		cdata.Bytes(),
+	}, nil
+}
diff --git a/internal/pkg/epubzip/storage_image_writer.go b/internal/pkg/epubzip/storage_image_writer.go
index ccec171..e19b3f2 100644
--- a/internal/pkg/epubzip/storage_image_writer.go
+++ b/internal/pkg/epubzip/storage_image_writer.go
@@ -50,3 +50,24 @@ func (e StorageImageWriter) Add(filename string, img image.Image, quality int) e
 
 	return nil
 }
+
+func (e StorageImageWriter) AddRaw(filename string, uncompressedData []byte) error {
+	zipImage, err := CompressRaw(filename, uncompressedData)
+
+	if err != nil {
+		return err
+	}
+
+	e.mut.Lock()
+	defer e.mut.Unlock()
+	fh, err := e.fz.CreateRaw(zipImage.Header)
+	if err != nil {
+		return err
+	}
+	_, err = fh.Write(zipImage.Data)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/pkg/epub/epub.go b/pkg/epub/epub.go
index debba78..1861b1c 100644
--- a/pkg/epub/epub.go
+++ b/pkg/epub/epub.go
@@ -15,6 +15,7 @@ import (
 	"github.com/gofrs/uuid"
 
 	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimage"
+	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimagepassthrough"
 	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimageprocessor"
 	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubprogress"
 	"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubtemplates"
@@ -52,13 +53,20 @@ func New(options epuboptions.EPUBOptions) EPUB {
 		"zoom": func(s int, z float32) int { return int(float32(s) * z) },
 	})
 
+	var imageProcessor epubimageprocessor.EPUBImageProcessor
+	if options.Image.Format == "copy" {
+		imageProcessor = epubimagepassthrough.New(options)
+	} else {
+		imageProcessor = epubimageprocessor.New(options)
+	}
+
 	return epub{
 		EPUBOptions:       options,
 		UID:               uid.String(),
 		Publisher:         "GO Comic Converter",
 		UpdatedAt:         time.Now().UTC().Format("2006-01-02T15:04:05Z"),
 		templateProcessor: tmpl,
-		imageProcessor:    epubimageprocessor.New(options),
+		imageProcessor:    imageProcessor,
 	}
 }
 
@@ -115,7 +123,7 @@ func (e epub) writeCoverImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, part,
 		[]byte(e.render(epubtemplates.Text, map[string]any{
 			"Title":      title,
 			"ViewPort":   e.Image.View.Port(),
-			"ImagePath":  "Images/cover." + e.Image.Format,
+			"ImagePath":  "Images/cover.jpeg",
 			"ImageStyle": img.ImgStyle(e.Image.View.Width, e.Image.View.Height, ""),
 		})),
 	); err != nil {
@@ -172,7 +180,7 @@ func (e epub) writeTitleImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, title
 		[]byte(e.render(epubtemplates.Text, map[string]any{
 			"Title":      title,
 			"ViewPort":   e.Image.View.Port(),
-			"ImagePath":  "Images/title." + e.Image.Format,
+			"ImagePath":  "Images/title.jpeg",
 			"ImageStyle": img.ImgStyle(e.Image.View.Width, e.Image.View.Height, titleAlign),
 		})),
 	); err != nil {
diff --git a/pkg/epuboptions/image.go b/pkg/epuboptions/image.go
index 1e78d1d..dc3f382 100644
--- a/pkg/epuboptions/image.go
+++ b/pkg/epuboptions/image.go
@@ -20,7 +20,3 @@ type Image struct {
 	Format                    string `yaml:"format" json:"format"`
 	AppleBookCompatibility    bool   `yaml:"apple_book_compatibility" json:"apple_book_compatibility"`
 }
-
-func (i Image) MediaType() string {
-	return "image/" + i.Format
-}