For a rotate image Python task, give the source pixels identities, declare the rotation settings, and verify a new saved file after reopening it. Keep the original file unchanged and distinguish an expanded result from a same-size crop.

This original packet uses a proposed opaque RGB PNG with width two and height three. No PNG, executable Python file, output, capture, or native run has been created. Pillow's 12.3.0 documentation is the reference; the installed version remains unknown.
Prepare six pixels you can track
Coordinates use an upper-left origin, with x across and y downward. The authored input is:
A B
C D
E F
| Pixel ID | Input coordinate (x, y) | RGB color |
|---|---|---|
| A | (0, 0) | Red, (255, 0, 0) |
| B | (1, 0) | Green, (0, 255, 0) |
| C | (0, 1) | Blue, (0, 0, 255) |
| D | (1, 1) | Yellow, (255, 255, 0) |
| E | (0, 2) | Magenta, (255, 0, 255) |
| F | (1, 2) | Cyan, (0, 255, 255) |
Each label denotes one distinct RGB tuple. The source manifest should record its actual path, PNG bytes/hash, size, mode, and every pixel after the fixture exists. Leave those actual fields blank now.
A magnified reading grid should display IDs and coordinates as well as colors. It is an explanation of the proposed image, not a screenshot of a file that has been loaded.
Declare angle, center and extent together
Pillow documents rotate as returning a rotated copy, with positive angles counterclockwise. Its expand option changes the output extent; the documented expansion assumes the default center and no translation. Pillow's rotate reference.
Use this bounded contract:
| Setting | Authored choice |
|---|---|
| Input | Static opaque RGB PNG, 2 × 3 |
| Angle cases | +90° and −90° |
| Center | Default image center |
| Translation | None |
| Resampler | NEAREST |
| Expanded cases | expand=True |
| Output format | New PNG files |
Do not extend the exact pixel-permutation expectations to arbitrary angles, a nondefault center, translation, EXIF orientation, animation, or a lossy JPEG output.
Check the +90° result
With +90°, expand=True, default center, and no translation, expect width three and height two:
B D F
A C E
For this quarter-turn, the authored coordinate mapping is:
x' = y; y' = width − 1 − x.
With input width two, A at (0,0) maps to (0,1), B at (1,0) to (0,0), and F at (1,2) to (2,0). The other three pixels follow the same mapping.
Keep that mapping beside the expected matrix so “counterclockwise” is more than a visual guess. The expected first row is green, yellow, cyan; the second is red, blue, magenta.
Check the −90° result independently
With −90° and the same other settings, expect:
E C A
F D B
The authored clockwise mapping is:
x' = height − 1 − y; y' = x.
With input height three, A maps to (2,0), E to (0,0), and F to (0,1). The expected first row is magenta, blue, red; the second is cyan, yellow, green.
These are exact expected permutations of the original six tuples. The matrices are independently authored and manually traced; they are not actual Pillow outputs.
Always derive each case from the original input. Do not feed the +90° output into the −90° case while labeling it as an independent clockwise rotation of the source.
Save to distinct new destinations and reopen
Pillow's save method writes the image to the supplied destination, with a format argument available. Use an explicit PNG contract here. Pillow's save reference.
Prepare this native source specification inside the manuscript:
from PIL import Image
with Image.open(source_path) as original:
original.load()
if original.mode != "RGB" or original.size != (2, 3):
raise ValueError("Input does not match the authored fixture")
positive = original.rotate(
90, resample=Image.Resampling.NEAREST, expand=True
)
negative = original.rotate(
-90, resample=Image.Resampling.NEAREST, expand=True
)
positive.save(positive_output_path, format="PNG")
negative.save(negative_output_path, format="PNG")
All three paths are unresolved implementation inputs. Before eventual writing, validate that the output paths are new, distinct destinations and do not resolve to the source or an existing artifact selected by accident. Record the source hash before and after the operation.
Then reopen each output and inspect decoded pixels:
def pixel_record(path):
with Image.open(path) as image:
image.load()
rows = [
[image.getpixel((x, y)) for x in range(image.width)]
for y in range(image.height)
]
return image.format, image.mode, image.size, rows
This is a source specification, not an executed save or inspection. The acceptance test needs actual reopened format PNG, mode RGB, size (3,2), and all six expected tuples in the correct positions.
Decoded pixel equality is different from encoded-file byte equality. Record new output hashes for provenance, but do not require them to equal the source hash. The source byte hash should remain unchanged because the authored workflow writes new destinations.
Treat expand=False as a different case
With expand omitted or False, Pillow documents output size equal to input size. For this input, that means (2,3).
Do not conclude that a same-size output retains all six pixels or that it is the expanded matrix squeezed into a smaller frame. The exact cropped placement and fill behavior need actual native observations.
Keep the cropped matrix pending rather than guessing it. A readout of (2,3) establishes the extent check only; it does not answer which pixels survived.
Keep expected and actual records separate
| Case | Expected extent | Expected pixel record | Actual observation |
|---|---|---|---|
| Input | Width 2, height 3; RGB | AB / CD / EF | |
| +90 expanded | Width 3, height 2; RGB | BDF / ACE | |
| −90 expanded | Width 3, height 2; RGB | ECA / FDB | |
| +90 same extent | Width 2, height 3 | Cropped/fill matrix pending | |
| Source after new-file writes | Same original bytes | Hash unchanged |
Record actual Python/Pillow version, source hash, settings, output paths/hashes, and reopened observations. Missing or mismatched source pixels hold the fixture; they are not permission to reinterpret the expected matrices.
Changed input bytes, angle, resampler, center, translation, expansion, format, or runtime require fresh acceptance. Preserve historical cases under their original configuration.
Later review the original magnified grid and saved/reopened results at the actual article width and in a narrow container. Keep coordinates readable and avoid color-only explanations. No visual comparison or native tests have passed yet.
Copy this prompt for the rotation packet
Create one complete, self-contained US-English HTML companion for “Quarter-turn pixel workbench”. Return the full HTML document, with inline CSS and any JavaScript needed for the local interactions. Use the original scenario, named records, numbers and expected cases below.
Design the page for this task: use clearly labeled input or source records, a readable result or worked example, and an adjacent explanation of the evidence. Use a restrained visual hierarchy, left-aligned text, readable tables or stacked records, and a responsive layout at 720px and 360px. Provide meaningful labeled controls for +90° · counterclockwise; −90° · clockwise; +90° · same extent; Compare supplied record; Select text. Use keyboard-accessible native controls and visible focus. Keep the complete content readable without an external dependency.
The following brief supplies the substantive content and constraints. Native-format requests describe the material to represent or copy manually; this HTML must not pretend to create DOCX, XLSX, PDF, PPTX, H5P or another native file, run Python/Flask/Django/Snowflake/Power BI, connect a live service, send messages, or perform an authorized real-world action. Where the task requires a native source, actual observation or separate approval, retain that requirement and leave unsupplied evidence blank.
Prepare an original English raster-rotation authoring packet. Do not create PNG/Python files, rotate/save images, execute code,
copy source sample imagery, capture screens, or publish. Pillow 12.3.0 documentation is a reference, not installed/latest proof.
Proposed source: opaque static RGB PNG, width 2, height 3. Top-to-bottom ID rows: A B / C D / E F. A=(255,0,0), B=(0,255,0), C=(0,0,255),
D=(255,255,0), E=(255,0,255), F=(0,255,255). Record actual source path/bytes/hash/size/mode/pixels later; blank now.
Default center, no translation, NEAREST resampler. Independent cases each start from the original:
+90 degrees, expand=True -> width 3, height 2; B D F / A C E. Mapping x' = y, y' = width - 1 - x.
-90 degrees, expand=True -> width 3, height 2; E C A / F D B. Mapping x' = height - 1 - y, y' = x. Matrices are authored expectations, not native observed output.
Prepare source specifications inside the manuscript for rotate and
explicit PNG save, then reopen and inspect format/mode/size/every pixel. Actual output paths must be new/distinct and not resolve to source. No overwriting an existing artifact by accident. Check source hash before/after remains unchanged. Record new output hashes, not equality with source encoded bytes. Decoded-pixel equality differs from file-byte equality.
Separate expand=False/omitted case:
Expected size stays width 2, height 3. Exact crop/fill matrix pending actual native inspection. Do not guess retention of all pixels.
Deliver native input/settings/coordinate ledger, expected matrices,
source/save/reopen specifications and blank actual observations. Invalid/missing source or changed bytes/settings/runtime require fresh
acceptance, not reused proof. No arbitrary-angle, EXIF, animation, nondefault center/translation or
lossy output support inferred from this quarter-turn opaque PNG fixture. Plan actual pixel/source-preservation/save/reopen/visual/article-width/
narrow checks; all native/runtime/visual results pending.
Native raster files/Python/pixel records
remain authoritative. NOS does not execute Pillow or rotate file bytes.
COMPLETE AUTHORED SCENARIO AND EXPECTED CASES
The following is the supplied reading/teaching/calculation record to represent in the companion. Preserve its particular content, examples, source references and unknowns. Wording about a future native implementation refers to that native task, not permission to omit this HTML companion.
# Rotate Image Python: Verify the Saved Pixel Grid
The preview looks rotated, but the saved file has the original dimensions and clips part of the image. Another attempt turns it clockwise when you expected counterclockwise. A browser display can conceal both mistakes.
For a rotate image Python task, give the source pixels identities, declare the rotation settings, and verify a new saved file after reopening it. Keep the original file unchanged and distinguish an expanded result from a same-size crop.
This original packet uses a proposed opaque RGB PNG with width two and height three. No PNG, executable Python file, output, capture, or native run has been created. Pillow's 12.3.0 documentation is the reference; the installed version remains unknown.
## Prepare six pixels you can track
Coordinates use an upper-left origin, with x across and y downward. The authored input is:
A B
C D
E F
| Pixel ID | Input coordinate (x, y) | RGB color |
| --- | --- | --- |
| A | (0, 0) | Red, (255, 0, 0) |
| B | (1, 0) | Green, (0, 255, 0) |
| C | (0, 1) | Blue, (0, 0, 255) |
| D | (1, 1) | Yellow, (255, 255, 0) |
| E | (0, 2) | Magenta, (255, 0, 255) |
| F | (1, 2) | Cyan, (0, 255, 255) |
Each label denotes one distinct RGB tuple. The source manifest should record its actual path, PNG bytes/hash, size, mode, and every pixel after the fixture exists. Leave those actual fields blank now.
A magnified reading grid should display IDs and coordinates as well as colors. It is an explanation of the proposed image, not a screenshot of a file that has been loaded.
## Declare angle, center and extent together
Pillow documents rotate as returning a rotated copy, with positive angles counterclockwise. Its expand option changes the output extent; the documented expansion assumes the default center and no translation. [Pillow's rotate reference](https://pillow.readthedocs.io/en/stable/reference/Image.html).
Use this bounded contract:
| Setting | Authored choice |
| --- | --- |
| Input | Static opaque RGB PNG, 2 × 3 |
| Angle cases | +90° and −90° |
| Center | Default image center |
| Translation | None |
| Resampler | NEAREST |
| Expanded cases | expand=True |
| Output format | New PNG files |
Do not extend the exact pixel-permutation expectations to arbitrary angles, a nondefault center, translation, EXIF orientation, animation, or a lossy JPEG output.
## Check the +90° result
With +90°, expand=True, default center, and no translation, expect width three and height two:
B D F
A C E
For this quarter-turn, the authored coordinate mapping is:
**x' = y; y' = width − 1 − x.**
With input width two, A at (0,0) maps to (0,1), B at (1,0) to (0,0), and F at (1,2) to (2,0). The other three pixels follow the same mapping.
Keep that mapping beside the expected matrix so “counterclockwise” is more than a visual guess. The expected first row is green, yellow, cyan; the second is red, blue, magenta.
## Check the −90° result independently
With −90° and the same other settings, expect:
E C A
F D B
The authored clockwise mapping is:
**x' = height − 1 − y; y' = x.**
With input height three, A maps to (2,0), E to (0,0), and F to (0,1). The expected first row is magenta, blue, red; the second is cyan, yellow, green.
These are exact expected permutations of the original six tuples. The matrices are independently authored and manually traced; they are not actual Pillow outputs.
Always derive each case from the original input. Do not feed the +90° output into the −90° case while labeling it as an independent clockwise rotation of the source.
## Save to distinct new destinations and reopen
Pillow's save method writes the image to the supplied destination, with a format argument available. Use an explicit PNG contract here. [Pillow's save reference](https://pillow.readthedocs.io/en/stable/reference/Image.html).
Prepare this native source specification inside the manuscript:
from PIL import Image
with Image.open(source_path) as original:
original.load()
if original.mode != "RGB" or original.size != (2, 3):
raise ValueError("Input does not match the authored fixture")
positive = original.rotate(
90, resample=Image.Resampling.NEAREST, expand=True
)
negative = original.rotate(
-90, resample=Image.Resampling.NEAREST, expand=True
)
positive.save(positive_output_path, format="PNG")
negative.save(negative_output_path, format="PNG")
All three paths are unresolved implementation inputs. Before eventual writing, validate that the output paths are new, distinct destinations and do not resolve to the source or an existing artifact selected by accident. Record the source hash before and after the operation.
Then reopen each output and inspect decoded pixels:
def pixel_record(path):
with Image.open(path) as image:
image.load()
rows = [
[image.getpixel((x, y)) for x in range(image.width)]
for y in range(image.height)
]
return image.format, image.mode, image.size, rows
This is a source specification, not an executed save or inspection. The acceptance test needs actual reopened format PNG, mode RGB, size (3,2), and all six expected tuples in the correct positions.
Decoded pixel equality is different from encoded-file byte equality. Record new output hashes for provenance, but do not require them to equal the source hash. The source byte hash should remain unchanged because the authored workflow writes new destinations.
## Treat expand=False as a different case
With expand omitted or False, Pillow documents output size equal to input size. For this input, that means (2,3).
Do not conclude that a same-size output retains all six pixels or that it is the expanded matrix squeezed into a smaller frame. The exact cropped placement and fill behavior need actual native observations.
Keep the cropped matrix pending rather than guessing it. A readout of (2,3) establishes the extent check only; it does not answer which pixels survived.
## Keep expected and actual records separate
| Case | Expected extent | Expected pixel record | Actual observation |
| --- | --- | --- | --- |
| Input | Width 2, height 3; RGB | AB / CD / EF | |
| +90 expanded | Width 3, height 2; RGB | BDF / ACE | |
| −90 expanded | Width 3, height 2; RGB | ECA / FDB | |
| +90 same extent | Width 2, height 3 | Cropped/fill matrix pending | |
| Source after new-file writes | Same original bytes | Hash unchanged | |
Record actual Python/Pillow version, source hash, settings, output paths/hashes, and reopened observations. Missing or mismatched source pixels hold the fixture; they are not permission to reinterpret the expected matrices.
Changed input bytes, angle, resampler, center, translation, expansion, format, or runtime require fresh acceptance. Preserve historical cases under their original configuration.
Later review the original magnified grid and saved/reopened results at the actual article width and in a narrow container. Keep coordinates readable and avoid color-only explanations. No visual comparison or native tests have passed yet.
Implement the local companion rather than returning a text-only plan. Preserve every numerical fixture and the distinction between illustrative expectations and actual evidence. Any native-runtime or classroom tests mentioned above remain tests to perform in the proper environment; do not mark them passed. Keep edits and practice responses in this open page only, without claiming persistent storage. Provide invalid/missing-input feedback and reset behavior that agree with this specific brief. Do not claim accessibility certification, learning gains, real approvals or test results that were not observed.
Review the prepared pixel comparison
After native testing, a reading copy can place the source IDs, expected quarter-turn matrices, and actual reopened pixel records beside one another. Label the expanded and same-extent cases separately.
Native raster files, Python/Pillow settings, hashes, and decoded pixels remain authoritative. A rendered comparison or CSS rotation is not proof that a saved bitmap changed.
Give the reviewer the new extent and each reopened pixel, while preserving the original source.