For an image site, copyright isn't a "bonus feature" — it's a matter of life and death.
When an image is plagiarized, the original author has to prove "this is mine," the platform has to prove "we handled this," and a third party has to be able to check "can this image be used?" These three things together form a copyright system: certification (prove whose it is), tracing (find out where the image came from), and licensing (say clearly whether it can be used). This article takes all three apart, from start to finish.
And you'll find this copyright system isn't an isolated feature — it interlocks with the pieces covered in earlier articles: the blind watermark embedded at upload (a18's article), the ownership relationship of images, the identity of logged-in users — all are copyright's bedrock. Copyright isn't a shell added at the end; it's a web woven from the moment an image enters the site.
The first step of the copyright system isn't on the copyright-registration page — it's at the moment of upload. Recalling a18's article, after every image upload, the backend embeds a blind watermark while processing on COS:
// image processing at upload confirm: WebP conversion + blind watermark + thumbnail
String watermarkText = "@" + loginUser.getUserName() + " | yuemutuku.com";
cosManager.processUploadedImage(req.getCosKey(), watermarkText, quality);
That watermark reads "@username | yuemutuku.com" — invisible to the eye, but extractable by a program. It means: every image that leaves this site carries its owner's signature. When plagiarism is discovered later, extracting the blind watermark reveals "which user uploaded this image."
Why is the blind watermark the first step of the copyright system? Because a copyright claim has a hard precondition: you have to be able to prove "I uploaded this image first." The blind watermark plants an ownership marker the moment the image enters the system, making "who originally uploaded this image" traceable. Without this step, copyright registration becomes "talking without evidence" — you register "this is mine," but you can't produce proof the image is yours. The blind watermark is the seed of that proof.
More cleverly, this watermark is fully automatic — the user does nothing at upload; the backend silently embeds it. The most effective link of a copyright system is often the one users never perceive — it doesn't bother users, yet it lays the foundation for the whole system.
Where does the watermark's "blindness" come from? Unlike a traditional watermark that sits on top of the image (the kind you can crop away), it's embedded into the image's pixel data — specifically, it exploits the fact that the human eye is insensitive to certain frequency-domain details, "hiding" the information inside the image. Ordinary cropping, compression and format conversion can't touch it, because it's mixed in with the pixels themselves. The blind watermark's "invisibility" is exactly its "removability resistance" — it wants you not to notice it exists, until the moment it needs to be extracted.
Extracting the watermark is also a COS capability — embed it at upload, extract it later with the corresponding API. This "embed + extract" symmetry makes the watermark a complete reversible process: any image can have its originally-embedded "@username | sitename" extracted, locating the original uploader. The blind watermark's essence is giving every image an "invisible ID number" — invisible normally, checkable at will when needed.
Why use the username instead of an image ID? Because the username is a stable, human-facing identifier — extract the watermark, see "@OldWang," and you immediately know who it is without looking anything up. In an evidence chain, identifiers closer to human language are more usable — you extract the watermark to trace to a person, so put the person directly into the watermark.
I want to stress the positional difference between the blind watermark and a traditional watermark. A traditional watermark (a semi-transparent logo stamped on the image) exists to "prevent theft" — but someone truly determined to steal can crop it off. A blind watermark exists to "prove theft" — you can't remove it, and extracting it is evidence. One guards against the "gentlemen," one guards against the "deniers." For an image site, the blind watermark's value isn't in interception, it's in evidence — it turns "this image is mine" from "I say so" into "it says so." That's also why the watermark must interlock with copyright registration: the watermark is evidence, the registration is the claim, and only the two together form a complete copyright claim.
The blind watermark solves "who uploaded the image," but "uploaded" isn't "owns." A user might upload an image they took, or... well, to formally claim copyright, you have to go through "registration." The backend's registerCopyright does the certification:
public Long registerCopyright(CopyrightRegisterRequest registerRequest, HttpServletRequest request) {
// parameter validation
Long pictureId = registerRequest.getPictureId();
ThrowUtils.throwIf(pictureId == null || pictureId <= 0, ErrorCode.PARAMS_ERROR, "Image ID cannot be empty");
String copyrightOwner = registerRequest.getCopyrightOwner();
ThrowUtils.throwIf(StringUtils.isBlank(copyrightOwner), ErrorCode.PARAMS_ERROR, "Copyright owner name cannot be empty");
// verify the image exists and belongs to the current user
Picture picture = pictureMapper.selectById(pictureId);
ThrowUtils.throwIf(picture == null, ErrorCode.NOT_FOUND_ERROR, "Image not found");
ThrowUtils.throwIf(!picture.getUserId().equals(loginUser.getId()), ErrorCode.NO_AUTH_ERROR, "You can only apply for copyright on your own images");
// check whether copyright has already been registered
PictureCopyright existCopyright = copyrightMapper.selectOne(
new QueryWrapper<PictureCopyright>().eq("pictureId", pictureId));
ThrowUtils.throwIf(existCopyright != null, ErrorCode.OPERATION_ERROR, "This image already has registered copyright");
// generate the copyright trace code
String copyrightCode = generateCopyrightCode(pictureId, loginUser.getId());
// create the copyright record
PictureCopyright copyright = new PictureCopyright();
copyright.setPictureId(pictureId);
copyright.setUserId(loginUser.getId());
copyright.setCopyrightCode(copyrightCode);
copyright.setCopyrightOwner(copyrightOwner);
copyright.setCopyrightDesc(registerRequest.getCopyrightDesc());
copyright.setAllowCommercial(registerRequest.getAllowCommercial() != null ? registerRequest.getAllowCommercial() : 0);
copyright.setRequireAttribution(registerRequest.getRequireAttribution() != null ? registerRequest.getRequireAttribution() : 1);
copyright.setTraceCount(0L);
copyrightMapper.insert(copyright);
return copyright.getId();
}
The core of certification is three checks, all indispensable:
First: the image must exist. Applying for copyright on a nonexistent image ID is rejected outright. Second: the image must be yours. picture.getUserId().equals(loginUser.getId()) — you can't apply for copyright on someone else's image; that's the foundation of a copyright claim: "the person claiming the right must be the rights holder." Third: an image can only be registered once. The "one image, one certificate" principle of copyright registration — the same image can't have multiple copyright records, or a third party tracing it wouldn't know which to trust.
These three checks turn "certification" from "filling a form" into "a claim with a basis": the image is yours, it hasn't been registered by someone else, and you declare yourself the owner. Every check answers "why you."
Certification also asks the user to fill in some "declaration" fields: copyrightOwner (the owner's name), copyrightDesc (the copyright description), plus the licensing options covered later. copyrightOwner is required — a copyright claim needs "who is claiming" as its subject; without even the owner filled in, the registration is empty. copyrightDesc is supplementary — users can write "this image was photographed by me" or "this is my original design" to make the registration more complete.
The frontend CopyrightRegisterPage.vue mirrors these fields: owner input, copyright description, commercial option, attribution option, plus an "edit mode" (isEditMode) — an already-registered image can have its licensing modified. A detail here: the page first calls getCopyrightByPictureId to check whether this image has been registered; if yes, it enters edit mode; if no, new-registration mode. The frontend and backend agree on "whether it's already registered" — the backend uses pictureId deduplication to block duplicate registration, the frontend uses the same interface to decide whether to show edit or create.

The certification endpoint also carries a rate limit: 10 per user per minute, 100 per hour (BucketRateLimit). Why rate-limit registration too? Because copyright registration is a "low-frequency, high-value" operation — a normal user registers a few images a day at most, but a script can batch-register copyright on every image, making noise and wasting storage. Limiting to "10 per minute" is imperceptible to normal users and a hard constraint on scripts. Any "high-value, low-frequency" operation deserves a rate limit — it doesn't block legitimate users, it only blocks abuse.
One more detail: once copyrightCode is generated at registration, can the user change it? No — the trace code is a system-generated unique identifier, not a user-customizable field. Why? Because the trace code must guarantee "globally unique + unforgeable," and user customization breaks both properties. System-generated identifiers are managed by the system — users can only manage "declarations" (owner, licensing), not "numbers" (the trace code).
One easily-ignored field in the certification record: userId — the account that owns the copyright record. It differs from copyrightOwner (the registered signature): userId is the system's account ID, copyrightOwner is the name the user declares to the outside. One governs "who the system recognizes," the other "who displays to the outside"; storing them separately both prevents "I registered someone else's name" (the system recognizes the logged-in account) and lets users display whatever signature they like. Separating "system identity" from "public identity" is a detail many systems would do well to borrow.
After certification, the image gets a unique "copyright certificate number" — the trace code:
public String generateCopyrightCode(Long pictureId, Long userId) {
String year = String.valueOf(LocalDate.now().getYear()); // registration year
String pictureSuffix = String.format("%04d", pictureId % 10000); // last 4 digits of the image ID
String randomPart = IdUtil.randomUUID().substring(0, 8).toUpperCase(); // 8 random chars
return String.format("CR-%s-%s-%s", year, pictureSuffix, randomPart);
}
The trace code looks like: CR-2026-0123-A1B2C3D4. Four segments, each with a meaning: CR is the Copyright marker; 2026 is the registration year; 0123 is the last 4 digits of the image ID (for rough association); A1B2C3D4 is 8 random uppercase characters (for uniqueness).
The encoding design has a clever balance: readability and uniqueness together. The first two segments let anyone see at a glance "this is a copyright registered in 2026," while the last two make near-collision impossible worldwide. A purely random code is more secure, but users have to hand-type the trace code — CR-2026-... with semantic meaning is easier to type and remember than a long string of gibberish. The trace code is for users, so it needs "human flavor," not just a random string for machines.
An easily-overlooked consideration: it has to resist guessing and enumeration. If the code were too short or too regular (say, a sequential counter), someone could sweep through a batch of copyright records by incrementing; the 8-character random segment blocks "following the trail" — you can query a known code, but you can't guess the next one. That's the balance between "readability" and "unguessability": users can enter it, hackers can't enumerate it.
traceCount starts at 0 and increments on every trace. It's not just a counter — it's a "work-gets-attention" signal: an image queried many times means it's been reposted and referenced a lot out in the wild; seeing that number, the rights holder realizes "my work is popular, but also more likely to be stolen." Letting rights holders see their work's "attention level" is a thoughtful touch in the copyright system — it turns passive records into valuable feedback for creators.
A frontend detail: after successful registration, the trace code is shown on the image detail page — users can see their certificate number and copy it for others. This "visible certificate number" turns copyright from backend data into something users can show off and spread, incidentally promoting the trace code itself. Making system-generated identifiers "visible, copyable, spreadable" is a key step for many features going from "usable" to "actually used."
Uniqueness is guaranteed by "last 4 digits of image ID + 8 random characters": the same image can only be registered once (deduplicated earlier), the image ID's last 4 digits separate different images, and 8 random characters rarely repeat within the same year. Even in an extreme collision, traceCopyright only takes the latest one if the query hits multiple — that "fallback when codes collide" is covered later.
Once generated, the trace code's greatest value is that it can be queried by anyone — that's tracing. traceCopyright requires no login; anyone entering a trace code can find the image's copyright ownership:
public CopyrightInfoVO traceCopyright(CopyrightTraceRequest traceRequest, HttpServletRequest request) {
// query the copyright info by trace code
PictureCopyright copyright = copyrightMapper.selectOne(
new QueryWrapper<PictureCopyright>().eq("copyrightCode", traceRequest.getCopyrightCode()));
ThrowUtils.throwIf(copyright == null, ErrorCode.NOT_FOUND_ERROR, "No matching copyright information found");
// record the trace query
PictureCopyrightTrace trace = new PictureCopyrightTrace();
trace.setCopyrightId(copyright.getId());
trace.setPictureId(copyright.getPictureId());
trace.setCopyrightCode(copyrightCode);
// record who queried (may not be logged in)
try {
User loginUser = userService.getLoginUser(request);
if (loginUser != null) trace.setTraceUserId(loginUser.getId());
} catch (Exception e) { /* unauthenticated users can query too */ }
// record the query IP and time
trace.setTraceIp(ServletUtils.getClientIP(request));
trace.setTraceTime(new Date());
traceMapper.insert(trace);
// increment the trace count
copyright.setTraceCount(copyright.getTraceCount() + 1);
copyrightMapper.updateById(copyright);
// return copyright info + image info
CopyrightInfoVO vo = new CopyrightInfoVO();
BeanUtils.copyProperties(copyright, vo);
Picture picture = pictureMapper.selectById(copyright.getPictureId());
if (picture != null) {
vo.setPictureUrl(picture.getUrl());
vo.setPictureName(picture.getName());
}
return vo;
}
Tracing being open to everyone is the soul of the copyright system — copyright has value only when it can be verified by a third party. An image hung elsewhere; the other party sees the trace code, enters it, finds "copyright owner is X, commercial use prohibited," and knows not to use it; finds "commercial use allowed but attribution required," and knows to use it with credit. The trace code turns copyright from "self-declaration" into "publicly verifiable fact."
Note traceCount — it increments on every trace. That number is an "attention signal": an image's copyright queried many times means it's been reposted/referenced a lot, worth the rights holder's attention. Trace-query count is an underrated ops metric in the copyright system — it tells you "how much exposure this image has out there."
The trace endpoint's openness brings a design trade-off: querying copyright requires no login, meaning anyone can get part of the copyright info (owner, licensing, image). That's the inevitable cost of "publicly verifiable" — for copyright to be verified by third parties, it has to be public enough for anyone to query. The key is only exposing "what should be public," never leaking "what shouldn't": CopyrightInfoVO returns the "public info" — owner, licensing, image — not the user ID, IP, or internal fields. Field trimming on an open endpoint is the balance between privacy and transparency — make what should be public transparent, and what should be private invisible.
CopyrightInfoVO returns not just the copyright record but also the image itself — image URL, image name. Why return the image for a trace? Because the querier (a third party) entering a trace code wants to confirm "which image does this code correspond to"; without the image, only a text description, it's not clear. A trace result must be "illustrated" — code right and image right, then the querier has confidence "it's this one."
And that fallback detail: when selectOne hits multiple records on a code collision, the system must tolerate it — it can't let "theoretically won't collide" crash the whole query. That's also why the code generation piles on random segments and the dedup guarantees uniqueness: uniqueness isn't just design aesthetics, it's the precondition for query-logic correctness. A uniqueness guaranteed by constraints is better than one left to query-time luck.
More important than "getting the result" is that every query is recorded. PictureCopyrightTrace records each trace: who queried (traceUserId), from where (traceIp), and when (traceTime).
Why record even the queries? Two uses. Security-side — if someone repeatedly queries the same trace code (say, checking whether they can get away with stealing), the IP gets recorded, and abnormal query patterns become traceable; ops-side — trace records are the trail of "who has been paying attention to this image," and paired with traceCount, rights holders can see their work's "attention map."
A detail here: the trace endpoint works without login, but records the user ID if logged in. The try-catch wraps getLoginUser, because it throws when unauthenticated — catch it, leave the user ID blank, and the query proceeds. That's the balance between "permission" and "openness": querying copyright is a public right, but the querier's identity is kept on record where possible. Open what can be open, keep traces of what can be traced — the design principle for audit-type features.
Let me expand one layer: why record traceIp? Besides security aggregation, it has an "evidence" value — if a real copyright dispute arises later and you need to prove "this trace code was queried at this time, from this IP," the trace record is ready-made evidence. Though a single IP can't pinpoint a real person, paired with the logged-in user ID (the traceUserId recorded at login), you can piece together "who queried this image's copyright." Design audit records imagining "we'll be in court one day" — one more field now, one less awkwardness later.
One more detail: trace records and copyright info are stored in two separate tables (PictureCopyright and PictureCopyrightTrace) — copyright is "state" (one per image), tracing is "flow" (one per query). Separating state and flow is the standard practice of audit systems: state changes (licensing can be modified), flow only appends (once queried is once queried). Store mutable state and immutable flow separately, and both query and audit stay clean.
One more detail on the flow table: PictureCopyrightTrace's fields — copyrightId (which copyright it corresponds to), copyrightCode (the code at the time), traceUserId (who queried), traceIp (from where), traceTime (when). It freezes "which copyright was queried by whom, from where, when." Note it records the copyrightCode snapshot rather than a foreign-key reference — even if the code ever changed (it won't), this record keeps the code as it was at query time. A flow table records "the snapshot at the time," not "the current reference" — that's what immutable flow should look like.
The traceIp also has an aggregation-analysis scenario: if "a certain IP queried a pile of different trace codes in a short time," that could be a crawler batch-collecting copyright info, or someone studying how to circumvent copyright. Aggregating trace records by IP can surface such patterns — the same idea as the IP aggregation of login records in a23's article. Audit data is dead water one record at a time; aggregated, it reveals flowing attack patterns.
And a product-level detail: the trace endpoint is rate-limited by IP (20 per IP per minute), but normal users never notice — a normal user querying copyright 20 times in a minute? Nearly impossible. This limit isn't for users, it's to block scripts. Rate limiting targets attackers, not users — when designing a limit, make sure "a normal user can never reach this volume," and then you can limit with peace of mind.
The tracing frontend, CopyrightTracePage.vue, is designed with a sense of ceremony — enter a trace code, verification passes, and a "digital pass" card appears:
<div v-if="copyrightInfo" class="digital-pass-card">
<div class="pass-id">{{ copyrightInfo.copyrightCode }}</div>
<div class="auth-stamp">Verified</div>
<img :src="copyrightInfo.pictureUrl" :alt="copyrightInfo.pictureName" class="asset-cover" />
<h4 class="asset-name">{{ copyrightInfo.pictureName }}</h4>
<!-- copyright owner, licensing terms -->
</div>
A card with a "Verified" stamp, carrying the trace code, image thumbnail, copyright owner and licensing terms. This design isn't just "displaying a result" — it conveys a ceremony of "trust": copyright verification needs the querier to feel "this is an authoritative result", and a formal pass card is far more persuasive than a line of plain text.
The input also has a clear button shown with v-show="copyrightCode" and the search button disabled when empty — standard form interactions, but all done properly. The completeness of frontend experience often lives in these "corner interactions" — whether empty input can submit, when the clear button shows — users don't say it, but they notice.
There's also a "query failure" experience: if the user mistypes a trace code and the backend returns "no matching copyright information found," how does the frontend present it? The ideal is keeping the input and giving a clear "no such certificate" message, rather than clearing it or erroring. The failure state of a verification feature should tell the user "is the code wrong or not found" — a clear failure feedback matters more than success, because it decides whether the user retypes or gives up.
And that "Verified" stamp on the digital pass (the auth-stamp) — a CSS-made red seal visual. It's pure decoration, but it carries "authority": the seal is the visual language of certificates, and seeing a seal makes people feel "this is officially verified." Visual language's suggestive power is especially valuable in trust-sensitive scenarios — copyright verification wants the querier to feel "trustworthy," and one seal beats a hundred lines of explanation.
Copyright registration isn't just "prove it's mine" — it also has to say "can others use it, and how." Two fields in PictureCopyright do exactly that:
private Integer allowCommercial; // commercial use allowed? (1=yes, 0=no)
private Integer requireAttribution; // attribution required? (1=yes, 0=no)
These two fields combine into a simple licensing agreement: the four combinations of allowCommercial + requireAttribution — commercial allowed and attribution required, commercial allowed without attribution, commercial prohibited with attribution, commercial prohibited without attribution (rare but possible). It's simpler than CC, but captures the two core dimensions of licensing: can you profit from it, and do you have to leave a credit.
At registration, the user checks these two options, and third parties can see the licensing terms when tracing. Copyright and licensing are two sides of one coin — merely claiming "it's mine" isn't enough; you also have to say "what happens if you use it," so third parties can decide whether to use it. A copyright registration without licensing terms is like a contract without the payment clause — a formality.
These two fields are, in fact, the embryo of a miniature CC license. CC (covered in a1's article) has the BY/NC/SA/ND dimensions; here it's distilled to two core dimensions: can it be used commercially (the essence of NC) + is attribution required (the essence of BY). The four combinations cover the most common licensing needs: fully open, attribution-only, commercial-prohibited, strictest. For a small site, two dimensions are far easier for users to grasp than CC's six licenses — a licensing model isn't better the more complex it is; it's better the more it matches users' mental models.
A default-value detail: allowCommercial defaults to 0 (commercial prohibited), requireAttribution defaults to 1 (attribution required) — that is, "strictest by default." Why the conservative default? Because copyright is "better strict than loose" — if commercial use is allowed by default and a third party uses it commercially, it's too late to change your mind; if prohibited by default, the licensor can relax it anytime (via edit mode). In copyright scenarios, defaults should favor protecting the rights holder, leaving the power to "relax" for the holder to exercise deliberately.
String this article together with a18's, and you'll see the copyright system is a complete chain:
User uploads an image
→ backend auto-embeds a blind watermark (@username | sitename) ← covered in a18
→ image enters the database, ownership recorded
→ user applies for copyright registration (must be theirs + one image one certificate)
→ a trace code CR-2026-xxxx-xxxxxxxx is generated
→ anyone entering the trace code can trace (ownership + licensing)
→ every trace leaves an IP / user / time record
Every link depends on the one before it: the blind watermark plants evidence for "who uploaded the image," registration upgrades "uploaded" into "claimed," the trace code makes the claim publicly verifiable, and trace records make the verification process trackable. Missing any link, and the copyright system breaks — no blind watermark, registration is empty talk; no registration, no code to trace; no trace records, queriers come and go without a trace.
The design philosophy worth calling out: copyright isn't a "registration feature" — it's an evidence chain running through an image's entire lifecycle. From the moment the image enters the site to the moment a third party queries it, every step accumulates evidence for "whose image is this, can it be used." No single link is hard; what's hard is weaving them into a web.
A coupling easy to overlook in this web: copyright registration depends on the upload chain's watermark, and the watermark depends on the user identity system. Without logged-in identity, the watermark has nothing to embed; without the watermark, the copyright registration loses half its evidence; without registration, the trace code has no source. That's why this article is written after a18 (upload) and a23 (login) — copyright isn't an independent feature; it stands on the foundations built by the systems before it. A system's value often lies not in itself, but in its interlock with other systems.
More beautifully, this loop keeps reinforcing itself: image registered → has a trace code → queried by third parties → traceCount rises → rights holder sees the attention → more willing to register more. Each additional link that gets used adds another layer of value to the whole chain. People building systems often stare at single features, but what truly grows into an ecosystem is design where "links feed each other."
This loop also has outward value: it makes third parties "dare to use" the site's images. A creator wanting to illustrate an article sees copyright info beside an image, clicks into the trace page — owner, licensing terms, all clear. Can use it? Use it with confidence. Can't? Pick another. The copyright system turns "uncertain fear" into "certain judgment" — positive for the flow of content on the site, because clear copyright actually encourages compliant use.
Back to the tech itself: this system uses nothing but "ordinary" tech — COS image processing, MySQL tables, an endpoint, a page. But interlock it with upload, login, rate-limiting and audit infrastructure, and it becomes a "copyright moat." An architecture's value always lives in its interlocking joints — individual parts are cheap; assembled systems are valuable.
This copyright chain has its share of potholes. The most memorable:
Pothole 1: The dedup used the wrong field. Initially "already registered" was checked by the image ID's camel-case name, and MyBatis's automatic mapping didn't align with the database's underscore field, letting "the same image register multiple times." Standardizing on eq("pictureId", pictureId) and confirming the mapping fixed it. ORM field mapping is where "looks simple" hides the most dangerous flip-overs — one wrong camel-to-underscore conversion is data chaos.
Pothole 2: Code collision had no fallback. CR-year-image-4digits-8random is theoretically nearly collision-free, but if it did collide, selectOne would throw a "multiple records" error. Later, on hitting multiple results, the latest by time is taken, avoiding a query crash. When generating unique codes, have a "what if they collide" fallback — don't bet on "won't collide."
Pothole 3: Unauthenticated tracing made the endpoint error. Initially getLoginUser threw when unauthenticated, making the whole trace endpoint 500. Wrapping it in try-catch let unauthenticated users query too (just without the user ID). An open endpoint can't fail because of "optional identity info" — identity trace-keeping is a bonus ability; the query itself must be unconditionally available.
Pothole 4: The trace-record table got hammered. Someone wrote a script repeatedly querying trace codes, each record inserting into the DB, the table ballooning. Adding IP rate-limiting to the trace endpoint (20 per IP per minute) blocked the scripts. Audit endpoints need protection themselves — they can keep traces, but the tracing itself can't become an attack entry.
Pothole 5: Copyright registration had no frequency limit. Initially the registration endpoint was unlimited — one image one certificate blocked duplicates, but a user could batch-register across many images, flooding copyright records. Adding per-user rate-limiting (10/min, 100/hour) fixed it. Even "legitimate features" need abuse protection — batch-flooding copyright records is harmless but wastes storage and makes noise.
Pothole 6: The blind watermark was mistaken for a "removable watermark." Some thought that since the watermark is "blind," it could be washed off. In fact "blind" means invisible to the eye; it's embedded in the pixel frequency domain, and ordinary cropping, compression and format conversion can't remove it. This misconception is common, so the product copy explicitly explains "the blind watermark cannot be removed." Technical details should be translated into expectations users can understand, so users don't form unrealistic hopes or fears about copyright protection.
Pothole 7: Image deleted, copyright record became an orphan. After a user registered copyright and deleted the original image, the copyright record still hung around — tracing could find the copyright info, but the image was gone and showed a broken image. Later, a fallback was added for a missing image at trace time (if no image found, return only the copyright info, don't show the image). Associated data needs a "what if the other side is gone" fallback — copyright records are weakly linked to images, the image can be deleted, and tracing must not crash along with it.
Pothole 8: The commercial option was mis-ticked. Allowing commercial use (allowCommercial=1) is a "broad license"; mis-ticking it would make third parties think it's free for commercial use. Later, a prominent hint was added on the registration page for the commercial option ("allowing commercial use = others may use it commercially"). Key options involving rights must state the consequences clearly — defaults can be conservative, but the choice must be given to users, and users must understand what they're choosing.
Pothole 9: The copyright-image link is a "reference," not a "hard constraint." After image deletion, the copyright record becomes an orphan (Pothole 7), but conversely, if some image fields change (say the owner renames), the copyrightOwner in the copyright record doesn't follow — it's a snapshot at registration. That's intentional (copyright claims follow the registration time), but it also means copyright info may not match the user's current state. The trade-off between snapshot and real-time must be stated at design time — if copyright is "by registration," accept that it doesn't sync in real time.
Collected together, you'll find: the copyright system isn't "register once" — it's an evidence web running through an image's entire journey, from upload to third-party query. The blind watermark plants ownership, registration gives the claim, the trace code enables verification, records leave traces, licensing defines the boundary — five links, all indispensable.
Three sentences summarize this article:
The blind watermark is copyright's foundation. An image gets its ownership marker automatically at upload, making "who uploaded this image" traceable — a copyright claim without it is empty talk.
The trace code makes copyright publicly verifiable. Anyone entering a code can find the ownership and licensing terms — copyright goes from "self-declaration" to "a fact verifiable by third parties," and only then has real constraint.
Every trace is remembered. IP, user, time, query count — audit records make the verification process trackable, and turn "who's paying attention to this image" into an analyzable signal.
When you get this far, the distance from "slogan" to "system" in copyright comes down to three questions: does attribution leave evidence? does every claim have a per-image credential? is there a public way to verify licensing? Answer all three, then interlock watermark, registration, trace code, records, and licensing — and copyright finally stops being a poster on the wall.