diff --git a/App/Functions/DocumentInspector/ImageViewerForm.cs b/App/Functions/DocumentInspector/ImageViewerForm.cs index 72d88f0..df29d88 100644 --- a/App/Functions/DocumentInspector/ImageViewerForm.cs +++ b/App/Functions/DocumentInspector/ImageViewerForm.cs @@ -18,13 +18,24 @@ namespace PDFPatcher.Functions _ImageBox.Image = bmp.ToBitmap(); } else { + FIBITMAP b = default; try { - using FreeImageBitmap bmp = FreeImageHelper.CreateFromBytes(bytes); - _ImageBox.Image = bmp.ToBitmap(); + var isCmyk = iTextSharp.text.pdf.PdfName.DEVICECMYK.Equals(image.ColorSpace); + using var ms = new System.IO.MemoryStream(bytes); + b = FreeImage.LoadFromStream(ms, isCmyk ? FREE_IMAGE_LOAD_FLAGS.TIFF_CMYK | FREE_IMAGE_LOAD_FLAGS.JPEG_CMYK : FREE_IMAGE_LOAD_FLAGS.DEFAULT); + if (isCmyk) { + b = ConvertCmykToRgb(b, image.InvertCmyk); + } + _ImageBox.Image = FreeImage.GetBitmap(b); } catch (System.Exception ex) { this.ErrorBox("无法加载图片", ex); } + finally { + if (!b.IsNull) { + FreeImage.Unload(b); + } + } } } @@ -62,5 +73,73 @@ namespace PDFPatcher.Functions break; } } + + static FIBITMAP ConvertCmykToRgb(FIBITMAP cmykDib, bool invert) { + int width = (int)FreeImage.GetWidth(cmykDib); + int height = (int)FreeImage.GetHeight(cmykDib); + + FIBITMAP rgbDib = FreeImage.Allocate(width, height, 24, 0, 0, 0); + + FIBITMAP cChannel = FreeImage.GetChannel(cmykDib, FREE_IMAGE_COLOR_CHANNEL.FICC_BLUE); + FIBITMAP mChannel = FreeImage.GetChannel(cmykDib, FREE_IMAGE_COLOR_CHANNEL.FICC_GREEN); + FIBITMAP yChannel = FreeImage.GetChannel(cmykDib, FREE_IMAGE_COLOR_CHANNEL.FICC_RED); + FIBITMAP kChannel = FreeImage.GetChannel(cmykDib, FREE_IMAGE_COLOR_CHANNEL.FICC_ALPHA); + + unsafe { + var cPtr = (byte*)FreeImage.GetBits(cChannel); + var mPtr = (byte*)FreeImage.GetBits(mChannel); + var yPtr = (byte*)FreeImage.GetBits(yChannel); + var kPtr = (byte*)FreeImage.GetBits(kChannel); + var rgbPtr = (byte*)FreeImage.GetBits(rgbDib); + + var pitch = (int)FreeImage.GetPitch(rgbDib); + + for (int y = 0; y < height; y++) { + int rowOffset = y * pitch; + int srcBaseIdx = y * width; // 假设通道也是连续的,无行填充(通常 FreeImage 通道如此) + + for (int x = 0; x < width; x++) { + int srcIdx = srcBaseIdx + x; + int dstIdx = rowOffset + x * 3; + + // 读取原始值 + int c = cPtr[srcIdx]; + int m = mPtr[srcIdx]; + int yVal = yPtr[srcIdx]; + int k = kPtr[srcIdx]; + + // 如果需要取反(之前的逻辑) + if (invert) { + c = 255 - c; + m = 255 - m; + yVal = 255 - yVal; + k = 255 - k; + } + + // 计算红色: R = (255 - C) * (255 - K) / 255 + int r_val = ((255 - c) * (255 - k)) / 255; + + // 计算绿色: G = (255 - M) * (255 - K) / 255 + int g_val = ((255 - m) * (255 - k)) / 255; + + // 计算蓝色: B = (255 - Y) * (255 - K) / 255 + int b_val = ((255 - yVal) * (255 - k)) / 255; + + // 写入 RGB (BGR 顺序) + rgbPtr[dstIdx + 0] = (byte)b_val; + rgbPtr[dstIdx + 1] = (byte)g_val; + rgbPtr[dstIdx + 2] = (byte)r_val; + } + } + } + + FreeImage.Unload(cChannel); + FreeImage.Unload(mChannel); + FreeImage.Unload(yChannel); + FreeImage.Unload(kChannel); + FreeImage.Unload(cmykDib); + + return rgbDib; + } } }