如何在Python中无需保存直接将尼康.NEF RAW文件加载到QImage
Hey there! Let's get that NEF embedded JPEG preview displayed in PyQt without saving it first—you're already on the right track with rawpy, so let's fix those code issues and get this working.
Why Your Previous Code Failed
Let's break down what went wrong with your attempts:
- Code Snippet 1: The
raw.postprocess()output defaults to 16-bit color depth (uint16), butQImage.Format_RGB888expects 8-bit data. Additionally, transposing the array and passing it directly without ensuring contiguous memory can cause QImage to fail to recognize the data. - Code Snippet 2: Manually parsing NEF headers is extremely error-prone—Nikon's NEF format varies across camera models, so your hardcoded offsets are almost certainly pointing to the wrong location for the JPEG data, resulting in invalid bytes that QImage can't load.
The Clean Solution: Extract Embedded JPEG with rawpy
The simplest and most reliable way to get the embedded JPEG from a NEF is using rawpy's built-in methods, which handle the NEF structure correctly across different Nikon cameras. Here's a working implementation:
import rawpy from PyQt5 import QtGui # Or PyQt6, adjust imports accordingly def load_nef_embedded_preview(nef_file_path): with rawpy.imread(nef_file_path) as raw: # Check if the NEF contains an embedded JPEG preview if raw.has_jpeg: # Extract the raw JPEG byte data directly from the NEF jpeg_bytes = raw.extract_jpeg() # Load the JPEG bytes into a QImage without saving to disk q_image = QtGui.QImage.fromData(jpeg_bytes) if q_image.isNull(): print("Failed to load embedded JPEG from NEF") return None # Convert to QPixmap for easy display in PyQt widgets return QtGui.QPixmap.fromImage(q_image) else: print("This NEF file does not contain an embedded JPEG preview") return None # Example usage: preview_pixmap = load_nef_embedded_preview("your_photo.nef") if preview_pixmap: # Assign to a QLabel or other display widget # your_label.setPixmap(preview_pixmap.scaled(your_label.size(), Qt.KeepAspectRatio)) pass
Key Notes:
raw.has_jpeg: Always check this first—some NEF files (especially from older cameras) might not have an embedded JPEG preview.raw.extract_jpeg(): This pulls the full-size embedded preview (not the tiny thumbnail) directly as byte data, which is perfect forQImage.fromData().- No File Saving: The entire workflow stays in memory, so you don't need to write any temporary files to disk.
Fixing Your Raw Processing Code (If You Need Full RAW Conversion)
If you ever need to process the actual RAW data instead of using the embedded preview, here's how to fix your first snippet to work with QImage:
import rawpy import numpy as np from PyQt5 import QtGui with rawpy.imread(nef_file_path) as raw: # Process RAW to 8-bit RGB (output_bps=8 ensures 0-255 range) rgb_data = raw.postprocess(output_bps=8) height, width, _ = rgb_data.shape # Create QImage from the numpy array—ensure contiguous memory and correct format q_image = QtGui.QImage( rgb_data.data, width, height, width * 3, # Bytes per line (3 bytes per pixel for RGB888) QtGui.QImage.Format_RGB888 ) # Make a copy to avoid memory issues with the numpy array being garbage collected q_image = q_image.copy() preview_pixmap = QtGui.QPixmap.fromImage(q_image)
This converts the RAW data to a displayable image, but it's slower than extracting the embedded JPEG since it processes the full sensor data.
内容的提问来源于stack exchange,提问作者ziarra

